copy homebuttonLib from oot-vc (#2960)

* initial copy of hbm from sdk_2009-12-11

* some more nw4hbm cleanup

* nw4hbm db mostly done

* nw4hbm snd copied from oot-vc

* nw4hbm ut copied

* nw4hbm lyt copied

* nw4hbm copied, mostly matching usa 1.0

* setup nw4hbm debug define

* fix HBMDataInfo struct

* add rvl sdk card lib
This commit is contained in:
TakaRikka 2025-12-16 06:55:07 -08:00 committed by GitHub
parent c8104b6d62
commit 8185d87f85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
235 changed files with 32438 additions and 320 deletions

View File

@ -2345,7 +2345,7 @@ revolution/gf/GFPixel.cpp:
revolution/gf/GFTev.cpp: revolution/gf/GFTev.cpp:
.text start:0x802B20AC end:0x802B210C .text start:0x802B20AC end:0x802B210C
revolution/hbm/HBMBase.cpp: revolution/homebuttonLib/HBMBase.cpp:
.text start:0x802B210C end:0x802BA91C .text start:0x802B210C end:0x802BA91C
.rodata start:0x803EF1C8 end:0x803EF478 .rodata start:0x803EF1C8 end:0x803EF478
.data start:0x804253D8 end:0x80426308 .data start:0x804253D8 end:0x80426308
@ -2354,125 +2354,125 @@ revolution/hbm/HBMBase.cpp:
.sbss start:0x8053B090 end:0x8053B098 .sbss start:0x8053B090 end:0x8053B098
.sdata2 start:0x8053FCD0 end:0x8053FD30 .sdata2 start:0x8053FCD0 end:0x8053FD30
revolution/hbm/HBMAnmController.cpp: revolution/homebuttonLib/HBMAnmController.cpp:
.text start:0x802BA91C end:0x802BAA3C .text start:0x802BA91C end:0x802BAA3C
.data start:0x80426308 end:0x80426318 .data start:0x80426308 end:0x80426318
revolution/hbm/HBMFrameController.cpp: revolution/homebuttonLib/HBMFrameController.cpp:
.text start:0x802BAA3C end:0x802BABDC .text start:0x802BAA3C end:0x802BABDC
.sdata2 start:0x8053FD30 end:0x8053FD38 .sdata2 start:0x8053FD30 end:0x8053FD38
revolution/hbm/HBMGUIManager.cpp: revolution/homebuttonLib/HBMGUIManager.cpp:
.text start:0x802BABDC end:0x802BC260 .text start:0x802BABDC end:0x802BC260
.data start:0x80426318 end:0x804264F8 .data start:0x80426318 end:0x804264F8
.sdata start:0x8053A118 end:0x8053A120 .sdata start:0x8053A118 end:0x8053A120
.sbss start:0x8053B098 end:0x8053B0A0 .sbss start:0x8053B098 end:0x8053B0A0
.sdata2 start:0x8053FD38 end:0x8053FD48 .sdata2 start:0x8053FD38 end:0x8053FD48
revolution/hbm/HBMController.cpp: revolution/homebuttonLib/HBMController.cpp:
.text start:0x802BC260 end:0x802BCAB8 .text start:0x802BC260 end:0x802BCAB8
.bss start:0x804C2448 end:0x804C25D8 .bss start:0x804C2448 end:0x804C25D8
.sbss start:0x8053B0A0 end:0x8053B0A8 .sbss start:0x8053B0A0 end:0x8053B0A8
.sdata2 start:0x8053FD48 end:0x8053FD58 .sdata2 start:0x8053FD48 end:0x8053FD58
revolution/hbm/HBMRemoteSpk.cpp: revolution/homebuttonLib/HBMRemoteSpk.cpp:
.text start:0x802BCAB8 end:0x802BD2B8 .text start:0x802BCAB8 end:0x802BD2B8
.data start:0x804264F8 end:0x80426568 .data start:0x804264F8 end:0x80426568
.sbss start:0x8053B0A8 end:0x8053B0B0 .sbss start:0x8053B0A8 end:0x8053B0B0
revolution/db/db_assert.cpp: revolution/homebuttonLib/nw4hbm/db/db_assert.cpp:
.text start:0x802BD2B8 end:0x802BD8C8 .text start:0x802BD2B8 end:0x802BD8C8
.data start:0x80426568 end:0x80426618 .data start:0x80426568 end:0x80426618
.bss start:0x804C25D8 end:0x804C2608 .bss start:0x804C25D8 end:0x804C2608
.sdata start:0x8053A120 end:0x8053A128 .sdata start:0x8053A120 end:0x8053A128
.sbss start:0x8053B0B0 end:0x8053B0C0 .sbss start:0x8053B0B0 end:0x8053B0C0
revolution/db/db_console.cpp: revolution/homebuttonLib/nw4hbm/db/db_console.cpp:
.text start:0x802BD8C8 end:0x802BE1C8 .text start:0x802BD8C8 end:0x802BE1C8
.data start:0x80426618 end:0x80426738 .data start:0x80426618 end:0x80426738
.bss start:0x804C2608 end:0x804C2A20 .bss start:0x804C2608 end:0x804C2A20
.sdata start:0x8053A128 end:0x8053A130 .sdata start:0x8053A128 end:0x8053A130
revolution/db/db_DbgPrintBase.cpp: revolution/homebuttonLib/nw4hbm/db/db_DbgPrintBase.cpp:
.text start:0x802BE1C8 end:0x802BE208 .text start:0x802BE1C8 end:0x802BE208
revolution/db/db_directPrint.cpp: revolution/homebuttonLib/nw4hbm/db/db_directPrint.cpp:
.text start:0x802BE208 end:0x802BEC18 .text start:0x802BE208 end:0x802BEC18
.rodata start:0x803EF478 end:0x803EF730 .rodata start:0x803EF478 end:0x803EF730
.data start:0x80426738 end:0x804267E8 .data start:0x80426738 end:0x804267E8
.bss start:0x804C2A20 end:0x804C2A60 .bss start:0x804C2A20 end:0x804C2A60
.sbss start:0x8053B0C0 end:0x8053B0C8 .sbss start:0x8053B0C0 end:0x8053B0C8
revolution/db/db_mapFile.cpp: revolution/homebuttonLib/nw4hbm/db/db_mapFile.cpp:
.text start:0x802BEC18 end:0x802BF52C .text start:0x802BEC18 end:0x802BF52C
.data start:0x804267E8 end:0x804269F0 .data start:0x804267E8 end:0x804269F0
.bss start:0x804C2A60 end:0x804C2CA0 .bss start:0x804C2A60 end:0x804C2CA0
.sdata start:0x8053A130 end:0x8053A138 .sdata start:0x8053A130 end:0x8053A138
.sbss start:0x8053B0C8 end:0x8053B0D8 .sbss start:0x8053B0C8 end:0x8053B0D8
revolution/homebuttonLib/lyt_animation.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_animation.cpp:
.text start:0x802BF52C end:0x802C049C .text start:0x802BF52C end:0x802C049C
.data start:0x804269F0 end:0x80426E60 .data start:0x804269F0 end:0x80426E60
.sdata start:0x8053A138 end:0x8053A140 .sdata start:0x8053A138 end:0x8053A140
.sdata2 start:0x8053FD58 end:0x8053FD78 .sdata2 start:0x8053FD58 end:0x8053FD78
revolution/homebuttonLib/lyt_arcResourceAccessor.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_arcResourceAccessor.cpp:
.text start:0x802C049C end:0x802C0BA0 .text start:0x802C049C end:0x802C0BA0
.data start:0x80426E60 end:0x804270D8 .data start:0x80426E60 end:0x804270D8
.sdata start:0x8053A140 end:0x8053A148 .sdata start:0x8053A140 end:0x8053A148
revolution/homebuttonLib/lyt_bounding.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_bounding.cpp:
.text start:0x802C0BA0 end:0x802C0CB8 .text start:0x802C0BA0 end:0x802C0CB8
.ctors start:0x803CE384 end:0x803CE388 .ctors start:0x803CE384 end:0x803CE388
.data start:0x804270D8 end:0x80427140 .data start:0x804270D8 end:0x80427140
.sbss start:0x8053B0D8 end:0x8053B0E8 .sbss start:0x8053B0D8 end:0x8053B0E8
revolution/homebuttonLib/lyt_common.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_common.cpp:
.text start:0x802C0CB8 end:0x802C1B38 .text start:0x802C0CB8 end:0x802C1B38
.data start:0x80427140 end:0x804271B0 .data start:0x80427140 end:0x804271B0
.bss start:0x804C2CA0 end:0x804C2CC0 .bss start:0x804C2CA0 end:0x804C2CC0
.sdata2 start:0x8053FD78 end:0x8053FD88 .sdata2 start:0x8053FD78 end:0x8053FD88
revolution/homebuttonLib/lyt_drawInfo.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_drawInfo.cpp:
.text start:0x802C1B38 end:0x802C1BEC .text start:0x802C1B38 end:0x802C1BEC
.data start:0x804271B0 end:0x804271C0 .data start:0x804271B0 end:0x804271C0
.sdata2 start:0x8053FD88 end:0x8053FD90 .sdata2 start:0x8053FD88 end:0x8053FD90
revolution/homebuttonLib/lyt_group.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_group.cpp:
.text start:0x802C1BEC end:0x802C2094 .text start:0x802C1BEC end:0x802C2094
.data start:0x804271C0 end:0x804272C0 .data start:0x804271C0 end:0x804272C0
revolution/homebuttonLib/lyt_layout.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_layout.cpp:
.text start:0x802C2094 end:0x802C3048 .text start:0x802C2094 end:0x802C3048
.data start:0x804272C0 end:0x80427528 .data start:0x804272C0 end:0x80427528
.sbss start:0x8053B0E8 end:0x8053B0F0 .sbss start:0x8053B0E8 end:0x8053B0F0
.sdata2 start:0x8053FD90 end:0x8053FD98 .sdata2 start:0x8053FD90 end:0x8053FD98
revolution/homebuttonLib/lyt_material.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_material.cpp:
.text start:0x802C3048 end:0x802C6768 .text start:0x802C3048 end:0x802C6768
.data start:0x80427528 end:0x80427B28 .data start:0x80427528 end:0x80427B28
.sdata2 start:0x8053FD98 end:0x8053FDB8 .sdata2 start:0x8053FD98 end:0x8053FDB8
.sbss2 start:0x80540BD0 end:0x80540BE8 .sbss2 start:0x80540BD0 end:0x80540BE8
revolution/homebuttonLib/lyt_pane.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_pane.cpp:
.text start:0x802C6768 end:0x802C7AC0 .text start:0x802C6768 end:0x802C7AC0
.ctors start:0x803CE388 end:0x803CE38C .ctors start:0x803CE388 end:0x803CE38C
.data start:0x80427B28 end:0x80427EB8 .data start:0x80427B28 end:0x80427EB8
.sbss start:0x8053B0F0 end:0x8053B0F8 .sbss start:0x8053B0F0 end:0x8053B0F8
.sdata2 start:0x8053FDB8 end:0x8053FDD8 .sdata2 start:0x8053FDB8 end:0x8053FDD8
revolution/homebuttonLib/lyt_picture.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_picture.cpp:
.text start:0x802C7AC0 end:0x802C81E0 .text start:0x802C7AC0 end:0x802C81E0
.ctors start:0x803CE38C end:0x803CE390 .ctors start:0x803CE38C end:0x803CE390
.data start:0x80427EB8 end:0x804280E0 .data start:0x80427EB8 end:0x804280E0
.sbss start:0x8053B0F8 end:0x8053B100 .sbss start:0x8053B0F8 end:0x8053B100
.sdata2 start:0x8053FDD8 end:0x8053FDE0 .sdata2 start:0x8053FDD8 end:0x8053FDE0
revolution/homebuttonLib/lyt_resourceAccessor.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_resourceAccessor.cpp:
.text start:0x802C81E0 end:0x802C8238 .text start:0x802C81E0 end:0x802C8238
.data start:0x804280E0 end:0x804280F8 .data start:0x804280E0 end:0x804280F8
revolution/homebuttonLib/lyt_textBox.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_textBox.cpp:
.text start:0x802C8238 end:0x802CB080 .text start:0x802C8238 end:0x802CB080
.ctors start:0x803CE390 end:0x803CE394 .ctors start:0x803CE390 end:0x803CE394
.data start:0x804280F8 end:0x80428770 .data start:0x804280F8 end:0x80428770
@ -2480,74 +2480,74 @@ revolution/homebuttonLib/lyt_textBox.cpp:
.sbss start:0x8053B100 end:0x8053B108 .sbss start:0x8053B100 end:0x8053B108
.sdata2 start:0x8053FDE0 end:0x8053FDF8 .sdata2 start:0x8053FDE0 end:0x8053FDF8
revolution/homebuttonLib/lyt_window.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_window.cpp:
.text start:0x802CB080 end:0x802CD954 .text start:0x802CB080 end:0x802CD954
.ctors start:0x803CE394 end:0x803CE398 .ctors start:0x803CE394 end:0x803CE398
.data start:0x80428770 end:0x804289D0 .data start:0x80428770 end:0x804289D0
.sbss start:0x8053B108 end:0x8053B114 .sbss start:0x8053B108 end:0x8053B114
.sdata2 start:0x8053FDF8 end:0x8053FE10 .sdata2 start:0x8053FDF8 end:0x8053FE10
revolution/homebuttonLib/math_triangular.cpp: revolution/homebuttonLib/nw4hbm/math/math_triangular.cpp:
.text start:0x802CD954 end:0x802CDBC4 .text start:0x802CD954 end:0x802CDBC4
.data start:0x804289D0 end:0x80429AE8 .data start:0x804289D0 end:0x80429AE8
.sdata2 start:0x8053FE10 end:0x8053FE30 .sdata2 start:0x8053FE10 end:0x8053FE30
revolution/homebuttonLib/snd_SoundArchivePlayer.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundArchivePlayer.cpp:
.text start:0x802CDBC4 end:0x802CDC34 .text start:0x802CDBC4 end:0x802CDC34
.data start:0x80429AE8 end:0x80429B48 .data start:0x80429AE8 end:0x80429B48
revolution/homebuttonLib/snd_SoundHandle.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundHandle.cpp:
.text start:0x802CDC34 end:0x802CDC84 .text start:0x802CDC34 end:0x802CDC84
revolution/homebuttonLib/snd_SoundPlayer.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundPlayer.cpp:
.text start:0x802CDC84 end:0x802CDD74 .text start:0x802CDC84 end:0x802CDD74
.data start:0x80429B48 end:0x80429BB8 .data start:0x80429B48 end:0x80429BB8
.sdata2 start:0x8053FE30 end:0x8053FE38 .sdata2 start:0x8053FE30 end:0x8053FE38
revolution/homebuttonLib/snd_SoundStartable.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundStartable.cpp:
.text start:0x802CDD74 end:0x802CDDE0 .text start:0x802CDD74 end:0x802CDDE0
revolution/homebuttonLib/ut_binaryFileFormat.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_binaryFileFormat.cpp:
.text start:0x802CDDE0 end:0x802CE038 .text start:0x802CDDE0 end:0x802CE038
.data start:0x80429BB8 end:0x80429D08 .data start:0x80429BB8 end:0x80429D08
revolution/homebuttonLib/ut_CharStrmReader.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_CharStrmReader.cpp:
.text start:0x802CE038 end:0x802CE998 .text start:0x802CE038 end:0x802CE998
.data start:0x80429D08 end:0x80429E50 .data start:0x80429D08 end:0x80429E50
revolution/homebuttonLib/ut_CharWriter.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_CharWriter.cpp:
.text start:0x802CE998 end:0x802D2EF4 .text start:0x802CE998 end:0x802D2EF4
.data start:0x80429E50 end:0x8042A130 .data start:0x80429E50 end:0x8042A130
.bss start:0x804C2CC0 end:0x804C2CE0 .bss start:0x804C2CC0 end:0x804C2CE0
.sbss start:0x8053B114 end:0x8053B118 .sbss start:0x8053B114 end:0x8053B118
.sdata2 start:0x8053FE38 end:0x8053FE58 .sdata2 start:0x8053FE38 end:0x8053FE58
revolution/homebuttonLib/ut_Font.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_Font.cpp:
.text start:0x802D2EF4 end:0x802D30B8 .text start:0x802D2EF4 end:0x802D30B8
.data start:0x8042A130 end:0x8042A1A8 .data start:0x8042A130 end:0x8042A1A8
revolution/homebuttonLib/ut_LinkList.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_LinkList.cpp:
.text start:0x802D30B8 end:0x802D3528 .text start:0x802D30B8 end:0x802D3528
.data start:0x8042A1A8 end:0x8042A350 .data start:0x8042A1A8 end:0x8042A350
revolution/homebuttonLib/ut_list.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_list.cpp:
.text start:0x802D3528 end:0x802D38D0 .text start:0x802D3528 end:0x802D38D0
.data start:0x8042A350 end:0x8042A3B0 .data start:0x8042A350 end:0x8042A3B0
revolution/homebuttonLib/ut_ResFont.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_ResFont.cpp:
.text start:0x802D38D0 end:0x802D48E8 .text start:0x802D38D0 end:0x802D48E8
.data start:0x8042A3B0 end:0x8042AC68 .data start:0x8042A3B0 end:0x8042AC68
revolution/homebuttonLib/ut_ResFontBase.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_ResFontBase.cpp:
.text start:0x802D48E8 end:0x802D80C8 .text start:0x802D48E8 end:0x802D80C8
.data start:0x8042AC68 end:0x8042AF80 .data start:0x8042AC68 end:0x8042AF80
revolution/homebuttonLib/ut_TagProcessorBase.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_TagProcessorBase.cpp:
.text start:0x802D80C8 end:0x802D92D0 .text start:0x802D80C8 end:0x802D92D0
.data start:0x8042AF80 end:0x8042B058 .data start:0x8042AF80 end:0x8042B058
.sdata2 start:0x8053FE58 end:0x8053FE60 .sdata2 start:0x8053FE58 end:0x8053FE60
revolution/homebuttonLib/ut_TextWriterBase.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_TextWriterBase.cpp:
.text start:0x802D92D0 end:0x802E1FB4 .text start:0x802D92D0 end:0x802E1FB4
.ctors start:0x803CE398 end:0x803CE39C .ctors start:0x803CE398 end:0x803CE39C
.data start:0x8042B058 end:0x8042B680 .data start:0x8042B058 end:0x8042B680

View File

@ -2348,7 +2348,7 @@ revolution/gf/GFPixel.cpp:
revolution/gf/GFTev.cpp: revolution/gf/GFTev.cpp:
.text start:0x802B1D5C end:0x802B1DBC .text start:0x802B1D5C end:0x802B1DBC
revolution/hbm/HBMBase.cpp: revolution/homebuttonLib/HBMBase.cpp:
.text start:0x802B1DBC end:0x802BA3D4 .text start:0x802B1DBC end:0x802BA3D4
.rodata start:0x803DA7C8 end:0x803DAA78 .rodata start:0x803DA7C8 end:0x803DAA78
.data start:0x804107F0 end:0x80411398 .data start:0x804107F0 end:0x80411398
@ -2357,95 +2357,95 @@ revolution/hbm/HBMBase.cpp:
.sbss start:0x805210B0 end:0x805210B8 .sbss start:0x805210B0 end:0x805210B8
.sdata2 start:0x80525D58 end:0x80525DB8 .sdata2 start:0x80525D58 end:0x80525DB8
revolution/hbm/HBMAnmController.cpp: revolution/homebuttonLib/HBMAnmController.cpp:
.text start:0x802BA3D4 end:0x802BA4E0 .text start:0x802BA3D4 end:0x802BA4E0
.data start:0x80411398 end:0x804113A8 .data start:0x80411398 end:0x804113A8
revolution/hbm/HBMFrameController.cpp: revolution/homebuttonLib/HBMFrameController.cpp:
.text start:0x802BA4E0 end:0x802BA680 .text start:0x802BA4E0 end:0x802BA680
.sdata2 start:0x80525DB8 end:0x80525DC0 .sdata2 start:0x80525DB8 end:0x80525DC0
revolution/hbm/HBMGUIManager.cpp: revolution/homebuttonLib/HBMGUIManager.cpp:
.text start:0x802BA680 end:0x802BBAB8 .text start:0x802BA680 end:0x802BBAB8
.data start:0x804113A8 end:0x80411500 .data start:0x804113A8 end:0x80411500
.sbss start:0x805210B8 end:0x805210C0 .sbss start:0x805210B8 end:0x805210C0
.sdata2 start:0x80525DC0 end:0x80525DD0 .sdata2 start:0x80525DC0 end:0x80525DD0
revolution/hbm/HBMController.cpp: revolution/homebuttonLib/HBMController.cpp:
.text start:0x802BBAB8 end:0x802BC310 .text start:0x802BBAB8 end:0x802BC310
.bss start:0x804A8B78 end:0x804A8D08 .bss start:0x804A8B78 end:0x804A8D08
.sbss start:0x805210C0 end:0x805210C8 .sbss start:0x805210C0 end:0x805210C8
.sdata2 start:0x80525DD0 end:0x80525DE0 .sdata2 start:0x80525DD0 end:0x80525DE0
revolution/hbm/HBMRemoteSpk.cpp: revolution/homebuttonLib/HBMRemoteSpk.cpp:
.text start:0x802BC310 end:0x802BCA6C .text start:0x802BC310 end:0x802BCA6C
.data start:0x80411500 end:0x80411510 .data start:0x80411500 end:0x80411510
.sbss start:0x805210C8 end:0x805210D0 .sbss start:0x805210C8 end:0x805210D0
revolution/db/db_DbgPrintBase.cpp: revolution/homebuttonLib/nw4hbm/db/db_DbgPrintBase.cpp:
.text start:0x802BCA6C end:0x802BCAAC .text start:0x802BCA6C end:0x802BCAAC
revolution/homebuttonLib/lyt_animation.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_animation.cpp:
.text start:0x802BCAAC end:0x802BD61C .text start:0x802BCAAC end:0x802BD61C
.data start:0x80411510 end:0x80411530 .data start:0x80411510 end:0x80411530
.sdata2 start:0x80525DE0 end:0x80525E00 .sdata2 start:0x80525DE0 end:0x80525E00
revolution/homebuttonLib/lyt_arcResourceAccessor.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_arcResourceAccessor.cpp:
.text start:0x802BD61C end:0x802BD990 .text start:0x802BD61C end:0x802BD990
.data start:0x80411530 end:0x80411548 .data start:0x80411530 end:0x80411548
.sdata start:0x80520160 end:0x80520168 .sdata start:0x80520160 end:0x80520168
revolution/homebuttonLib/lyt_bounding.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_bounding.cpp:
.text start:0x802BD990 end:0x802BDAA8 .text start:0x802BD990 end:0x802BDAA8
.ctors start:0x803B8DC8 end:0x803B8DCC .ctors start:0x803B8DC8 end:0x803B8DCC
.data start:0x80411548 end:0x804115B0 .data start:0x80411548 end:0x804115B0
.sbss start:0x805210D0 end:0x805210E0 .sbss start:0x805210D0 end:0x805210E0
revolution/homebuttonLib/lyt_common.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_common.cpp:
.text start:0x802BDAA8 end:0x802BE8A0 .text start:0x802BDAA8 end:0x802BE8A0
.bss start:0x804A8D08 end:0x804A8D28 .bss start:0x804A8D08 end:0x804A8D28
.sdata2 start:0x80525E00 end:0x80525E10 .sdata2 start:0x80525E00 end:0x80525E10
revolution/homebuttonLib/lyt_drawInfo.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_drawInfo.cpp:
.text start:0x802BE8A0 end:0x802BE954 .text start:0x802BE8A0 end:0x802BE954
.data start:0x804115B0 end:0x804115C0 .data start:0x804115B0 end:0x804115C0
.sdata2 start:0x80525E10 end:0x80525E18 .sdata2 start:0x80525E10 end:0x80525E18
revolution/homebuttonLib/lyt_group.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_group.cpp:
.text start:0x802BE954 end:0x802BEC74 .text start:0x802BE954 end:0x802BEC74
.data start:0x804115C0 end:0x804115D0 .data start:0x804115C0 end:0x804115D0
revolution/homebuttonLib/lyt_layout.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_layout.cpp:
.text start:0x802BEC74 end:0x802BF8E4 .text start:0x802BEC74 end:0x802BF8E4
.data start:0x804115D0 end:0x80411608 .data start:0x804115D0 end:0x80411608
.sbss start:0x805210E0 end:0x805210E8 .sbss start:0x805210E0 end:0x805210E8
.sdata2 start:0x80525E18 end:0x80525E20 .sdata2 start:0x80525E18 end:0x80525E20
revolution/homebuttonLib/lyt_material.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_material.cpp:
.text start:0x802BF8E4 end:0x802C2CB8 .text start:0x802BF8E4 end:0x802C2CB8
.data start:0x80411608 end:0x80411670 .data start:0x80411608 end:0x80411670
.sdata2 start:0x80525E20 end:0x80525E40 .sdata2 start:0x80525E20 end:0x80525E40
.sbss2 start:0x80526C50 end:0x80526C68 .sbss2 start:0x80526C50 end:0x80526C68
revolution/homebuttonLib/lyt_pane.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_pane.cpp:
.text start:0x802C2CB8 end:0x802C3BEC .text start:0x802C2CB8 end:0x802C3BEC
.ctors start:0x803B8DCC end:0x803B8DD0 .ctors start:0x803B8DCC end:0x803B8DD0
.data start:0x80411670 end:0x804116D8 .data start:0x80411670 end:0x804116D8
.sbss start:0x805210E8 end:0x805210F0 .sbss start:0x805210E8 end:0x805210F0
.sdata2 start:0x80525E40 end:0x80525E60 .sdata2 start:0x80525E40 end:0x80525E60
revolution/homebuttonLib/lyt_picture.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_picture.cpp:
.text start:0x802C3BEC end:0x802C410C .text start:0x802C3BEC end:0x802C410C
.ctors start:0x803B8DD0 end:0x803B8DD4 .ctors start:0x803B8DD0 end:0x803B8DD4
.data start:0x804116D8 end:0x80411748 .data start:0x804116D8 end:0x80411748
.sbss start:0x805210F0 end:0x805210F8 .sbss start:0x805210F0 end:0x805210F8
.sdata2 start:0x80525E60 end:0x80525E68 .sdata2 start:0x80525E60 end:0x80525E68
revolution/homebuttonLib/lyt_resourceAccessor.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_resourceAccessor.cpp:
.text start:0x802C410C end:0x802C4164 .text start:0x802C410C end:0x802C4164
.data start:0x80411748 end:0x80411760 .data start:0x80411748 end:0x80411760
revolution/homebuttonLib/lyt_textBox.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_textBox.cpp:
.text start:0x802C4164 end:0x802C5794 .text start:0x802C4164 end:0x802C5794
.ctors start:0x803B8DD4 end:0x803B8DD8 .ctors start:0x803B8DD4 end:0x803B8DD8
.data start:0x80411760 end:0x804117D8 .data start:0x80411760 end:0x804117D8
@ -2453,66 +2453,66 @@ revolution/homebuttonLib/lyt_textBox.cpp:
.sbss start:0x805210F8 end:0x80521100 .sbss start:0x805210F8 end:0x80521100
.sdata2 start:0x80525E68 end:0x80525E80 .sdata2 start:0x80525E68 end:0x80525E80
revolution/homebuttonLib/lyt_window.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_window.cpp:
.text start:0x802C5794 end:0x802C7C10 .text start:0x802C5794 end:0x802C7C10
.ctors start:0x803B8DD8 end:0x803B8DDC .ctors start:0x803B8DD8 end:0x803B8DDC
.data start:0x804117D8 end:0x80411890 .data start:0x804117D8 end:0x80411890
.sbss start:0x80521100 end:0x8052110C .sbss start:0x80521100 end:0x8052110C
.sdata2 start:0x80525E80 end:0x80525E98 .sdata2 start:0x80525E80 end:0x80525E98
revolution/homebuttonLib/math_triangular.cpp: revolution/homebuttonLib/nw4hbm/math/math_triangular.cpp:
.text start:0x802C7C10 end:0x802C7E80 .text start:0x802C7C10 end:0x802C7E80
.data start:0x80411890 end:0x804129A8 .data start:0x80411890 end:0x804129A8
.sdata2 start:0x80525E98 end:0x80525EB8 .sdata2 start:0x80525E98 end:0x80525EB8
revolution/homebuttonLib/snd_SoundArchivePlayer.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundArchivePlayer.cpp:
.text start:0x802C7E80 end:0x802C7E90 .text start:0x802C7E80 end:0x802C7E90
revolution/homebuttonLib/snd_SoundHandle.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundHandle.cpp:
.text start:0x802C7E90 end:0x802C7EE0 .text start:0x802C7E90 end:0x802C7EE0
revolution/homebuttonLib/snd_SoundPlayer.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundPlayer.cpp:
.text start:0x802C7EE0 end:0x802C7F50 .text start:0x802C7EE0 end:0x802C7F50
revolution/homebuttonLib/snd_SoundStartable.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundStartable.cpp:
.text start:0x802C7F50 end:0x802C7FBC .text start:0x802C7F50 end:0x802C7FBC
revolution/homebuttonLib/ut_binaryFileFormat.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_binaryFileFormat.cpp:
.text start:0x802C7FBC end:0x802C8030 .text start:0x802C7FBC end:0x802C8030
revolution/homebuttonLib/ut_CharStrmReader.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_CharStrmReader.cpp:
.text start:0x802C8030 end:0x802C8140 .text start:0x802C8030 end:0x802C8140
revolution/homebuttonLib/ut_CharWriter.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_CharWriter.cpp:
.text start:0x802C8140 end:0x802C9BC4 .text start:0x802C8140 end:0x802C9BC4
.bss start:0x804A8D28 end:0x804A8D48 .bss start:0x804A8D28 end:0x804A8D48
.sbss start:0x8052110C end:0x80521110 .sbss start:0x8052110C end:0x80521110
.sdata2 start:0x80525EB8 end:0x80525ED8 .sdata2 start:0x80525EB8 end:0x80525ED8
revolution/homebuttonLib/ut_Font.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_Font.cpp:
.text start:0x802C9BC4 end:0x802C9C6C .text start:0x802C9BC4 end:0x802C9C6C
.data start:0x804129A8 end:0x804129D8 .data start:0x804129A8 end:0x804129D8
revolution/homebuttonLib/ut_LinkList.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_LinkList.cpp:
.text start:0x802C9C6C end:0x802C9D64 .text start:0x802C9C6C end:0x802C9D64
revolution/homebuttonLib/ut_list.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_list.cpp:
.text start:0x802C9D64 end:0x802C9EC4 .text start:0x802C9D64 end:0x802C9EC4
revolution/homebuttonLib/ut_ResFont.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_ResFont.cpp:
.text start:0x802C9EC4 end:0x802CA1C8 .text start:0x802C9EC4 end:0x802CA1C8
.data start:0x804129D8 end:0x80412A30 .data start:0x804129D8 end:0x80412A30
revolution/homebuttonLib/ut_ResFontBase.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_ResFontBase.cpp:
.text start:0x802CA1C8 end:0x802CA798 .text start:0x802CA1C8 end:0x802CA798
.data start:0x80412A30 end:0x80412AF0 .data start:0x80412A30 end:0x80412AF0
revolution/homebuttonLib/ut_TagProcessorBase.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_TagProcessorBase.cpp:
.text start:0x802CA798 end:0x802CAF58 .text start:0x802CA798 end:0x802CAF58
.data start:0x80412AF0 end:0x80412B48 .data start:0x80412AF0 end:0x80412B48
.sdata2 start:0x80525ED8 end:0x80525EE0 .sdata2 start:0x80525ED8 end:0x80525EE0
revolution/homebuttonLib/ut_TextWriterBase.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_TextWriterBase.cpp:
.text start:0x802CAF58 end:0x802CC984 .text start:0x802CAF58 end:0x802CC984
.ctors start:0x803B8DDC end:0x803B8DE0 .ctors start:0x803B8DDC end:0x803B8DE0
.bss start:0x804A8D48 end:0x804A8D60 .bss start:0x804A8D48 end:0x804A8D60

View File

@ -2348,7 +2348,7 @@ revolution/gf/GFPixel.cpp:
revolution/gf/GFTev.cpp: revolution/gf/GFTev.cpp:
.text start:0x802B387C end:0x802B38DC .text start:0x802B387C end:0x802B38DC
revolution/hbm/HBMBase.cpp: revolution/homebuttonLib/HBMBase.cpp:
.text start:0x802B38DC end:0x802BBEF4 .text start:0x802B38DC end:0x802BBEF4
.rodata start:0x803D8788 end:0x803D8A38 .rodata start:0x803D8788 end:0x803D8A38
.data start:0x8040E670 end:0x8040F218 .data start:0x8040E670 end:0x8040F218
@ -2357,95 +2357,95 @@ revolution/hbm/HBMBase.cpp:
.sbss start:0x8051EF20 end:0x8051EF28 .sbss start:0x8051EF20 end:0x8051EF28
.sdata2 start:0x80523BB0 end:0x80523C10 .sdata2 start:0x80523BB0 end:0x80523C10
revolution/hbm/HBMAnmController.cpp: revolution/homebuttonLib/HBMAnmController.cpp:
.text start:0x802BBEF4 end:0x802BC000 .text start:0x802BBEF4 end:0x802BC000
.data start:0x8040F218 end:0x8040F228 .data start:0x8040F218 end:0x8040F228
revolution/hbm/HBMFrameController.cpp: revolution/homebuttonLib/HBMFrameController.cpp:
.text start:0x802BC000 end:0x802BC1A0 .text start:0x802BC000 end:0x802BC1A0
.sdata2 start:0x80523C10 end:0x80523C18 .sdata2 start:0x80523C10 end:0x80523C18
revolution/hbm/HBMGUIManager.cpp: revolution/homebuttonLib/HBMGUIManager.cpp:
.text start:0x802BC1A0 end:0x802BD5D8 .text start:0x802BC1A0 end:0x802BD5D8
.data start:0x8040F228 end:0x8040F380 .data start:0x8040F228 end:0x8040F380
.sbss start:0x8051EF28 end:0x8051EF30 .sbss start:0x8051EF28 end:0x8051EF30
.sdata2 start:0x80523C18 end:0x80523C28 .sdata2 start:0x80523C18 end:0x80523C28
revolution/hbm/HBMController.cpp: revolution/homebuttonLib/HBMController.cpp:
.text start:0x802BD5D8 end:0x802BDE30 .text start:0x802BD5D8 end:0x802BDE30
.bss start:0x804A69F8 end:0x804A6B88 .bss start:0x804A69F8 end:0x804A6B88
.sbss start:0x8051EF30 end:0x8051EF38 .sbss start:0x8051EF30 end:0x8051EF38
.sdata2 start:0x80523C28 end:0x80523C38 .sdata2 start:0x80523C28 end:0x80523C38
revolution/hbm/HBMRemoteSpk.cpp: revolution/homebuttonLib/HBMRemoteSpk.cpp:
.text start:0x802BDE30 end:0x802BE58C .text start:0x802BDE30 end:0x802BE58C
.data start:0x8040F380 end:0x8040F390 .data start:0x8040F380 end:0x8040F390
.sbss start:0x8051EF38 end:0x8051EF40 .sbss start:0x8051EF38 end:0x8051EF40
revolution/db/db_DbgPrintBase.cpp: revolution/homebuttonLib/nw4hbm/db/db_DbgPrintBase.cpp:
.text start:0x802BE58C end:0x802BE5CC .text start:0x802BE58C end:0x802BE5CC
revolution/homebuttonLib/lyt_animation.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_animation.cpp:
.text start:0x802BE5CC end:0x802BF13C .text start:0x802BE5CC end:0x802BF13C
.data start:0x8040F390 end:0x8040F3B0 .data start:0x8040F390 end:0x8040F3B0
.sdata2 start:0x80523C38 end:0x80523C58 .sdata2 start:0x80523C38 end:0x80523C58
revolution/homebuttonLib/lyt_arcResourceAccessor.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_arcResourceAccessor.cpp:
.text start:0x802BF13C end:0x802BF4B0 .text start:0x802BF13C end:0x802BF4B0
.data start:0x8040F3B0 end:0x8040F3C8 .data start:0x8040F3B0 end:0x8040F3C8
.sdata start:0x8051DFD0 end:0x8051DFD8 .sdata start:0x8051DFD0 end:0x8051DFD8
revolution/homebuttonLib/lyt_bounding.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_bounding.cpp:
.text start:0x802BF4B0 end:0x802BF5C8 .text start:0x802BF4B0 end:0x802BF5C8
.ctors start:0x803BA888 end:0x803BA88C .ctors start:0x803BA888 end:0x803BA88C
.data start:0x8040F3C8 end:0x8040F430 .data start:0x8040F3C8 end:0x8040F430
.sbss start:0x8051EF40 end:0x8051EF50 .sbss start:0x8051EF40 end:0x8051EF50
revolution/homebuttonLib/lyt_common.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_common.cpp:
.text start:0x802BF5C8 end:0x802C03C0 .text start:0x802BF5C8 end:0x802C03C0
.bss start:0x804A6B88 end:0x804A6BA8 .bss start:0x804A6B88 end:0x804A6BA8
.sdata2 start:0x80523C58 end:0x80523C68 .sdata2 start:0x80523C58 end:0x80523C68
revolution/homebuttonLib/lyt_drawInfo.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_drawInfo.cpp:
.text start:0x802C03C0 end:0x802C0474 .text start:0x802C03C0 end:0x802C0474
.data start:0x8040F430 end:0x8040F440 .data start:0x8040F430 end:0x8040F440
.sdata2 start:0x80523C68 end:0x80523C70 .sdata2 start:0x80523C68 end:0x80523C70
revolution/homebuttonLib/lyt_group.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_group.cpp:
.text start:0x802C0474 end:0x802C0794 .text start:0x802C0474 end:0x802C0794
.data start:0x8040F440 end:0x8040F450 .data start:0x8040F440 end:0x8040F450
revolution/homebuttonLib/lyt_layout.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_layout.cpp:
.text start:0x802C0794 end:0x802C1404 .text start:0x802C0794 end:0x802C1404
.data start:0x8040F450 end:0x8040F488 .data start:0x8040F450 end:0x8040F488
.sbss start:0x8051EF50 end:0x8051EF58 .sbss start:0x8051EF50 end:0x8051EF58
.sdata2 start:0x80523C70 end:0x80523C78 .sdata2 start:0x80523C70 end:0x80523C78
revolution/homebuttonLib/lyt_material.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_material.cpp:
.text start:0x802C1404 end:0x802C47D8 .text start:0x802C1404 end:0x802C47D8
.data start:0x8040F488 end:0x8040F4F0 .data start:0x8040F488 end:0x8040F4F0
.sdata2 start:0x80523C78 end:0x80523C98 .sdata2 start:0x80523C78 end:0x80523C98
.sbss2 start:0x80524A90 end:0x80524AA8 .sbss2 start:0x80524A90 end:0x80524AA8
revolution/homebuttonLib/lyt_pane.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_pane.cpp:
.text start:0x802C47D8 end:0x802C570C .text start:0x802C47D8 end:0x802C570C
.ctors start:0x803BA88C end:0x803BA890 .ctors start:0x803BA88C end:0x803BA890
.data start:0x8040F4F0 end:0x8040F558 .data start:0x8040F4F0 end:0x8040F558
.sbss start:0x8051EF58 end:0x8051EF60 .sbss start:0x8051EF58 end:0x8051EF60
.sdata2 start:0x80523C98 end:0x80523CB8 .sdata2 start:0x80523C98 end:0x80523CB8
revolution/homebuttonLib/lyt_picture.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_picture.cpp:
.text start:0x802C570C end:0x802C5C2C .text start:0x802C570C end:0x802C5C2C
.ctors start:0x803BA890 end:0x803BA894 .ctors start:0x803BA890 end:0x803BA894
.data start:0x8040F558 end:0x8040F5C8 .data start:0x8040F558 end:0x8040F5C8
.sbss start:0x8051EF60 end:0x8051EF68 .sbss start:0x8051EF60 end:0x8051EF68
.sdata2 start:0x80523CB8 end:0x80523CC0 .sdata2 start:0x80523CB8 end:0x80523CC0
revolution/homebuttonLib/lyt_resourceAccessor.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_resourceAccessor.cpp:
.text start:0x802C5C2C end:0x802C5C84 .text start:0x802C5C2C end:0x802C5C84
.data start:0x8040F5C8 end:0x8040F5E0 .data start:0x8040F5C8 end:0x8040F5E0
revolution/homebuttonLib/lyt_textBox.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_textBox.cpp:
.text start:0x802C5C84 end:0x802C72B4 .text start:0x802C5C84 end:0x802C72B4
.ctors start:0x803BA894 end:0x803BA898 .ctors start:0x803BA894 end:0x803BA898
.data start:0x8040F5E0 end:0x8040F658 .data start:0x8040F5E0 end:0x8040F658
@ -2453,66 +2453,66 @@ revolution/homebuttonLib/lyt_textBox.cpp:
.sbss start:0x8051EF68 end:0x8051EF70 .sbss start:0x8051EF68 end:0x8051EF70
.sdata2 start:0x80523CC0 end:0x80523CD8 .sdata2 start:0x80523CC0 end:0x80523CD8
revolution/homebuttonLib/lyt_window.cpp: revolution/homebuttonLib/nw4hbm/lyt/lyt_window.cpp:
.text start:0x802C72B4 end:0x802C9730 .text start:0x802C72B4 end:0x802C9730
.ctors start:0x803BA898 end:0x803BA89C .ctors start:0x803BA898 end:0x803BA89C
.data start:0x8040F658 end:0x8040F710 .data start:0x8040F658 end:0x8040F710
.sbss start:0x8051EF70 end:0x8051EF7C .sbss start:0x8051EF70 end:0x8051EF7C
.sdata2 start:0x80523CD8 end:0x80523CF0 .sdata2 start:0x80523CD8 end:0x80523CF0
revolution/homebuttonLib/math_triangular.cpp: revolution/homebuttonLib/nw4hbm/math/math_triangular.cpp:
.text start:0x802C9730 end:0x802C99A0 .text start:0x802C9730 end:0x802C99A0
.data start:0x8040F710 end:0x80410828 .data start:0x8040F710 end:0x80410828
.sdata2 start:0x80523CF0 end:0x80523D10 .sdata2 start:0x80523CF0 end:0x80523D10
revolution/homebuttonLib/snd_SoundArchivePlayer.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundArchivePlayer.cpp:
.text start:0x802C99A0 end:0x802C99B0 .text start:0x802C99A0 end:0x802C99B0
revolution/homebuttonLib/snd_SoundHandle.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundHandle.cpp:
.text start:0x802C99B0 end:0x802C9A00 .text start:0x802C99B0 end:0x802C9A00
revolution/homebuttonLib/snd_SoundPlayer.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundPlayer.cpp:
.text start:0x802C9A00 end:0x802C9A70 .text start:0x802C9A00 end:0x802C9A70
revolution/homebuttonLib/snd_SoundStartable.cpp: revolution/homebuttonLib/nw4hbm/snd/snd_SoundStartable.cpp:
.text start:0x802C9A70 end:0x802C9ADC .text start:0x802C9A70 end:0x802C9ADC
revolution/homebuttonLib/ut_binaryFileFormat.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_binaryFileFormat.cpp:
.text start:0x802C9ADC end:0x802C9B50 .text start:0x802C9ADC end:0x802C9B50
revolution/homebuttonLib/ut_CharStrmReader.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_CharStrmReader.cpp:
.text start:0x802C9B50 end:0x802C9C60 .text start:0x802C9B50 end:0x802C9C60
revolution/homebuttonLib/ut_CharWriter.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_CharWriter.cpp:
.text start:0x802C9C60 end:0x802CB6E4 .text start:0x802C9C60 end:0x802CB6E4
.bss start:0x804A6BA8 end:0x804A6BC8 .bss start:0x804A6BA8 end:0x804A6BC8
.sbss start:0x8051EF7C end:0x8051EF80 .sbss start:0x8051EF7C end:0x8051EF80
.sdata2 start:0x80523D10 end:0x80523D30 .sdata2 start:0x80523D10 end:0x80523D30
revolution/homebuttonLib/ut_Font.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_Font.cpp:
.text start:0x802CB6E4 end:0x802CB78C .text start:0x802CB6E4 end:0x802CB78C
.data start:0x80410828 end:0x80410858 .data start:0x80410828 end:0x80410858
revolution/homebuttonLib/ut_LinkList.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_LinkList.cpp:
.text start:0x802CB78C end:0x802CB884 .text start:0x802CB78C end:0x802CB884
revolution/homebuttonLib/ut_list.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_list.cpp:
.text start:0x802CB884 end:0x802CB9E4 .text start:0x802CB884 end:0x802CB9E4
revolution/homebuttonLib/ut_ResFont.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_ResFont.cpp:
.text start:0x802CB9E4 end:0x802CBCE8 .text start:0x802CB9E4 end:0x802CBCE8
.data start:0x80410858 end:0x804108B0 .data start:0x80410858 end:0x804108B0
revolution/homebuttonLib/ut_ResFontBase.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_ResFontBase.cpp:
.text start:0x802CBCE8 end:0x802CC2B8 .text start:0x802CBCE8 end:0x802CC2B8
.data start:0x804108B0 end:0x80410970 .data start:0x804108B0 end:0x80410970
revolution/homebuttonLib/ut_TagProcessorBase.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_TagProcessorBase.cpp:
.text start:0x802CC2B8 end:0x802CCA78 .text start:0x802CC2B8 end:0x802CCA78
.data start:0x80410970 end:0x804109C8 .data start:0x80410970 end:0x804109C8
.sdata2 start:0x80523D30 end:0x80523D38 .sdata2 start:0x80523D30 end:0x80523D38
revolution/homebuttonLib/ut_TextWriterBase.cpp: revolution/homebuttonLib/nw4hbm/ut/ut_TextWriterBase.cpp:
.text start:0x802CCA78 end:0x802CE4A4 .text start:0x802CCA78 end:0x802CE4A4
.ctors start:0x803BA89C end:0x803BA8A0 .ctors start:0x803BA89C end:0x803BA8A0
.bss start:0x804A6BC8 end:0x804A6BE0 .bss start:0x804A6BC8 end:0x804A6BE0

View File

@ -496,6 +496,14 @@ def RevolutionLib(lib_name: str, objects: List[Object]) -> Dict[str, Any]:
"progress_category": "sdk", "progress_category": "sdk",
"objects": objects, "objects": objects,
} }
elif config.version == "RZDE01_00":
return {
"lib": lib_name,
"mw_version": "GC/3.0a3",
"cflags": [*cflags_revolution_retail, "-DSDK_SEP2006", "-DNW4HBM_DEBUG"],
"progress_category": "sdk",
"objects": objects,
}
else: else:
return { return {
"lib": lib_name, "lib": lib_name,
@ -1614,6 +1622,25 @@ config.libs = [
Object(NonMatching, "revolution/dsp/dsp_task.c"), Object(NonMatching, "revolution/dsp/dsp_task.c"),
], ],
), ),
RevolutionLib(
"card",
[
Object(NonMatching, "revolution/card/CARDBios.c"),
Object(NonMatching, "revolution/card/CARDUnlock.c"),
Object(NonMatching, "revolution/card/CARDRdwr.c"),
Object(NonMatching, "revolution/card/CARDBlock.c"),
Object(NonMatching, "revolution/card/CARDDir.c"),
Object(NonMatching, "revolution/card/CARDCheck.c"),
Object(NonMatching, "revolution/card/CARDMount.c"),
Object(NonMatching, "revolution/card/CARDFormat.c"),
Object(NonMatching, "revolution/card/CARDOpen.c", extra_cflags=["-char signed"]),
Object(NonMatching, "revolution/card/CARDCreate.c"),
Object(NonMatching, "revolution/card/CARDRead.c"),
Object(NonMatching, "revolution/card/CARDWrite.c"),
Object(NonMatching, "revolution/card/CARDStat.c"),
Object(NonMatching, "revolution/card/CARDNet.c"),
],
),
RevolutionLib( RevolutionLib(
"hio2", "hio2",
[ [
@ -1693,6 +1720,51 @@ config.libs = [
Object(NonMatching, "revolution/gd/GDGeometry.c"), Object(NonMatching, "revolution/gd/GDGeometry.c"),
], ],
), ),
RevolutionLib(
"homebuttonLib",
[
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/db/db_assert.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/db/db_console.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/db/db_DbgPrintBase.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/db/db_directPrint.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/db/db_mapFile.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_animation.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_arcResourceAccessor.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_bounding.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_common.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_drawInfo.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_group.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_layout.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_material.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_pane.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_picture.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_resourceAccessor.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_textBox.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/lyt/lyt_window.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/math/math_triangular.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/snd/snd_SoundArchivePlayer.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/snd/snd_SoundHandle.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/snd/snd_SoundPlayer.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/snd/snd_SoundStartable.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_binaryFileFormat.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_CharStrmReader.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_CharWriter.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_Font.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_LinkList.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_list.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_ResFont.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_ResFontBase.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_TagProcessorBase.cpp"),
Object(NonMatching, "revolution/homebuttonLib/nw4hbm/ut/ut_TextWriterBase.cpp"),
Object(NonMatching, "revolution/homebuttonLib/HBMBase.cpp"),
Object(NonMatching, "revolution/homebuttonLib/HBMAnmController.cpp"),
Object(NonMatching, "revolution/homebuttonLib/HBMFrameController.cpp"),
Object(NonMatching, "revolution/homebuttonLib/HBMGUIManager.cpp"),
Object(NonMatching, "revolution/homebuttonLib/HBMController.cpp"),
Object(NonMatching, "revolution/homebuttonLib/HBMRemoteSpk.cpp"),
],
),
{ {
"lib": "Runtime.PPCEABI.H", "lib": "Runtime.PPCEABI.H",
"mw_version": MWVersion(config.version), "mw_version": MWVersion(config.version),

View File

@ -1,6 +1,9 @@
#ifndef _DOLPHIN_CARD_H_ #ifndef _DOLPHIN_CARD_H_
#define _DOLPHIN_CARD_H_ #define _DOLPHIN_CARD_H_
#ifdef __REVOLUTION_SDK__
#include <revolution/card.h>
#else
#include <dolphin/os.h> #include <dolphin/os.h>
#include <dolphin/dsp.h> #include <dolphin/dsp.h>
#include <dolphin/dvd.h> #include <dolphin/dvd.h>
@ -320,3 +323,4 @@ s32 CARDWrite(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset);
#endif #endif
#endif #endif
#endif

View File

@ -45,6 +45,10 @@
#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1)) #define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1))
#define TRUNC(n, a) (((u32)(n)) & ~((a)-1)) #define TRUNC(n, a) (((u32)(n)) & ~((a)-1))
#ifndef decltype
#define decltype __decltype__
#endif
#define JUT_EXPECT(...) #define JUT_EXPECT(...)
#define _SDA_BASE_(dummy) 0 #define _SDA_BASE_(dummy) 0
@ -77,6 +81,9 @@ void* __memcpy(void*, const void*, int);
#define SQUARE(x) ((x) * (x)) #define SQUARE(x) ((x) * (x))
#define POINTER_ADD_TYPE(type_, ptr_, offset_) ((type_)((unsigned long)(ptr_) + (unsigned long)(offset_)))
#define POINTER_ADD(ptr_, offset_) POINTER_ADD_TYPE(__typeof__(ptr_), ptr_, offset_)
// floating-point constants // floating-point constants
#define _HUGE_ENUF 1e+300 #define _HUGE_ENUF 1e+300
#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
@ -91,6 +98,14 @@ static const float INF = 2000000000.0f;
#define READU32_BE(ptr, offset) \ #define READU32_BE(ptr, offset) \
(((u32)ptr[offset] << 24) | ((u32)ptr[offset + 1] << 16) | ((u32)ptr[offset + 2] << 8) | (u32)ptr[offset + 3]); (((u32)ptr[offset] << 24) | ((u32)ptr[offset + 1] << 16) | ((u32)ptr[offset + 2] << 8) | (u32)ptr[offset + 3]);
#ifndef NO_INLINE
#ifdef __MWERKS__
#define NO_INLINE __attribute__((never_inline))
#else
#define NO_INLINE
#endif
#endif
// Hack to trick the compiler into not inlining functions that use this macro. // Hack to trick the compiler into not inlining functions that use this macro.
#define FORCE_DONT_INLINE \ #define FORCE_DONT_INLINE \
(void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; \ (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; \

View File

@ -1,7 +1,7 @@
#ifndef M_DO_M_DO_PRINTF_H #ifndef M_DO_M_DO_PRINTF_H
#define M_DO_M_DO_PRINTF_H #define M_DO_M_DO_PRINTF_H
#include "__va_arg.h" #include <dolphin/os.h>
void my_PutString(const char*); void my_PutString(const char*);
void mDoPrintf_vprintf_Interrupt(char const*, va_list); void mDoPrintf_vprintf_Interrupt(char const*, va_list);

67
include/revolution/arc.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef _REVOLUTION_ARC_H_
#define _REVOLUTION_ARC_H_
#include <revolution/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define ARC_ENTRY_NUM_INVALID (-1)
typedef struct {
unsigned int magic;
int fstStart;
int fstSize;
int fileStart;
int pad[4];
} ARCHeader;
typedef struct {
void* archiveStartAddr; // 0x0
void* FSTStart; // 0x4
void* fileStart; // 0x8
u32 entryNum; // 0xC
char* FSTStringStart; // 0x10
u32 FSTLength; // 0x14
u32 currDir; // 0x18
} ARCHandle;
typedef struct {
ARCHandle* handle;
u32 startOffset;
u32 length;
} ARCFileInfo;
typedef struct {
ARCHandle* handle;
u32 entryNum;
u32 location;
u32 next;
} ARCDir;
typedef struct {
ARCHandle* handle;
u32 entryNum;
BOOL isDir;
char* name;
} ARCDirEntry;
BOOL ARCInitHandle(void*, ARCHandle*);
BOOL ARCFastOpen(ARCHandle*, s32, ARCFileInfo*);
s32 ARCConvertPathToEntrynum(ARCHandle*, const char*);
void* ARCGetStartAddrInMem(ARCFileInfo*);
u32 ARCGetLength(ARCFileInfo*);
BOOL ARCClose(ARCFileInfo*);
BOOL ARCChangeDir(ARCHandle*, const char*);
BOOL ARCGetCurrentDir(ARCHandle*, char*, u32);
BOOL ARCOpenDir(ARCHandle*, const char*, ARCDir*);
BOOL ARCReadDir(ARCDir*, ARCDirEntry*);
BOOL ARCCloseDir(ARCDir*);
#ifdef __cplusplus
}
#endif
#endif // _REVOLUTION_ARC_H_

View File

@ -7,6 +7,16 @@
extern "C" { extern "C" {
#endif #endif
#define AX_SAMPLE_RATE 32000
#define AX_SAMPLES_PER_FRAME 96
#define AX_SAMPLE_DEPTH_BYTES sizeof(u32)
#define AX_SAMPLES_PER_FRAME_RMT 18
#define AX_FRAME_SIZE (AX_SAMPLES_PER_FRAME * AX_SAMPLE_DEPTH_BYTES)
#define AX_MAX_VOLUME 32768
#define AX_VOICE_STOP 0
#define AX_VOICE_RUN 1
typedef struct _AXPBMIX { typedef struct _AXPBMIX {
/* 0x00 */ u16 vL; /* 0x00 */ u16 vL;
/* 0x02 */ u16 vDeltaL; /* 0x02 */ u16 vDeltaL;
@ -210,7 +220,45 @@ typedef struct AX_AUX_DATA_DPL2 {
/* 0x00 */ s32* rs; /* 0x00 */ s32* rs;
} AX_AUX_DATA_DPL2; } AX_AUX_DATA_DPL2;
typedef struct _AXPBRMTMIX {
/* 0x0 */ u16 vMain0;
/* 0x2 */ u16 vDeltaMain0;
/* 0x4 */ u16 vAux0;
/* 0x6 */ u16 vDeltaAux0;
/* 0x8 */ u16 vMain1;
/* 0xA */ u16 vDeltaMain1;
/* 0xC */ u16 vAux1;
/* 0xE */ u16 vDeltaAux1;
/* 0x10 */ u16 vMain2;
/* 0x12 */ u16 vDeltaMain2;
/* 0x14 */ u16 vAux2;
/* 0x16 */ u16 vDeltaAux2;
/* 0x18 */ u16 vMain3;
/* 0x1A */ u16 vDeltaMain3;
/* 0x1C */ u16 vAux3;
/* 0x1E */ u16 vDeltaAux3;
} AXPBRMTMIX;
typedef struct _AXPBBIQUAD {
/* 0x0 */ u16 on;
/* 0x2 */ u16 xn1;
/* 0x4 */ u16 xn2;
/* 0x6 */ u16 yn1;
/* 0x8 */ u16 yn2;
/* 0xA */ u16 b0;
/* 0xC */ u16 b1;
/* 0xE */ u16 b2;
/* 0x10 */ u16 a1;
/* 0x12 */ u16 a2;
} AXPBBIQUAD;
typedef union __AXPBRMTIIR {
AXPBLPF lpf;
AXPBBIQUAD biquad;
} AXPBRMTIIR;
typedef void (*AXCallback)(); typedef void (*AXCallback)();
typedef void (*AXAuxCallback)(void* chans, void* context);
#define AX_DSP_SLAVE_LENGTH 0xF80 #define AX_DSP_SLAVE_LENGTH 0xF80
#define AX_MAX_VOICES 64 #define AX_MAX_VOICES 64
@ -268,7 +316,7 @@ AXVPB* AXAcquireVoice(u32 priority, void (*callback)(void *), u32 userContext);
void AXSetVoicePriority(AXVPB* p, u32 priority); void AXSetVoicePriority(AXVPB* p, u32 priority);
// AXAux // AXAux
void AXRegisterAuxACallback(void (*callback)(void*, void*), void* context); void AXRegisterAuxACallback(AXAuxCallback callback, void* context);
void AXRegisterAuxBCallback(void (*callback)(void*, void*), void* context); void AXRegisterAuxBCallback(void (*callback)(void*, void*), void* context);
// AXCL // AXCL

View File

@ -2,6 +2,7 @@
#define _REVOLUTION_AXFX_H_ #define _REVOLUTION_AXFX_H_
#include <revolution/types.h> #include <revolution/types.h>
#include <revolution/ax.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -158,6 +159,9 @@ typedef struct AXFX_CHORUS {
/* 0x98 */ u32 period; /* 0x98 */ u32 period;
} AXFX_CHORUS; } AXFX_CHORUS;
typedef void* (*AXFXAllocFunc)(u32);
typedef void (*AXFXFreeFunc)(void*);
// chorus // chorus
int AXFXChorusInit(AXFX_CHORUS* c); int AXFXChorusInit(AXFX_CHORUS* c);
int AXFXChorusShutdown(AXFX_CHORUS* c); int AXFXChorusShutdown(AXFX_CHORUS* c);
@ -168,14 +172,13 @@ void AXFXChorusCallback(AXFX_BUFFERUPDATE* bufferUpdate, AXFX_CHORUS* chorus);
void AXFXDelayCallback(AXFX_BUFFERUPDATE* bufferUpdate, AXFX_DELAY* delay); void AXFXDelayCallback(AXFX_BUFFERUPDATE* bufferUpdate, AXFX_DELAY* delay);
int AXFXDelaySettings(AXFX_DELAY* delay); int AXFXDelaySettings(AXFX_DELAY* delay);
int AXFXDelayInit(AXFX_DELAY* delay); int AXFXDelayInit(AXFX_DELAY* delay);
int AXFXDelayShutdown(AXFX_DELAY* delay); int AXFXDelayShutdown(AXFX_DELAY* delay);
// reverb_hi // reverb_hi
void DoCrossTalk(s32* l, s32* r, f32 cross, f32 invcross); void DoCrossTalk(s32* l, s32* r, f32 cross, f32 invcross);
int AXFXReverbHiInit(AXFX_REVERBHI* rev); int AXFXReverbHiInit(AXFX_REVERBHI* rev);
int AXFXReverbHiShutdown(AXFX_REVERBHI* rev); int AXFXReverbHiShutdown(AXFX_REVERBHI* rev);
int AXFXReverbHiSettings(AXFX_REVERBHI* rev); int AXFXReverbHiSettings(AXFX_REVERBHI* rev);
void AXFXReverbHiCallback(AXFX_BUFFERUPDATE* bufferUpdate, AXFX_REVERBHI* reverb);
// reverb_hi_4ch // reverb_hi_4ch
int AXFXReverbHiInitDpl2(AXFX_REVERBHI_DPL2* reverb); int AXFXReverbHiInitDpl2(AXFX_REVERBHI_DPL2* reverb);
@ -189,8 +192,23 @@ int AXFXReverbStdShutdown(AXFX_REVERBSTD* rev);
int AXFXReverbStdSettings(AXFX_REVERBSTD* rev); int AXFXReverbStdSettings(AXFX_REVERBSTD* rev);
void AXFXReverbStdCallback(AXFX_BUFFERUPDATE* bufferUpdate, AXFX_REVERBSTD* reverb); void AXFXReverbStdCallback(AXFX_BUFFERUPDATE* bufferUpdate, AXFX_REVERBSTD* reverb);
void AXFXReverbHiCallback(void *data, void *context);
void AXGetAuxACallback(AXAuxCallback* cbOut, void** contextOut);
void AXFXSetHooks(AXFXAllocFunc alloc, AXFXFreeFunc free);
void AXFXGetHooks(AXFXAllocFunc* allocOut, AXFXFreeFunc* freeOut);
BOOL AXFXReverbHiInit(AXFX_REVERBHI* reverbHi);
BOOL AXFXReverbHiShutdown(AXFX_REVERBHI* reverbHi);
u16 AXGetAuxAReturnVolume(void);
u16 AXGetAuxBReturnVolume(void);
u16 AXGetAuxCReturnVolume(void);
void AXSetAuxAReturnVolume(u16 volume);
void AXSetAuxBReturnVolume(u16 volume);
void AXSetAuxCReturnVolume(u16 volume);
void AXSetMasterVolume(u16 volume);
u16 AXGetMasterVolume(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif // _REVOLUTION_AXFX_H_ #endif // _REVOLUTION_AXFX_H_

322
include/revolution/card.h Normal file
View File

@ -0,0 +1,322 @@
#ifndef _REVOLUTION_CARD_H_
#define _REVOLUTION_CARD_H_
#include <revolution/os.h>
#include <revolution/dsp.h>
#include <revolution/dvd.h>
#ifdef __cplusplus
extern "C" {
#endif
#define CARD_FILENAME_MAX 32
#define CARD_MAX_FILE 127
#define CARD_ICON_MAX 8
typedef void (*CARDCallback)(s32 chan, s32 result);
typedef struct CARDFileInfo {
s32 chan;
s32 fileNo;
s32 offset;
s32 length;
u16 iBlock;
} CARDFileInfo;
typedef struct CARDDir {
u8 gameName[4];
u8 company[2];
u8 _padding0;
u8 bannerFormat;
u8 fileName[CARD_FILENAME_MAX];
u32 time; // seconds since 01/01/2000 midnight
u32 iconAddr; // 0xffffffff if not used
u16 iconFormat;
u16 iconSpeed;
u8 permission;
u8 copyTimes;
u16 startBlock;
u16 length;
u8 _padding1[2];
u32 commentAddr; // 0xffffffff if not used
} CARDDir;
typedef struct CARDControl {
/* 0x000 */ BOOL attached;
/* 0x004 */ s32 result;
/* 0x008 */ u16 size;
/* 0x00A */ u16 pageSize;
/* 0x00C */ s32 sectorSize;
/* 0x010 */ u16 cBlock;
/* 0x012 */ u16 vendorID;
/* 0x014 */ s32 latency;
/* 0x018 */ u8 id[12];
/* 0x024 */ int mountStep;
/* 0x028 */ int formatStep;
/* 0x028 */ u32 scramble;
/* 0x02C */ DSPTaskInfo task;
/* 0x080 */ void* workArea;
/* 0x084 */ CARDDir *currentDir;
/* 0x088 */ u16* currentFat;
/* 0x08C */ OSThreadQueue threadQueue;
/* 0x094 */ u8 cmd[9];
/* 0x0A0 */ s32 cmdlen;
/* 0x0A4 */ volatile u32 mode;
/* 0x0A8 */ int retry;
/* 0x0AC */ int repeat;
/* 0x0B0 */ u32 addr;
/* 0x0B4 */ void* buffer;
/* 0x0B8 */ s32 xferred;
/* 0x0BC */ u16 freeNo;
/* 0x0BE */ u16 startBlock;
/* 0x0C0 */ CARDFileInfo* fileInfo;
/* 0x0C4 */ CARDCallback extCallback;
/* 0x0C8 */ CARDCallback txCallback;
/* 0x0CC */ CARDCallback exiCallback;
/* 0x0D0 */ CARDCallback apiCallback;
/* 0x0D4 */ CARDCallback xferCallback;
/* 0x0D8 */ CARDCallback eraseCallback;
/* 0x0DC */ CARDCallback unlockCallback;
/* 0x0E0 */ OSAlarm alarm;
/* 0x108 */ u32 cid;
/* 0x10C */ const DVDDiskID* diskID;
} CARDControl;
typedef struct CARDDecParam {
/* 0x00 */ u8* inputAddr;
/* 0x04 */ u32 inputLength;
/* 0x08 */ u32 aramAddr;
/* 0x0C */ u8* outputAddr;
} CARDDecParam;
typedef struct CARDID {
/* 0x000 */ u8 serial[32];
/* 0x020 */ u16 deviceID;
/* 0x022 */ u16 size;
/* 0x024 */ u16 encode;
/* 0x026 */ u8 padding[470];
/* 0x1FC */ u16 checkSum;
/* 0x1FE */ u16 checkSumInv;
} CARDID;
typedef struct CARDDirCheck {
/* 0x00 */ u8 padding0[56];
/* 0x38 */ u16 padding1;
/* 0x3A */ s16 checkCode;
/* 0x3C */ u16 checkSum;
/* 0x3E */ u16 checkSumInv;
} CARDDirCheck;
typedef struct CARDStat {
/* 0x00 */ char fileName[CARD_FILENAME_MAX];
/* 0x20 */ u32 length;
/* 0x24 */ u32 time;
/* 0x28 */ u8 gameName[4];
/* 0x2C */ u8 company[2];
/* 0x2E */ u8 bannerFormat;
/* 0x30 */ u32 iconAddr;
/* 0x34 */ u16 iconFormat;
/* 0x36 */ u16 iconSpeed;
/* 0x38 */ u32 commentAddr;
/* 0x3C */ u32 offsetBanner;
/* 0x40 */ u32 offsetBannerTlut;
/* 0x44 */ u32 offsetIcon[CARD_ICON_MAX];
/* 0x64 */ u32 offsetIconTlut;
/* 0x68 */ u32 offsetData;
} CARDStat;
#define CARD_ATTR_PUBLIC 0x04u
#define CARD_ATTR_NO_COPY 0x08u
#define CARD_ATTR_NO_MOVE 0x10u
#define CARD_ATTR_GLOBAL 0x20u
#define CARD_ATTR_COMPANY 0x40u
#define CARD_FAT_AVAIL 0x0000u
#define CARD_FAT_CHECKSUM 0x0000u
#define CARD_FAT_CHECKSUMINV 0x0001u
#define CARD_FAT_CHECKCODE 0x0002u
#define CARD_FAT_FREEBLOCKS 0x0003u
#define CARD_FAT_LASTSLOT 0x0004u
#define CARD_WORKAREA_SIZE (5 * 8 * 1024)
#define CARD_SEG_SIZE 0x200u
#define CARD_PAGE_SIZE 0x80u
#define CARD_MAX_SIZE 0x01000000U
#define CARD_NUM_SYSTEM_BLOCK 5
#define CARD_SYSTEM_BLOCK_SIZE (8 * 1024u)
#define CARD_MAX_MOUNT_STEP (CARD_NUM_SYSTEM_BLOCK + 2)
#define CARD_STAT_SPEED_END 0
#define CARD_STAT_SPEED_FAST 1
#define CARD_STAT_SPEED_MIDDLE 2
#define CARD_STAT_SPEED_SLOW 3
#define CARD_STAT_SPEED_MASK 3
#define CARD_STAT_ANIM_LOOP 0
#define CARD_STAT_ANIM_BOUNCE 4
#define CARD_STAT_ANIM_MASK 0x4
#define CARD_RESULT_UNLOCKED 1
#define CARD_RESULT_READY 0
#define CARD_RESULT_BUSY -1
#define CARD_RESULT_WRONGDEVICE -2
#define CARD_RESULT_NOCARD -3
#define CARD_RESULT_NOFILE -4
#define CARD_RESULT_IOERROR -5
#define CARD_RESULT_BROKEN -6
#define CARD_RESULT_EXIST -7
#define CARD_RESULT_NOENT -8
#define CARD_RESULT_INSSPACE -9
#define CARD_RESULT_NOPERM -10
#define CARD_RESULT_LIMIT -11
#define CARD_RESULT_NAMETOOLONG -12
#define CARD_RESULT_ENCODING -13
#define CARD_RESULT_CANCELED -14
#define CARD_RESULT_FATAL_ERROR -128
#define CARDIsValidBlockNo(card, blockNo) ((blockNo) >= CARD_NUM_SYSTEM_BLOCK && (blockNo) < (card)->cBlock)
#define CARD_READ_SIZE 512
#define CARD_COMMENT_SIZE 64
#define CARD_ICON_WIDTH 32
#define CARD_ICON_HEIGHT 32
#define CARD_BANNER_WIDTH 96
#define CARD_BANNER_HEIGHT 32
#define CARD_STAT_ICON_NONE 0
#define CARD_STAT_ICON_C8 1
#define CARD_STAT_ICON_RGB5A3 2
#define CARD_STAT_ICON_MASK 3
#define CARD_STAT_BANNER_NONE 0
#define CARD_STAT_BANNER_C8 1
#define CARD_STAT_BANNER_RGB5A3 2
#define CARD_STAT_BANNER_MASK 3
#define CARD_ENCODE_ANSI 0
#define CARD_ENCODE_SJIS 1
#define CARDGetDirCheck(dir) ((CARDDirCheck*)&(dir)[CARD_MAX_FILE])
#define CARDGetBannerFormat(stat) (((stat)->bannerFormat) & CARD_STAT_BANNER_MASK)
#define CARDGetIconAnim(stat) (((stat)->bannerFormat) & CARD_STAT_ANIM_MASK)
#define CARDGetIconFormat(stat, n) (((stat)->iconFormat >> (2 * (n))) & CARD_STAT_ICON_MASK)
#define CARDGetIconSpeed(stat, n) (((stat)->iconSpeed >> (2 * (n))) & CARD_STAT_SPEED_MASK)
#define CARDSetBannerFormat(stat, f) \
((stat)->bannerFormat = (u8)(((stat)->bannerFormat & ~CARD_STAT_BANNER_MASK) | (f)))
#define CARDSetIconAnim(stat, f) \
((stat)->bannerFormat = (u8)(((stat)->bannerFormat & ~CARD_STAT_ANIM_MASK) | (f)))
#define CARDSetIconFormat(stat, n, f) \
((stat)->iconFormat = \
(u16)(((stat)->iconFormat & ~(CARD_STAT_ICON_MASK << (2 * (n)))) | ((f) << (2 * (n)))))
#define CARDSetIconSpeed(stat, n, f) \
((stat)->iconSpeed = \
(u16)(((stat)->iconSpeed & ~(CARD_STAT_SPEED_MASK << (2 * (n)))) | ((f) << (2 * (n)))))
#define CARDSetIconAddress(stat, addr) ((stat)->iconAddr = (u32)(addr))
#define CARDSetCommentAddress(stat, addr) ((stat)->commentAddr = (u32)(addr))
#define CARDGetFileNo(fileInfo) ((fileInfo)->fileNo)
extern u32 __CARDFreq;
#if DEBUG
#define CARDFreq __CARDFreq
#else
#define CARDFreq EXI_FREQ_16M
#endif
void CARDInit(void);
s32 CARDGetResultCode(s32 chan);
s32 CARDCheckAsync(s32 chan, CARDCallback callback);
s32 CARDFreeBlocks(s32 chan, s32* byteNotUsed, s32* filesNotUsed);
s32 CARDRenameAsync(s32 chan, const char* oldName, const char* newName, CARDCallback callback);
// CARDBios
void CARDInit(void);
s32 CARDGetResultCode(s32 chan);
s32 CARDFreeBlocks(s32 chan, s32* byteNotUsed, s32* filesNotUsed);
s32 CARDGetEncoding(s32 chan, u16* encode);
s32 CARDGetMemSize(s32 chan, u16* size);
s32 CARDGetSectorSize(s32 chan, u32* size);
const DVDDiskID* CARDGetDiskID(s32 chan);
s32 CARDSetDiskID(s32 chan, const DVDDiskID* diskID);
BOOL CARDSetFastMode(BOOL enable);
BOOL CARDGetFastMode(void);
s32 CARDGetCurrentMode(s32 chan, u32* mode);
// CARDCheck
s32 CARDCheckExAsync(s32 chan, s32* xferBytes, CARDCallback callback);
s32 CARDCheckAsync(s32 chan, CARDCallback callback);
s32 CARDCheckEx(s32 chan, s32* xferBytes);
s32 CARDCheck(s32 chan);
// CARDCreate
s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo, CARDCallback callback);
s32 CARDCreate(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo);
// CARDDelete
s32 CARDFastDeleteAsync(s32 chan, s32 fileNo, CARDCallback callback);
s32 CARDFastDelete(s32 chan, s32 fileNo);
s32 CARDDeleteAsync(s32 chan, const char* fileName, CARDCallback callback);
s32 CARDDelete(s32 chan, const char* fileName);
// CARDErase
s32 CARDEraseAsync(CARDFileInfo* fileInfo, s32 length, s32 offset, CARDCallback callback);
s32 CARDErase(CARDFileInfo* fileInfo, s32 length, s32 offset);
// CARDFormat
s32 CARDFormat(s32 chan);
// CARDMount
int CARDProbe(s32 chan);
s32 CARDProbeEx(s32 chan, s32* memSize, s32* sectorSize);
s32 CARDMountAsync(s32 chan, void* workArea, CARDCallback detachCallback, CARDCallback attachCallback);
s32 CARDMount(s32 chan, void* workArea, CARDCallback detachCallback);
s32 CARDUnmount(s32 chan);
// CARDNet
u16 CARDSetVendorID(u16 vendorID);
u16 CARDGetVendorID();
s32 CARDGetSerialNo(s32 chan, u64* serialNo);
s32 CARDGetUniqueCode(s32 chan, u64* uniqueCode);
s32 CARDGetAttributes(s32 chan, s32 fileNo, u8* attr);
s32 CARDSetAttributesAsync(s32 chan, s32 fileNo, u8 attr, CARDCallback callback);
s32 CARDSetAttributes(s32 chan, s32 fileNo, u8 attr);
// CARDOpen
s32 CARDFastOpen(s32 chan, s32 fileNo, CARDFileInfo* fileInfo);
s32 CARDOpen(s32 chan, const char* fileName, CARDFileInfo* fileInfo);
s32 CARDClose(CARDFileInfo* fileInfo);
// CARDProgram
s32 CARDProgramAsync(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset, CARDCallback callback);
s32 CARDProgram(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset);
// CARDRdwr
s32 CARDGetXferredBytes(s32 chan);
// CARDRead
s32 CARDReadAsync(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset, CARDCallback callback);
s32 CARDRead(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset);
s32 CARDCancel(CARDFileInfo* fileInfo);
// CARDRename
s32 CARDRename(s32 chan, const char* oldName, const char* newName);
// CARDStat
s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat* stat);
s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat* stat, CARDCallback callback);
s32 CARDSetStatus(s32 chan, s32 fileNo, CARDStat* stat);
// CARDWrite
s32 CARDWriteAsync(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset, CARDCallback callback);
s32 CARDWrite(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -2,10 +2,14 @@
#define _REVOLUTION_HBM_H_ #define _REVOLUTION_HBM_H_
#include <revolution/kpad.h> #include <revolution/kpad.h>
#include <revolution/mem.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define NW4HBM_VERSION(major, minor) ((major & 0xFF) << 8 | minor & 0xFF)
typedef enum HBMSelectBtnNum { typedef enum HBMSelectBtnNum {
HBM_SELECT_NULL = -1, HBM_SELECT_NULL = -1,
@ -18,8 +22,45 @@ typedef enum HBMSelectBtnNum {
HBM_SELECT_MAX HBM_SELECT_MAX
} HBMSelectBtnNum; } HBMSelectBtnNum;
// TODO: move this later enum HBMSoundEvent_et {
typedef struct MEMAllocator MEMAllocator; HBM_SOUND_EVENT_0, // StartInitSound? and then num would not matter
HBM_SOUND_EVENT_1, // EndInitSound? and then num would not matter
HBM_SOUND_EVENT_2, // Fadeout, num = ms? see calc_fadeoutAnm
HBM_SOUND_EVENT_3, // Blackout, num = ms? from various
HBM_SOUND_EVENT_4, // ShutdownSound? and then num would not matter
HBM_SOUND_EVENT_PLAY, /* num = HBMSound_et (see below) */
};
enum HBMSound_et {
HBM_SOUND_HOME_BUTTON,
HBM_SOUND_RETURN_APP,
HBM_SOUND_GOTO_MENU,
HBM_SOUND_RESET_APP,
HBM_SOUND_FOCUS,
HBM_SOUND_SELECT,
HBM_SOUND_CANCEL,
HBM_SOUND_OPEN_CONTROLLER,
HBM_SOUND_CLOSE_CONTROLLER,
HBM_SOUND_VOLUME_PLUS,
HBM_SOUND_VOLUME_MINUS,
HBM_SOUND_VOLUME_PLUS_LIMIT,
HBM_SOUND_VOLUME_MINUS_LIMIT,
HBM_SOUND_NOTHING_DONE,
HBM_SOUND_VIBE_ON,
HBM_SOUND_VIBE_OFF,
HBM_SOUND_START_CONNECT_WINDOW,
HBM_SOUND_CONNECTED1,
HBM_SOUND_CONNECTED2,
HBM_SOUND_CONNECTED3,
HBM_SOUND_CONNECTED4,
HBM_SOUND_END_CONNECT_WINDOW,
HBM_SOUND_MANUAL_OPEN,
HBM_SOUND_MANUAL_FOCUS,
HBM_SOUND_MANUAL_SELECT,
HBM_SOUND_MANUAL_SCROLL,
HBM_SOUND_MANUAL_CANCEL,
HBM_SOUND_MANUAL_RETURN_APP
};
typedef int HBMSoundCallback(int evt, int num); typedef int HBMSoundCallback(int evt, int num);
typedef struct HBMDataInfo { typedef struct HBMDataInfo {
@ -32,11 +73,11 @@ typedef struct HBMDataInfo {
/* 0x18 */ int backFlag; /* 0x18 */ int backFlag;
/* 0x1C */ int region; /* 0x1C */ int region;
/* 0x20 */ int cursor; /* 0x20 */ int cursor;
/* 0x24 */ u32 memSize; /* 0x28 */ u32 memSize;
/* 0x28 */ f32 frameDelta; /* 0x2C */ f32 frameDelta;
/* 0x2C */ Vec2 adjust; /* 0x30 */ Vec2 adjust;
/* 0x34 */ MEMAllocator* pAllocator; /* 0x38 */ MEMAllocator* pAllocator;
} HBMDataInfo; // size 0x38 } HBMDataInfo; // size 0x3C
typedef struct HBMKPadData { typedef struct HBMKPadData {
KPADStatus* kpad; KPADStatus* kpad;

8
include/revolution/mem.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef _REVOLUTION_MEM_H_
#define _REVOLUTION_MEM_H_
#include <revolution/mem/allocator.h>
#include <revolution/mem/expHeap.h>
#include <revolution/mem/heapCommon.h>
#endif // _REVOLUTION_MEM_H_

View File

@ -0,0 +1,37 @@
#ifndef _REVOLUTION_MEM_ALLOCATOR_H_
#define _REVOLUTION_MEM_ALLOCATOR_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <revolution/mem/heapCommon.h>
#include <revolution/types.h>
typedef struct MEMAllocator MEMAllocator;
typedef void* (*MEMFuncAllocatorAlloc)(MEMAllocator* pAllocator, u32 size);
typedef void (*MEMFuncAllocatorFree)(MEMAllocator* pAllocator, void* memBlock);
typedef struct MEMAllocatorFunc MEMAllocatorFunc;
struct MEMAllocatorFunc {
MEMFuncAllocatorAlloc pfAlloc;
MEMFuncAllocatorFree pfFree;
};
struct MEMAllocator {
const MEMAllocatorFunc* pFunc;
void* pHeap;
u32 heapParam1;
u32 heapParam2;
};
void* MEMAllocFromAllocator(MEMAllocator*, u32);
void MEMFreeToAllocator(MEMAllocator*, void*);
void MEMInitAllocatorForExpHeap(MEMAllocator*, MEMHeapHandle, int);
void MEMInitAllocatorForFrmHeap(MEMAllocator* allocator, struct MEMiHeapHead* heap, s32 align);
#ifdef __cplusplus
}
#endif
#endif // _REVOLUTION_MEM_ALLOCATOR_H_

View File

@ -0,0 +1,50 @@
#ifndef _REVOLUTION_MEM_EXPHEAP_H_
#define _REVOLUTION_MEM_EXPHEAP_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <revolution/mem/heapCommon.h>
typedef struct MEMiExpHeapMBlockHead MEMiExpHeapMBlockHead;
struct MEMiExPheapMBlockHead {
u16 signature;
union {
u16 val;
struct {
u16 allocDir : 1;
u16 alignment : 7;
u16 groupID : 8;
} fields;
} attribute;
u32 blockSize;
MEMiExpHeapMBlockHead* prev;
MEMiExpHeapMBlockHead* next;
};
MEMHeapHandle MEMCreateExpHeapEx(void*, u32, u16);
void* MEMDestroyExpHeap(MEMHeapHandle);
void* MEMAllocFromExpHeapEx(MEMHeapHandle, u32, int);
void MEMFreeToExpHeap(MEMHeapHandle, void*);
u32 MEMGetAllocatableSizeForExpHeapEx(MEMHeapHandle, int);
MEMHeapHandle MEMCreateFrmHeapEx(void* start, u32 size, u16 opt);
MEMHeapHandle MEMDestroyFrmHeap(MEMHeapHandle heap);
static inline MEMHeapHandle MEMCreateExpHeap(void* start, u32 size) {
return MEMCreateExpHeapEx(start, size, 0);
}
static inline void* MEMAllocFromExpHeap(MEMHeapHandle heap, u32 size) {
return MEMAllocFromExpHeapEx(heap, size, 4);
}
#ifdef __cplusplus
}
#endif
#endif // _REVOLUTION_MEM_EXPHEAP_H_

View File

@ -0,0 +1,43 @@
#ifndef _REVOLUTION_MEM_HEAPCOMMON_H_
#define _REVOLUTION_MEM_HEAPCOMMON_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <revolution/mem/list.h>
#include <revolution/os.h>
typedef struct MEMiHeapHead MEMiHeapHead;
struct MEMiHeapHead {
u32 signature;
MEMLink link;
MEMList childList;
void* heapStart;
void* heapEnd;
OSMutex mutex;
union {
u32 val;
struct {
u32 reserved : 24;
u32 optFlag : 8;
} fields;
} attribute;
};
typedef MEMiHeapHead* MEMHeapHandle;
typedef u32 UIntPtr;
static inline UIntPtr GetUIntPtr(const void* ptr) {
return (UIntPtr)(ptr);
}
#ifdef __cplusplus
}
#endif
#endif // _REVOLUTION_MEM_HEAPCOMMON_H_

View File

@ -0,0 +1,31 @@
#ifndef _REVOLUTION_MEM_LIST_H_
#define _REVOLUTION_MEM_LIST_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <revolution/types.h>
typedef struct {
void* prev;
void* next;
} MEMLink;
typedef struct {
void* head;
void* tail;
u16 num;
u16 offs;
} MEMList;
void MEMInitList(MEMList*, u16);
void MEMAppendListObject(MEMList*, void*);
void MEMRemoveListObject(MEMList*, void*);
void* MEMGetNextListObject(MEMList*, void*);
#ifdef __cplusplus
}
#endif
#endif // _REVOLUTION_MEM_LIST_H_

View File

@ -11,6 +11,8 @@ typedef struct Vec {
f32 x, y, z; f32 x, y, z;
} Vec, *VecPtr, Point3d, *Point3dPtr; } Vec, *VecPtr, Point3d, *Point3dPtr;
typedef const VecPtr CVecPtr;
typedef struct { typedef struct {
s16 x, y, z; s16 x, y, z;
} S16Vec, *S16VecPtr; } S16Vec, *S16VecPtr;

View File

@ -320,46 +320,98 @@ extern BOOL __OSInReboot;
#define ASSERT(cond) ASSERTLINE(__LINE__, cond) #define ASSERT(cond) ASSERTLINE(__LINE__, cond)
inline s16 __OSf32tos16(__REGISTER f32 inF) { static inline u8 __OSf32tou8(register f32 in) {
#ifdef __MWERKS__ f32 a;
register s16 out; register f32* ptr = &a;
u32 tmp; u8 r;
register u32* tmpPtr = &tmp;
// clang-format off
asm { #if defined(__MWERKS__)
psq_st inF, 0(tmpPtr), 0x1, 5 asm { psq_st in, 0(ptr), 1, 2 };
lha out, 0(tmpPtr) #else
} # pragma unused(in)
// clang-format on
return out;
#endif #endif
r = *(u8 *)ptr;
return r;
} }
inline void OSf32tos16(f32* f, s16* out) { static inline u16 __OSf32tou16(register f32 in) {
*out = __OSf32tos16(*f); f32 a;
} register f32* ptr = &a;
u16 r;
inline u8 __OSf32tou8(__REGISTER f32 inF) { #if defined(__MWERKS__)
#ifdef __MWERKS__ asm { psq_st in, 0(ptr), 1, 3 };
register u8 out; #else
u32 tmp; # pragma unused(in)
register u32* tmpPtr = &tmp;
// clang-format off
asm {
psq_st inF, 0(tmpPtr), 0x1, 2
lbz out, 0(tmpPtr)
}
// clang-format on
return out;
#endif #endif
r = *(u16 *)ptr;
return r;
} }
inline void OSf32tou8(f32* f, u8* out) { static inline s16 __OSf32tos16(register f32 in) {
*out = __OSf32tou8(*f); f32 a;
register f32* ptr = &a;
s16 r;
#if defined(__MWERKS__)
asm { psq_st in, 0(ptr), 1, 5 };
#else
# pragma unused(in)
#endif
r = *(s16*)ptr;
return r;
}
static inline f32 __OSu16tof32(register u16 const* arg) {
register f32 ret;
#if defined(__MWERKS__)
asm { psq_l ret, 0(arg), 1, 3 };
#else
# pragma unused(arg)
ret = 0;
#endif
return ret;
}
static inline f32 __OSs16tof32(register s16 const* arg) {
register f32 ret;
#if defined(__MWERKS__)
asm { psq_l ret, 0(arg), 1, 5 };
#else
# pragma unused(arg)
ret = 0;
#endif
return ret;
}
static inline void OSf32tou8(f32 const* in, u8* out) {
*out = __OSf32tou8(*in);
}
static inline void OSf32tou16(f32 const* in, u16* out) {
*out = __OSf32tou16(*in);
}
static inline void OSf32tos16(f32 const* in, s16* out) {
*out = __OSf32tos16(*in);
}
static inline void OSs16tof32(s16 const* in, f32* out) {
*out = __OSs16tof32(in);
}
static inline void OSu16tof32(u16 const* in, f32* out) {
*out = __OSu16tof32(in);
} }
static inline void OSInitFastCast(void) { static inline void OSInitFastCast(void) {

52
include/revolution/tpl.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef _REVOLUTION_TPL_H_
#define _REVOLUTION_TPL_H_
#include <revolution/gx.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
u16 numEntries;
u8 unpacked;
u8 _4;
GXTlutFmt format;
char* data;
} TPLClutHeader, *TPLClutHeaderPtr;
typedef struct {
u16 height;
u16 width;
u32 format;
char* data;
GXTexWrapMode wrapS;
GXTexWrapMode wrapT;
GXTexFilter minFilter;
GXTexFilter magFilter;
f32 LODBias;
u8 edgeLODEnable;
u8 minLOD;
u8 maxLOD;
u8 unpacked;
} TPLHeader, *TPLHeaderPtr;
typedef struct {
TPLHeaderPtr textureHeader;
TPLClutHeaderPtr CLUTHeader;
} TPLDescriptor, *TPLDescriptorPtr;
typedef struct {
u32 versionNumber;
u32 numDescriptors;
TPLDescriptorPtr descriptorArray;
} TPLPalette, *TPLPalettePtr;
void TPLBind(TPLPalettePtr);
TPLDescriptorPtr TPLGet(TPLPalettePtr, u32);
#ifdef __cplusplus
}
#endif
#endif // _REVOLUTION_TPL_H_

View File

@ -11,15 +11,9 @@ typedef enum {
WENC_FLAG_USER_INFO = (1 << 0), WENC_FLAG_USER_INFO = (1 << 0),
} WENCFlag; } WENCFlag;
typedef struct WENCInfo { typedef struct {
/* 0x00 */ s32 xn; u8 data[32];
/* 0x04 */ s32 dl; } WENCInfo; // size 0x20
/* 0x08 */ s32 qn;
/* 0x0C */ s32 dn;
/* 0x10 */ s32 dlh;
/* 0x14 */ s32 dlq;
/* 0x18 */ u8 padding[8];
} WENCInfo;
s32 WENCGetEncodeData(WENCInfo* info, u32 flag, const s16* pcmData, s32 samples, u8* adpcmData); s32 WENCGetEncodeData(WENCInfo* info, u32 flag, const s16* pcmData, s32 samples, u8* adpcmData);

View File

@ -2,6 +2,7 @@
#define _REVOLUTION_WPAD_H_ #define _REVOLUTION_WPAD_H_
#include <revolution/types.h> #include <revolution/types.h>
#include <revolution/sc.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -21,6 +22,22 @@ extern "C" {
#define WPAD_BUTTON_C 0x4000 #define WPAD_BUTTON_C 0x4000
#define WPAD_BUTTON_HOME 0x8000 #define WPAD_BUTTON_HOME 0x8000
#define WPAD_BUTTON_CL_UP (1 << 0)
#define WPAD_BUTTON_CL_LEFT (1 << 1)
#define WPAD_BUTTON_CL_ZR (1 << 2)
#define WPAD_BUTTON_CL_X (1 << 3)
#define WPAD_BUTTON_CL_A (1 << 4)
#define WPAD_BUTTON_CL_Y (1 << 5)
#define WPAD_BUTTON_CL_B (1 << 6)
#define WPAD_BUTTON_CL_ZL (1 << 7)
#define WPAD_BUTTON_CL_FULL_R (1 << 9)
#define WPAD_BUTTON_CL_PLUS (1 << 10)
#define WPAD_BUTTON_CL_HOME (1 << 11)
#define WPAD_BUTTON_CL_MINUS (1 << 12)
#define WPAD_BUTTON_CL_FULL_L (1 << 13)
#define WPAD_BUTTON_CL_DOWN (1 << 14)
#define WPAD_BUTTON_CL_RIGHT (1 << 15)
#define WPAD_MAX_DPD_OBJECTS 4 #define WPAD_MAX_DPD_OBJECTS 4
#define WPAD_CHAN0 0 #define WPAD_CHAN0 0
@ -62,11 +79,44 @@ enum WPADResult_et {
#define WPAD_CE6 (WPAD_E6 + 0) #define WPAD_CE6 (WPAD_E6 + 0)
#define WPAD_CEBADE (WPAD_EBADE + 0) #define WPAD_CEBADE (WPAD_EBADE + 0)
typedef void WPADInitFunc(void); #define WPAD_DEV_CORE 0
typedef void WPADCallback(s32 chan, s32 result); #define WPAD_DEV_FS 1
typedef void WPADExtensionCallback(s32 chan, s32 devType); #define WPAD_DEV_CLASSIC 2
typedef void WPADSamplingCallback(s32 chan); #define WPAD_DEV_BALANCE_CHECKER 3
typedef void WPADConnectCallback(s32 chan, s32 result); #define WPAD_DEV_VSM 4
#define WPAD_DEV_MOTION_PLUS 5
#define WPAD_DEV_MPLS_PT_FS 6
#define WPAD_DEV_MPLS_PT_CLASSIC 7
#define WPAD_DEV_TRAIN 16
#define WPAD_DEV_GUITAR 17
#define WPAD_DEV_DRUM 18
#define WPAD_DEV_TAIKO 19
#define WPAD_DEV_TURNTABLE 20
// seems to be like maybe general purpose non-specific device types
// maybe this was for testing or something? idk
#define WPAD_DEV_BULK_1 21
#define WPAD_DEV_BULK_2 22
#define WPAD_DEV_BULK_3 23
#define WPAD_DEV_BULK_4 24
#define WPAD_DEV_BULK_5 25
#define WPAD_DEV_BULK_6 26
#define WPAD_DEV_BULK_7 27
#define WPAD_DEV_BULK_8 28
#define WPAD_DEV_MPLS_PT_UNKNOWN 250
#define WPAD_DEV_251 251
#define WPAD_DEV_252 252 // invalid device mode?
#define WPAD_DEV_NONE 253 // sort of like WPAD_ENODEV (see __wpadAbortInitExtension in WPADHIDParser.c)
#define WPAD_DEV_INITIALIZING 255 // see __a1_20_status_report
typedef void (*WPADInitFunc)(void);
typedef void (*WPADCallback)(s32 chan, s32 result);
typedef void (*WPADExtensionCallback)(s32 chan, s32 devType);
typedef void (*WPADSamplingCallback)(s32 chan);
typedef void (*WPADConnectCallback)(s32 chan, s32 result);
typedef void (*WPADSimpleSyncCallback)(s32 result, s32 num);
typedef struct DPDObject { typedef struct DPDObject {
/* 0x00 */ s16 x; /* 0x00 */ s16 x;
@ -264,14 +314,33 @@ typedef struct WPADInfo {
#define WPAD_SPEAKER_PLAY 4 #define WPAD_SPEAKER_PLAY 4
#define WPAD_SPEAKER_CMD_05 5 // does the same thing as ENABLE? unless i'm missing something. not used so i don't know the context #define WPAD_SPEAKER_CMD_05 5 // does the same thing as ENABLE? unless i'm missing something. not used so i don't know the context
#define WPAD_MOTOR_STOP 0
#define WPAD_MOTOR_RUMBLE 1
s32 WPADProbe(s32 chan, u32* devType); s32 WPADProbe(s32 chan, u32* devType);
u8 WPADGetRadioSensitivity(s32 chan); u8 WPADGetRadioSensitivity(s32 chan);
void WPADRead(s32 chan, WPADStatus* status); void WPADRead(s32 chan, WPADStatus* status);
BOOL WPADIsSpeakerEnabled(s32 chan); BOOL WPADIsSpeakerEnabled(s32 chan);
s32 WPADControlSpeaker(s32 chan, u32 command, WPADCallback* cb); s32 WPADControlSpeaker(s32 chan, u32 command, WPADCallback cb);
s32 WPADSendStreamData(s32 chan, void* p_buf, u16 len); s32 WPADSendStreamData(s32 chan, void* p_buf, u16 len);
WPADExtensionCallback* WPADSetExtensionCallback(s32 chan, WPADExtensionCallback* cb); WPADConnectCallback WPADSetConnectCallback(s32 chan, WPADConnectCallback cb);
WPADExtensionCallback WPADSetExtensionCallback(s32 chan, WPADExtensionCallback cb);
WPADSimpleSyncCallback WPADSetSimpleSyncCallback(WPADSimpleSyncCallback cb);
BOOL WPADIsUsedCallbackByKPAD(void);
void WPADSetCallbackByKPAD(BOOL isKPAD);
s32 WPADGetInfoAsync(s32 chan, WPADInfo* info, WPADCallback cb);
void WPADControlMotor(s32 chan, u32 command);
BOOL WPADCanSendStreamData(s32 chan);
BOOL WPADStopSimpleSync(void);
void WPADDisconnect(s32 chan);
BOOL WPADStartFastSimpleSync(void);
BOOL WPADSaveConfig(SCFlushCallback* cb);
void WPADSetSpeakerVolume(u8 volume);
u8 WPADGetSpeakerVolume(void);
void WPADEnableMotor(BOOL enabled);
BOOL WPADIsMotorEnabled(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,8 @@
#ifndef STD_NEW_H_
#define STD_NEW_H_
#include <stdio.h>
inline void* (operator new)(size_t, void *ptr) { return ptr; }
#endif

View File

@ -39,6 +39,14 @@ inline float tan(float num) {
return ::i_tanf(num); return ::i_tanf(num);
} }
inline float tanf(float num) {
return ::i_tanf(num);
}
inline float acos(float num) {
return ::acosf(num);
}
inline float pow(float x, float y) { inline float pow(float x, float y) {
return ::pow(x, y); return ::pow(x, y);
} }

View File

@ -6,6 +6,14 @@
namespace std { namespace std {
using ::strlen; using ::strlen;
using ::strcpy; using ::strcpy;
using ::wcslen;
using ::strncpy;
using ::strcmp;
using ::strncmp;
using ::strcat;
using ::memset;
using ::memcpy;
inline char* strchr(char* str, int c) { inline char* strchr(char* str, int c) {
return ::strchr(str, c); return ::strchr(str, c);

View File

@ -15,8 +15,17 @@ int snprintf(char* s, size_t n, const char* format, ...);
int vsnprintf(char* s, size_t n, const char* format, va_list arg); int vsnprintf(char* s, size_t n, const char* format, va_list arg);
int vprintf(const char* format, va_list arg); int vprintf(const char* format, va_list arg);
int vswprintf(wchar_t* s, size_t n, const wchar_t* format, va_list arg);
#if defined(__cplusplus)
namespace std {
extern "C" { using ::vsnprintf; }
extern "C" { using ::vswprintf; }
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _MSL_COMMON_PRINTF_H */ #endif /* _MSL_COMMON_PRINTF_H */

View File

@ -2,6 +2,7 @@
#define _MSL_COMMON_STRING_H #define _MSL_COMMON_STRING_H
#include "stddef.h" #include "stddef.h"
#include "ansi_files.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -22,6 +23,8 @@ char* strncpy(char* dst, const char* src, size_t n);
char* strcpy(char* dst, const char* src); char* strcpy(char* dst, const char* src);
size_t strlen(const char* str); size_t strlen(const char* str);
size_t wcslen(const wchar_t* s);
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif

View File

@ -1000,7 +1000,7 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
if (format.argument_options == long_double_argument) { if (format.argument_options == long_double_argument) {
long_double_num = va_arg(arg, long double); long_double_num = va_arg(arg, long double);
} else { } else {
long_double_num = va_arg(arg, f64); long_double_num = va_arg(arg, double);
} }
if (!(buff_ptr = float2str(long_double_num, buff + 512, format))) { if (!(buff_ptr = float2str(long_double_num, buff + 512, format))) {
@ -1015,7 +1015,7 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
if (format.argument_options == long_double_argument) { if (format.argument_options == long_double_argument) {
long_double_num = va_arg(arg, long double); long_double_num = va_arg(arg, long double);
} else { } else {
long_double_num = va_arg(arg, f64); long_double_num = va_arg(arg, double);
} }
if (!(buff_ptr = double2hex(long_double_num, buff + 512, format))) { if (!(buff_ptr = double2hex(long_double_num, buff + 512, format))) {

View File

@ -1,7 +1,9 @@
#ifndef __VA_ARG_H #ifndef __VA_ARG_H
#define __VA_ARG_H #define __VA_ARG_H
#include "dolphin/types.h" #ifdef __cplusplus
extern "C" {
#endif
typedef struct __va_list_struct { typedef struct __va_list_struct {
char gpr; char gpr;
@ -13,11 +15,7 @@ typedef struct __va_list_struct {
typedef _va_list_struct __va_list[1]; typedef _va_list_struct __va_list[1];
#ifdef __cplusplus
extern "C" void* __va_arg(_va_list_struct*, int);
#else
void* __va_arg(_va_list_struct*, int); void* __va_arg(_va_list_struct*, int);
#endif
#ifndef __MWERKS__ #ifndef __MWERKS__
#define __builtin_va_info(...) #define __builtin_va_info(...)
@ -37,4 +35,12 @@ void* __va_arg(_va_list_struct*, int);
#define __va_copy(a, b) (*(a) = *(b)) #define __va_copy(a, b) (*(a) = *(b))
#if defined(__cplusplus)
namespace std { extern "C" { using ::va_list; } }
#endif
#ifdef __cplusplus
}
#endif
#endif /* __VA_ARG_H */ #endif /* __VA_ARG_H */

View File

@ -5,12 +5,15 @@
#include "Z2AudioLib/Z2SeqMgr.h" #include "Z2AudioLib/Z2SeqMgr.h"
#include "Z2AudioLib/Z2SeMgr.h" #include "Z2AudioLib/Z2SeMgr.h"
#include "Z2AudioLib/Z2SoundInfo.h" #include "Z2AudioLib/Z2SoundInfo.h"
#include "Z2AudioLib/Z2AudioCS.h"
#include "JSystem/JAudio2/JASCalc.h" #include "JSystem/JAudio2/JASCalc.h"
#include "JSystem/JAudio2/JASDriverIF.h" #include "JSystem/JAudio2/JASDriverIF.h"
#include "JSystem/JAudio2/JAUSectionHeap.h" #include "JSystem/JAudio2/JAUSectionHeap.h"
#include "d/d_com_inf_game.h" #include "d/d_com_inf_game.h"
#if PLATFORM_WII || PLATFORM_SHIELD
#include "Z2AudioLib/Z2AudioCS.h"
#endif
u16 seqCallback(JASTrack* track, u16 command) { u16 seqCallback(JASTrack* track, u16 command) {
switch (command) { switch (command) {
case 0x1000: case 0x1000:

View File

@ -0,0 +1,849 @@
#include <revolution/card.h>
#include "__card.h"
const char* __CARDVersion = "<< RVL_SDK - CARD \trelease build: Sep 7 2006 18:26:19 (0x4200_60422) >>";
CARDControl __CARDBlock[2];
static u16 __CARDEncode;
static u16 __CARDFastMode;
DVDDiskID __CARDDiskNone;
// prototypes
static void TimeoutHandler(OSAlarm* alarm, OSContext* context);
static void SetupTimeoutAlarm(CARDControl* card);
static s32 Retry(s32 chan);
static void UnlockedCallback(s32 chan, s32 result);
static BOOL OnShutdown(BOOL f, u32 event);
static OSShutdownFunctionInfo ShutdownFunctionInfo = {OnShutdown, 127};
void __CARDDefaultApiCallback(s32 chan, s32 result) {}
void __CARDSyncCallback(s32 chan, s32 result) {
CARDControl* card;
card = &__CARDBlock[chan];
OSWakeupThread(&card->threadQueue);
}
void __CARDExtHandler(s32 chan, OSContext* context) {
CARDControl* card;
CARDCallback callback;
ASSERTLINE(232, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (card->attached) {
ASSERTLINE(239, card->txCallback == 0);
card->attached = FALSE;
EXISetExiCallback(chan, 0);
OSCancelAlarm(&card->alarm);
callback = card->exiCallback;
if (callback) {
card->exiCallback = 0;
callback(chan, CARD_RESULT_NOCARD);
}
if (card->result != CARD_RESULT_BUSY) {
card->result = CARD_RESULT_NOCARD;
}
callback = card->extCallback;
if (callback && CARD_MAX_MOUNT_STEP <= card->mountStep) {
card->extCallback = 0;
callback(chan, CARD_RESULT_NOCARD);
}
}
}
void __CARDExiHandler(s32 chan, OSContext* context) {
CARDControl* card;
CARDCallback callback;
u8 status;
s32 result;
ASSERTLINE(283, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
OSCancelAlarm(&card->alarm);
if (!card->attached) {
return;
}
if (!EXILock(chan, 0, 0)) {
result = CARD_RESULT_FATAL_ERROR;
goto fatal;
}
if ((result = __CARDReadStatus(chan, &status)) < 0 || (result = __CARDClearStatus(chan)) < 0) {
goto error;
}
if ((result = (status & 0x18) ? CARD_RESULT_IOERROR : CARD_RESULT_READY) == CARD_RESULT_IOERROR &&
--card->retry > 0)
{
result = Retry(chan);
if (result >= 0)
{
return;
}
goto fatal;
}
error:
EXIUnlock(chan);
fatal:
callback = card->exiCallback;
if (callback) {
card->exiCallback = 0;
callback(chan, result);
}
}
void __CARDTxHandler(s32 chan, OSContext* context) {
CARDControl* card;
CARDCallback callback;
int err;
ASSERTLINE(365, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
err = !EXIDeselect(chan);
EXIUnlock(chan);
callback = card->txCallback;
if (callback) {
card->txCallback = NULL;
callback(chan, (!err && EXIProbe(chan)) ? CARD_RESULT_READY : CARD_RESULT_NOCARD);
}
}
void __CARDUnlockedHandler(s32 chan, OSContext* context) {
CARDControl* card;
CARDCallback callback;
ASSERTLINE(412, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
callback = card->unlockCallback;
if (callback) {
card->unlockCallback = 0;
callback(chan, EXIProbe(chan) ? CARD_RESULT_UNLOCKED : CARD_RESULT_NOCARD);
}
}
s32 __CARDEnableInterrupt(s32 chan, BOOL enable) {
BOOL err;
u32 cmd;
ASSERTLINE(431, 0 <= chan && chan < 2);
if (!EXISelect(chan, 0, CARDFreq)) {
return CARD_RESULT_NOCARD;
}
cmd = enable ? 0x81010000 : 0x81000000;
err = FALSE;
err |= !EXIImm(chan, &cmd, 2, EXI_WRITE, NULL);
err |= !EXISync(chan);
err |= !EXIDeselect(chan);
return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY;
}
s32 __CARDReadStatus(s32 chan, u8* status) {
BOOL err;
u32 cmd;
ASSERTLINE(450, 0 <= chan && chan < 2);
if (!EXISelect(chan, 0, CARDFreq)) {
return CARD_RESULT_NOCARD;
}
cmd = 0x83000000;
err = FALSE;
err |= !EXIImm(chan, &cmd, 2, EXI_WRITE, NULL);
err |= !EXISync(chan);
err |= !EXIImm(chan, status, 1, EXI_READ, NULL);
err |= !EXISync(chan);
err |= !EXIDeselect(chan);
return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY;
}
int __CARDReadVendorID(s32 chan, u16* id) {
BOOL err;
u32 cmd;
ASSERTLINE(471, 0 <= chan && chan < 2);
if (!EXISelect(chan, 0, CARDFreq)) {
return CARD_RESULT_NOCARD;
}
cmd = 0x85000000;
err = 0;
err |= !EXIImm(chan, &cmd, 2, EXI_WRITE, 0);
err |= !EXISync(chan);
err |= !EXIImm(chan, id, 2, EXI_READ, 0);
err |= !EXISync(chan);
err |= !EXIDeselect(chan);
return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY;
}
s32 __CARDClearStatus(s32 chan) {
BOOL err;
u32 cmd;
ASSERTLINE(492, 0 <= chan && chan < 2);
if (!EXISelect(chan, 0, CARDFreq)) {
return CARD_RESULT_NOCARD;
}
cmd = 0x89000000;
err = FALSE;
err |= !EXIImm(chan, &cmd, 1, EXI_WRITE, 0);
err |= !EXISync(chan);
err |= !EXIDeselect(chan);
return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY;
}
s32 __CARDSleep(s32 chan) {
int err;
u32 cmd;
ASSERTLINE(511, 0 <= chan && chan < 2);
if (!EXISelect(chan, 0, CARDFreq)) {
return CARD_RESULT_NOCARD;
}
cmd = 0x88000000;
err = 0;
err |= !EXIImm(chan, &cmd, 1, EXI_WRITE, 0);
err |= !EXISync(chan);
err |= !EXIDeselect(chan);
if(err) {
return CARD_RESULT_NOCARD;
}
return CARD_RESULT_READY;
}
s32 __CARDWakeup(s32 chan) {
int err;
u32 cmd;
ASSERTLINE(530, 0 <= chan && chan < 2);
if (!EXISelect(chan, 0, CARDFreq)) {
return CARD_RESULT_NOCARD;
}
cmd = 0x87000000;
err = 0;
err |= !EXIImm(chan, &cmd, 1, EXI_WRITE, 0);
err |= !EXISync(chan);
err |= !EXIDeselect(chan);
if(err) {
return CARD_RESULT_NOCARD;
}
return CARD_RESULT_READY;
}
static void TimeoutHandler(OSAlarm* alarm, OSContext* context) {
s32 chan;
CARDControl* card;
CARDCallback callback;
for (chan = 0; chan < 2; ++chan) {
card = &__CARDBlock[chan];
if (alarm == &card->alarm) {
break;
}
}
ASSERTLINE(578, 0 <= chan && chan < 2);
if (!card->attached) {
return;
}
EXISetExiCallback(chan, NULL);
callback = card->exiCallback;
if (callback) {
card->exiCallback = 0;
callback(chan, CARD_RESULT_IOERROR);
}
}
static void SetupTimeoutAlarm(CARDControl* card) {
OSCancelAlarm(&card->alarm);
switch (card->cmd[0]) {
case 0xF2:
OSSetAlarm(&card->alarm, OSMillisecondsToTicks(100),
TimeoutHandler);
break;
case 0xF3:
break;
case 0xF4:
if (card->pageSize > 0x80) {
OSSetAlarm(&card->alarm, OSSecondsToTicks((OSTime)2) * (card->cBlock / 0x40),
TimeoutHandler);
break;
}
case 0xF1:
OSSetAlarm(&card->alarm, OSSecondsToTicks((OSTime)2) * (card->sectorSize / 0x2000),
TimeoutHandler);
break;
}
}
static s32 Retry(s32 chan) {
CARDControl* card;
ASSERTLINE(654, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (!EXISelect(chan, 0, CARDFreq)) {
EXIUnlock(chan);
return CARD_RESULT_NOCARD;
}
SetupTimeoutAlarm(card);
if (!EXIImmEx(chan, card->cmd, card->cmdlen, EXI_WRITE)) {
EXIDeselect(chan);
EXIUnlock(chan);
return CARD_RESULT_NOCARD;
}
if (card->cmd[0] == 0x52 &&
!EXIImmEx(chan, (u8* )card->workArea + sizeof(CARDID), card->latency, EXI_WRITE))
{
EXIDeselect(chan);
EXIUnlock(chan);
return CARD_RESULT_NOCARD;
}
if (card->mode == 0xffffffff) {
EXIDeselect(chan);
EXIUnlock(chan);
return CARD_RESULT_READY;
}
if (!EXIDma(chan, card->buffer, (s32)((card->cmd[0] == 0x52) ? 512 : card->pageSize), card->mode,
__CARDTxHandler))
{
EXIDeselect(chan);
EXIUnlock(chan);
return CARD_RESULT_NOCARD;
}
return CARD_RESULT_READY;
}
static void UnlockedCallback(s32 chan, s32 result) {
CARDCallback callback;
CARDControl* card;
ASSERTLINE(718, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (result >= 0) {
card->unlockCallback = UnlockedCallback;
if (!EXILock(chan, 0, __CARDUnlockedHandler)) {
result = CARD_RESULT_READY;
} else {
card->unlockCallback = 0;
result = Retry(chan);
}
}
if (result < 0) {
switch (card->cmd[0]) {
case 0x52:
callback = card->txCallback;
if (callback) {
card->txCallback = NULL;
callback(chan, result);
}
break;
case 0xF2:
case 0xF4:
case 0xF1:
callback = card->exiCallback;
if (callback) {
card->exiCallback = 0;
callback(chan, result);
}
break;
}
}
}
static s32 __CARDStart(s32 chan, CARDCallback txCallback, CARDCallback exiCallback) {
BOOL enabled;
CARDControl* card;
s32 result;
enabled = OSDisableInterrupts();
ASSERTLINE(784, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (!card->attached) {
result = CARD_RESULT_NOCARD;
} else {
if (txCallback) {
card->txCallback = txCallback;
}
if (exiCallback) {
card->exiCallback = exiCallback;
}
card->unlockCallback = UnlockedCallback;
if (!EXILock(chan, 0, __CARDUnlockedHandler)) {
result = CARD_RESULT_BUSY;
} else {
card->unlockCallback = 0;
if (!EXISelect(chan, 0, CARDFreq)) {
EXIUnlock(chan);
result = CARD_RESULT_NOCARD;
} else {
SetupTimeoutAlarm(card);
result = CARD_RESULT_READY;
}
}
}
OSRestoreInterrupts(enabled);
return result;
}
#define AD1(x) ((u8)(((x) >> 17) & 0x7f))
#define AD1EX(x) ((u8)(AD1(x) | 0x80));
#define AD2(x) ((u8)(((x) >> 9) & 0xff))
#define AD3(x) ((u8)(((x) >> 7) & 0x03))
#define BA(x) ((u8)((x)&0x7f))
s32 __CARDReadSegment(s32 chan, CARDCallback callback) {
CARDControl* card;
s32 result;
ASSERTLINE(846, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
ASSERTLINE(848, card->addr % CARD_SEG_SIZE == 0);
ASSERTLINE(849, card->addr < (u32) card->size * 1024 * 1024 / 8);
card->cmd[0] = 0x52;
card->cmd[1] = AD1(card->addr);
card->cmd[2] = AD2(card->addr);
card->cmd[3] = AD3(card->addr);
card->cmd[4] = BA(card->addr);
card->cmdlen = 5;
card->mode = 0;
card->retry = 0;
result = __CARDStart(chan, callback, 0);
if (result == CARD_RESULT_BUSY) {
result = CARD_RESULT_READY;
} else if (result >= 0) {
if (!EXIImmEx(chan, card->cmd, card->cmdlen, EXI_WRITE) ||
!EXIImmEx(chan, (u8* )card->workArea + sizeof(CARDID), card->latency,
EXI_WRITE) || // XXX use DMA if possible
!EXIDma(chan, card->buffer, 512, card->mode, __CARDTxHandler))
{
card->txCallback = NULL;
EXIDeselect(chan);
EXIUnlock(chan);
result = CARD_RESULT_NOCARD;
} else {
result = CARD_RESULT_READY;
}
}
return result;
}
s32 __CARDWritePage(s32 chan, CARDCallback callback) {
CARDControl* card;
s32 result;
ASSERTLINE(903, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
ASSERTLINE(905, card->addr % card->pageSize == 0);
ASSERTLINE(906, card->addr < (u32) card->size * 1024 * 1024 / 8);
card->cmd[0] = 0xF2;
if (card->pageSize > 0x80) {
card->cmd[1] = AD1(card->addr) | 0x80;
} else {
card->cmd[1] = AD1(card->addr);
}
card->cmd[2] = AD2(card->addr);
card->cmd[3] = AD3(card->addr);
card->cmd[4] = BA(card->addr);
card->cmdlen = 5;
card->mode = 1;
card->retry = 3;
result = __CARDStart(chan, 0, callback);
if (result == CARD_RESULT_BUSY) {
result = CARD_RESULT_READY;
} else if (result >= 0) {
if (!EXIImmEx(chan, card->cmd, card->cmdlen, EXI_WRITE) ||
!EXIDma(chan, card->buffer, card->pageSize, card->mode, __CARDTxHandler))
{
card->exiCallback = 0;
EXIDeselect(chan);
EXIUnlock(chan);
result = CARD_RESULT_NOCARD;
} else {
result = CARD_RESULT_READY;
}
}
return result;
}
s32 __CARDErase(s32 chan, CARDCallback callback) {
CARDControl* card;
s32 result;
ASSERTLINE(962, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
card->cmd[0] = 0xF4;
card->cmd[1] = 0;
card->cmd[2] = 0;
card->cmdlen = 3;
card->mode = -1;
card->retry = 3;
result = __CARDStart(chan, 0, callback);
if (result == CARD_RESULT_BUSY) {
result = CARD_RESULT_READY;
} else if (result >= 0) {
if (EXIImmEx(chan, &card->cmd, card->cmdlen, EXI_WRITE) == 0) {
result = CARD_RESULT_NOCARD;
card->exiCallback = 0;
} else {
result = CARD_RESULT_READY;
}
EXIDeselect(chan);
EXIUnlock(chan);
}
return result;
}
s32 __CARDEraseSector(s32 chan, u32 addr, CARDCallback callback) {
CARDControl* card;
s32 result;
ASSERTLINE(1010, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
ASSERTLINE(1012, addr % card->sectorSize == 0);
ASSERTLINE(1013, addr < (u32) card->size * 1024 * 1024 / 8);
if (card->pageSize > 0x80) {
if (callback) {
callback(chan, 0);
}
return 0;
}
card->cmd[0] = 0xF1;
card->cmd[1] = AD1(addr);
card->cmd[2] = AD2(addr);
card->cmdlen = 3;
card->mode = -1;
card->retry = 3;
result = __CARDStart(chan, 0, callback);
if (result == CARD_RESULT_BUSY) {
result = CARD_RESULT_READY;
} else if (result >= 0) {
if (!EXIImmEx(chan, card->cmd, card->cmdlen, EXI_WRITE)) {
result = CARD_RESULT_NOCARD;
card->exiCallback = NULL;
} else {
result = CARD_RESULT_READY;
}
EXIDeselect(chan);
EXIUnlock(chan);
}
return result;
}
void CARDInit(void) {
int chan;
if (__CARDBlock[0].diskID && __CARDBlock[1].diskID) {
return;
}
__CARDEncode = OSGetFontEncode();
OSRegisterVersion(__CARDVersion);
DSPInit();
for (chan = 0; chan < 2; ++chan) {
CARDControl* card = &__CARDBlock[chan];
card->result = CARD_RESULT_NOCARD;
OSInitThreadQueue(&card->threadQueue);
OSCreateAlarm(&card->alarm);
}
__CARDSetDiskID((void*)OSPhysicalToCached(0));
OSRegisterShutdownFunction(&ShutdownFunctionInfo);
}
u16 __CARDGetFontEncode(void) {
return __CARDEncode;
}
u16 __CARDSetFontEncode(u16 encode) {
u16 prev = __CARDEncode;
switch (encode) {
case CARD_ENCODE_ANSI:
case CARD_ENCODE_SJIS:
__CARDEncode = encode;
break;
}
return prev;
}
void __CARDSetDiskID(const DVDDiskID* id) {
__CARDBlock[0].diskID = id ? id : &__CARDDiskNone;
__CARDBlock[1].diskID = id ? id : &__CARDDiskNone;
}
const DVDDiskID* CARDGetDiskID(s32 chan) {
ASSERTLINE(1168, 0 <= chan && chan < 2);
return __CARDBlock[chan].diskID;
}
s32 CARDSetDiskID(s32 chan, const DVDDiskID* diskID) {
BOOL enabled;
CARDControl* card;
card = &__CARDBlock[chan];
ASSERTLINE(1189, 0 <= chan && chan < 2);
enabled = OSDisableInterrupts();
if (card->result == CARD_RESULT_BUSY) {
return CARD_RESULT_BUSY;
}
card->diskID = diskID != 0 ? diskID : (const DVDDiskID*)OSPhysicalToCached(0);
OSRestoreInterrupts(enabled);
return 0;
}
s32 __CARDGetControlBlock(s32 chan, CARDControl** pcard) {
BOOL enabled;
s32 result;
CARDControl* card;
card = &__CARDBlock[chan];
if (chan < 0 || chan >= 2 || card->diskID == 0) {
return CARD_RESULT_FATAL_ERROR;
}
enabled = OSDisableInterrupts();
if (!card->attached) {
result = CARD_RESULT_NOCARD;
} else if (card->result == CARD_RESULT_BUSY) {
result = CARD_RESULT_BUSY;
} else {
card->result = CARD_RESULT_BUSY;
result = CARD_RESULT_READY;
card->apiCallback = NULL;
*pcard = card;
}
OSRestoreInterrupts(enabled);
return result;
}
s32 __CARDPutControlBlock(CARDControl* card, s32 result) {
BOOL enabled;
ASSERTLINE(1259, result != CARD_RESULT_BUSY);
enabled = OSDisableInterrupts();
if (card->attached) {
card->result = result;
} else if (card->result == CARD_RESULT_BUSY) {
card->result = result;
}
OSRestoreInterrupts(enabled);
return result;
}
s32 CARDGetResultCode(s32 chan) {
CARDControl* card;
ASSERTLINE(1292, 0 <= chan && chan < 2);
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
card = &__CARDBlock[chan];
return card->result;
}
s32 CARDFreeBlocks(s32 chan, s32* byteNotUsed, s32* filesNotUsed) {
CARDControl* card;
s32 result;
u16* fat;
CARDDir* dir;
CARDDir* ent;
u16 fileNo;
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
fat = __CARDGetFatBlock(card);
dir = __CARDGetDirBlock(card);
if (fat == 0 || dir == 0) {
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
}
if (byteNotUsed) {
*byteNotUsed = (s32)(card->sectorSize * fat[CARD_FAT_FREEBLOCKS]);
}
if (filesNotUsed) {
*filesNotUsed = 0;
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
ent = &dir[fileNo];
if (ent->fileName[0] == 0xff) {
++*filesNotUsed;
}
}
}
return __CARDPutControlBlock(card, CARD_RESULT_READY);
}
s32 CARDGetEncoding(s32 chan, u16* encode) {
CARDControl* card;
CARDID* id;
s32 result;
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
id = card->workArea;
*encode = id->encode;
return __CARDPutControlBlock(card, CARD_RESULT_READY);
}
s32 CARDGetMemSize(s32 chan, u16* size) {
CARDControl* card;
s32 result;
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
*size = card->size;
return __CARDPutControlBlock(card, CARD_RESULT_READY);
}
s32 CARDGetSectorSize(s32 chan, u32* size) {
CARDControl* card;
s32 result;
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
*size = card->sectorSize;
return __CARDPutControlBlock(card, CARD_RESULT_READY);
}
s32 __CARDSync(s32 chan) {
CARDControl* block;
s32 result;
s32 enabled;
block = &__CARDBlock[chan];
enabled = OSDisableInterrupts();
while ((result = CARDGetResultCode(chan)) == CARD_RESULT_BUSY) {
OSSleepThread(&block->threadQueue);
}
OSRestoreInterrupts(enabled);
return result;
}
static BOOL OnShutdown(BOOL final, u32 event) {
if (!final) {
if (CARDUnmount(0) == CARD_RESULT_BUSY || CARDUnmount(1) == CARD_RESULT_BUSY) {
return FALSE;
}
}
return TRUE;
}
BOOL CARDSetFastMode(BOOL enable) {
u16 prev = __CARDFastMode;
__CARDFastMode = enable ? TRUE : FALSE;
return prev ? TRUE : FALSE;
}
BOOL CARDGetFastMode(void) {
return __CARDFastMode ? TRUE : FALSE;
}
s32 CARDGetCurrentMode(s32 chan, u32* mode) {
CARDControl* card;
s32 result;
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
switch (card->pageSize) {
case 512:
*mode = 1;
break;
case 128:
default:
*mode = 0;
break;
}
return __CARDPutControlBlock(card, CARD_RESULT_READY);
}

View File

@ -0,0 +1,160 @@
#include <dolphin/card.h>
#include "__card.h"
// prototypes
static void WriteCallback(s32 chan, s32 result);
static void EraseCallback(s32 chan, s32 result);
void* __CARDGetFatBlock(CARDControl* card) {
ASSERTLINE(57, card->currentFat);
return card->currentFat;
}
static void WriteCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
u16* fat0;
u16* fat1;
card = &__CARDBlock[chan];
if (result >= 0) {
fat0 = (u16*)((u8*)card->workArea + 0x6000);
fat1 = (u16*)((u8*)card->workArea + 0x8000);
ASSERTLINE(82, card->currentFat);
if (card->currentFat == fat0) {
card->currentFat = fat1;
memcpy(fat1, fat0, 0x2000);
} else {
ASSERTLINE(90, card->currentFat == fat1);
card->currentFat = fat0;
memcpy(fat0, fat1, 0x2000);
}
}
if (!card->apiCallback)
__CARDPutControlBlock(card, result);
callback = card->eraseCallback;
if (callback) {
card->eraseCallback = NULL;
callback(chan, result);
}
}
static void EraseCallback(s32 chan, s32 result) {
CARDControl* card = &__CARDBlock[chan];
CARDCallback callback;
u16* fat;
u32 addr;
if (result < 0)
goto error;
fat = __CARDGetFatBlock(card);
addr = ((u32)fat - (u32)card->workArea) / CARD_SYSTEM_BLOCK_SIZE * card->sectorSize;
result = __CARDWrite(chan, addr, CARD_SYSTEM_BLOCK_SIZE, fat, WriteCallback);
if (result < 0)
goto error;
return;
error:
if (!card->apiCallback)
__CARDPutControlBlock(card, result);
callback = card->eraseCallback;
if (callback) {
card->eraseCallback = NULL;
callback(chan, result);
}
}
s32 __CARDAllocBlock(s32 chan, u32 cBlock, CARDCallback callback) {
CARDControl* card;
u16* fat;
u16 iBlock;
u16 startBlock;
u16 prevBlock;
u16 count;
ASSERTLINE(182, 0 < cBlock);
ASSERTLINE(183, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (!card->attached)
return CARD_RESULT_NOCARD;
fat = __CARDGetFatBlock(card);
if (fat[3] < cBlock)
return CARD_RESULT_INSSPACE;
fat[3] -= cBlock;
startBlock = 0xFFFF;
iBlock = fat[4];
count = 0;
while (0 < cBlock) {
if (card->cBlock - 5 < ++count)
return CARD_RESULT_BROKEN;
iBlock++;
if (!CARDIsValidBlockNo(card, iBlock))
iBlock = 5;
if (fat[iBlock] == 0x0000u) {
if (startBlock == 0xFFFF)
startBlock = iBlock;
else
fat[prevBlock] = iBlock;
prevBlock = iBlock;
fat[iBlock] = 0xFFFF;
--cBlock;
}
}
fat[4] = iBlock;
card->startBlock = startBlock;
return __CARDUpdateFatBlock(chan, fat, callback);
}
s32 __CARDFreeBlock(s32 chan, u16 nBlock, CARDCallback callback) {
CARDControl* card;
u16* fat;
u16 nextBlock;
ASSERTLINE(253, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (!card->attached)
return CARD_RESULT_NOCARD;
fat = __CARDGetFatBlock(card);
while (nBlock != 0xFFFF) {
if (!CARDIsValidBlockNo(card, nBlock))
return CARD_RESULT_BROKEN;
nextBlock = fat[nBlock];
fat[nBlock] = 0;
nBlock = nextBlock;
++fat[3];
}
return __CARDUpdateFatBlock(chan, fat, callback);
}
s32 __CARDUpdateFatBlock(s32 chan, u16* fat, CARDCallback callback) {
CARDControl* card;
u32 addr;
ASSERTLINE(295, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
++fat[2];
__CARDCheckSum(fat + 2, 0x1FFC, fat, fat + 1);
DCStoreRange(fat, 0x2000);
card->eraseCallback = callback;
addr = (((char*)fat - (char*)card->workArea) / 8192u) * card->sectorSize;
return __CARDEraseSector(chan, addr, EraseCallback);
}

View File

@ -0,0 +1,343 @@
#include <dolphin/card.h>
#include "os/__os.h"
#include "__card.h"
// prototypes
static s32 VerifyID(CARDControl* card);
static s32 VerifyDir(CARDControl* card, int* pcurrent);
static s32 VerifyFAT(CARDControl* card, int* pcurrent);
void __CARDCheckSum(void* ptr, int length, u16* checksum, u16* checksumInv) {
u16* p;
int i;
ASSERTLINE(82, length % sizeof(u16) == 0);
length /= sizeof(u16);
*checksum = *checksumInv = 0;
for (i = 0, p = ptr; i < length; i++, p++) {
*checksum += *p;
*checksumInv += ~*p;
}
if (*checksum == 0xFFFF)
*checksum = 0;
if (*checksumInv == 0xFFFF)
*checksumInv = 0;
}
static s32 VerifyID(CARDControl* card) {
CARDID* id;
u16 checksum;
u16 checksumInv;
OSSramEx* sramEx;
OSTime rand;
int i;
id = card->workArea;
if (id->deviceID != 0 || id->size != card->size)
return CARD_RESULT_BROKEN;
__CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &checksum, &checksumInv);
if (id->checkSum != checksum || id->checkSumInv != checksumInv)
return CARD_RESULT_BROKEN;
rand = *(OSTime*)&id->serial[12];
sramEx = __OSLockSramEx();
for (i = 0; i < 12; i++) {
rand = (rand * 1103515245 + 12345) >> 16;
if (id->serial[i] != (u8)(sramEx->flashID[card - __CARDBlock][i] + rand)) {
__OSUnlockSramEx(FALSE);
return CARD_RESULT_BROKEN;
}
rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF;
}
__OSUnlockSramEx(FALSE);
if (id->encode != __CARDGetFontEncode())
return CARD_RESULT_ENCODING;
return CARD_RESULT_READY;
}
static s32 VerifyDir(CARDControl* card, int* pcurrent) {
CARDDir* dir[2];
CARDDirCheck* check[2];
u16 checkSum;
u16 checkSumInv;
int i;
int errors;
int current;
current = errors = 0;
for (i = 0; i < 2; i++) {
dir[i] = (CARDDir*)((u8*)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE);
check[i] = CARDGetDirCheck(dir[i]);
__CARDCheckSum(dir[i], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv);
if (check[i]->checkSum != checkSum || check[i]->checkSumInv != checkSumInv) {
++errors;
current = i;
card->currentDir = 0;
}
}
if (0 == errors) {
if (card->currentDir == 0) {
if ((check[0]->checkCode - check[1]->checkCode) < 0)
current = 0;
else
current = 1;
card->currentDir = dir[current];
memcpy(dir[current], dir[current ^ 1], CARD_SYSTEM_BLOCK_SIZE);
} else {
current = (card->currentDir == dir[0]) ? 0 : 1;
}
}
if (pcurrent)
*pcurrent = current;
return errors;
}
static s32 VerifyFAT(CARDControl* card, int* pcurrent) {
u16* fat[2];
u16* fatp;
u16 nBlock;
u16 cFree;
int i;
u16 checkSum;
u16 checkSumInv;
int errors;
int current;
current = errors = 0;
for (i = 0; i < 2; i++) {
fatp = fat[i] = (u16*)((u8*)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE);
__CARDCheckSum(&fatp[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv);
if (fatp[CARD_FAT_CHECKSUM] != checkSum || fatp[CARD_FAT_CHECKSUMINV] != checkSumInv) {
++errors;
current = i;
card->currentFat = 0;
continue;
}
cFree = 0;
for (nBlock = CARD_NUM_SYSTEM_BLOCK; nBlock < card->cBlock; nBlock++) {
if (fatp[nBlock] == CARD_FAT_AVAIL)
cFree++;
}
if (cFree != fatp[CARD_FAT_FREEBLOCKS]) {
++errors;
current = i;
card->currentFat = 0;
continue;
}
}
if (0 == errors) {
if (card->currentFat == 0) {
if (((s16)fat[0][CARD_FAT_CHECKCODE] - (s16)fat[1][CARD_FAT_CHECKCODE]) < 0)
current = 0;
else
current = 1;
card->currentFat = fat[current];
memcpy(fat[current], fat[current ^ 1], CARD_SYSTEM_BLOCK_SIZE);
} else
current = (card->currentFat == fat[0]) ? 0 : 1;
}
if (pcurrent)
*pcurrent = current;
return errors;
}
s32 __CARDVerify(CARDControl* card) {
s32 result;
int errors;
result = VerifyID(card);
if (result < 0)
return result;
errors = VerifyDir(card, NULL);
errors += VerifyFAT(card, NULL);
switch (errors) {
case 0:
ASSERTLINE(301, card->currentDir);
ASSERTLINE(302, card->currentFat);
return CARD_RESULT_READY;
case 1:
return CARD_RESULT_BROKEN;
default:
return CARD_RESULT_BROKEN;
}
}
s32 CARDCheckExAsync(s32 chan, s32* xferBytes, CARDCallback callback) {
CARDControl* card;
CARDDir* dir[2];
u16* fat[2];
u16* map;
s32 result;
int errors;
int currentFat;
int currentDir;
s32 fileNo;
u16 iBlock;
u16 cBlock;
u16 cFree;
BOOL updateFat = FALSE;
BOOL updateDir = FALSE;
BOOL updateOrphan = FALSE;
ASSERTLINE(346, 0 <= chan && chan < 2);
if (xferBytes) {
*xferBytes = 0;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
result = VerifyID(card);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
errors = VerifyDir(card, &currentDir);
errors += VerifyFAT(card, &currentFat);
if (1 < errors) {
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
}
dir[0] = (CARDDir*)((u8*)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE);
dir[1] = (CARDDir*)((u8*)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE);
fat[0] = (u16*)((u8*)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE);
fat[1] = (u16*)((u8*)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE);
ASSERTLINE(377, errors == 0 || errors == 1);
switch (errors) {
case 0:
ASSERTLINE(381, card->currentDir);
ASSERTLINE(382, card->currentFat);
break;
case 1:
if (!card->currentDir) {
ASSERTLINE(387, card->currentFat);
card->currentDir = dir[currentDir];
memcpy(dir[currentDir], dir[currentDir ^ 1], CARD_SYSTEM_BLOCK_SIZE);
updateDir = TRUE;
} else {
ASSERTLINE(394, !card->currentFat);
card->currentFat = fat[currentFat];
memcpy(fat[currentFat], fat[currentFat ^ 1], CARD_SYSTEM_BLOCK_SIZE);
updateFat = TRUE;
}
break;
}
map = fat[currentFat ^ 1];
memset(map, 0, CARD_SYSTEM_BLOCK_SIZE);
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
CARDDir* ent;
ent = &card->currentDir[fileNo];
if (ent->gameName[0] == 0xff) {
continue;
}
for (iBlock = ent->startBlock, cBlock = 0; iBlock != 0xFFFF && cBlock < ent->length;
iBlock = card->currentFat[iBlock], ++cBlock)
{
if (!CARDIsValidBlockNo(card, iBlock) || 1 < ++map[iBlock]) {
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
}
}
if (cBlock != ent->length || iBlock != 0xFFFF) {
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
}
}
cFree = 0;
for (iBlock = CARD_NUM_SYSTEM_BLOCK; iBlock < card->cBlock; iBlock++) {
u16 nextBlock;
nextBlock = card->currentFat[iBlock];
if (map[iBlock] == 0) {
if (nextBlock != CARD_FAT_AVAIL) {
card->currentFat[iBlock] = CARD_FAT_AVAIL;
updateOrphan = TRUE;
}
cFree++;
} else if (!CARDIsValidBlockNo(card, nextBlock) && nextBlock != 0xFFFF) {
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
}
}
if (cFree != card->currentFat[CARD_FAT_FREEBLOCKS]) {
card->currentFat[CARD_FAT_FREEBLOCKS] = cFree;
updateOrphan = TRUE;
}
if (updateOrphan) {
__CARDCheckSum(&card->currentFat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32),
&card->currentFat[CARD_FAT_CHECKSUM],
&card->currentFat[CARD_FAT_CHECKSUMINV]);
}
memcpy(fat[currentFat ^ 1], fat[currentFat], CARD_SYSTEM_BLOCK_SIZE);
if (updateDir) {
if (xferBytes) {
*xferBytes = CARD_SYSTEM_BLOCK_SIZE;
}
return __CARDUpdateDir(chan, callback);
}
if (updateFat | updateOrphan) {
if (xferBytes) {
*xferBytes = CARD_SYSTEM_BLOCK_SIZE;
}
return __CARDUpdateFatBlock(chan, card->currentFat, callback);
}
__CARDPutControlBlock(card, CARD_RESULT_READY);
if (callback) {
BOOL enabled = OSDisableInterrupts();
callback(chan, CARD_RESULT_READY);
OSRestoreInterrupts(enabled);
}
return CARD_RESULT_READY;
}
s32 CARDCheckAsync(s32 chan, CARDCallback callback) {
s32 xferBytes;
return CARDCheckExAsync(chan, &xferBytes, callback);
}
s32 CARDCheckEx(s32 chan, s32* xferBytes) {
s32 result = CARDCheckExAsync(chan, xferBytes, __CARDSyncCallback);
if (result < 0 || xferBytes == 0) {
return result;
}
return __CARDSync(chan);
}
s32 CARDCheck(s32 chan) {
s32 xferBytes;
return CARDCheckEx(chan, &xferBytes);
}

View File

@ -0,0 +1,126 @@
#include <dolphin/card.h>
#include "__card.h"
// prototypes
static void CreateCallbackFat(s32 chan, s32 result);
static void CreateCallbackFat(s32 chan, s32 result) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
CARDCallback callback;
card = &__CARDBlock[chan];
callback = card->apiCallback;
card->apiCallback = NULL;
if (result >= 0) {
dir = __CARDGetDirBlock(card);
ent = &dir[card->freeNo];
memcpy(ent->gameName, card->diskID->gameName, sizeof(ent->gameName));
memcpy(ent->company, card->diskID->company, sizeof(ent->company));
ent->permission = 4;
ent->copyTimes = 0;
ASSERTLINE(111, CARDIsValidBlockNo(card, card->startBlock));
ent->startBlock = (u16)card->startBlock;
ent->bannerFormat = 0;
ent->iconAddr = -1;
ent->iconFormat = 0;
ent->iconSpeed = 0;
ent->commentAddr = -1;
CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST);
card->fileInfo->offset = 0;
card->fileInfo->iBlock = ent->startBlock;
ent->time = OSTicksToSeconds(OSGetTime());
result = __CARDUpdateDir(chan, callback);
if (result < 0) {
goto after;
}
} else {
after:;
__CARDPutControlBlock(card, result);
if (callback) {
callback(chan, result);
}
}
}
s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo, CARDCallback callback) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
u16 fileNo;
u16 freeNo;
u16* fat;
s32 result;
ASSERTLINE(175, 0 <= chan && chan < 2);
ASSERTLINE(176, strlen(fileName) <= CARD_FILENAME_MAX);
if (strlen(fileName) > (u32)CARD_FILENAME_MAX) {
return CARD_RESULT_NAMETOOLONG;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
ASSERTLINE(188, 0 < size && (size % card->sectorSize) == 0);
if (size <= 0 || (size % card->sectorSize) != 0) {
return CARD_RESULT_FATAL_ERROR;
}
freeNo = (u16)-1;
dir = __CARDGetDirBlock(card);
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
ent = &dir[fileNo];
if (ent->gameName[0] == 0xff) {
if (freeNo == (u16)-1) {
freeNo = fileNo;
}
} else if (memcmp(ent->gameName, card->diskID->gameName, sizeof(ent->gameName)) == 0 &&
memcmp(ent->company, card->diskID->company, sizeof(ent->company)) == 0 &&
__CARDCompareFileName(ent, fileName)) {
return __CARDPutControlBlock(card, CARD_RESULT_EXIST);
}
}
if (freeNo == (u16)-1) {
return __CARDPutControlBlock(card, CARD_RESULT_NOENT);
}
fat = __CARDGetFatBlock(card);
if (card->sectorSize * fat[CARD_FAT_FREEBLOCKS] < size) {
return __CARDPutControlBlock(card, CARD_RESULT_INSSPACE);
}
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
card->freeNo = freeNo;
ent = &dir[freeNo];
ent->length = (u16)(size / card->sectorSize);
strncpy((char*)ent->fileName, fileName, CARD_FILENAME_MAX);
card->fileInfo = fileInfo;
fileInfo->chan = chan;
fileInfo->fileNo = freeNo;
result = __CARDAllocBlock(chan, size / card->sectorSize, CreateCallbackFat);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
return result;
}
s32 CARDCreate(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo) {
s32 result = CARDCreateAsync(chan, fileName, size, fileInfo, __CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(chan);
}

View File

@ -0,0 +1,108 @@
#include <dolphin/card.h>
#include "__card.h"
// prototypes
static void DeleteCallback(s32 chan, s32 result);
static void DeleteCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
card = &__CARDBlock[chan];
callback = card->apiCallback;
card->apiCallback = NULL;
if (result < 0)
goto error;
result = __CARDFreeBlock(chan, card->startBlock, callback);
if (result < 0)
goto error;
return;
error:
__CARDPutControlBlock(card, result);
if (callback)
callback(chan, result);
}
s32 CARDFastDeleteAsync(s32 chan, s32 fileNo, CARDCallback callback) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
ASSERTLINE(133, 0 <= fileNo && fileNo < CARD_MAX_FILE);
ASSERTLINE(134, 0 <= chan && chan < 2);
if (fileNo < 0 || CARD_MAX_FILE <= fileNo)
return CARD_RESULT_FATAL_ERROR;
result = __CARDGetControlBlock(chan, &card);
if (result < 0)
return result;
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
result = __CARDIsWritable(card, ent);
if (result < 0)
return __CARDPutControlBlock(card, result);
if (__CARDIsOpened(card, fileNo))
return __CARDPutControlBlock(card, CARD_RESULT_BUSY);
card->startBlock = ent->startBlock;
memset(ent, 0xff, sizeof(CARDDir));
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
result = __CARDUpdateDir(chan, DeleteCallback);
if (result < 0)
__CARDPutControlBlock(card, result);
return result;
}
s32 CARDFastDelete(s32 chan, s32 fileNo) {
s32 result = CARDFastDeleteAsync(chan, fileNo, __CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(chan);
}
s32 CARDDeleteAsync(s32 chan, const char* fileName, CARDCallback callback) {
CARDControl* card;
s32 fileNo;
s32 result;
CARDDir* dir;
CARDDir* ent;
result = __CARDGetControlBlock(chan, &card);
if (result < 0)
return result;
result = __CARDGetFileNo(card, fileName, &fileNo);
if (result < 0)
return __CARDPutControlBlock(card, result);
if (__CARDIsOpened(card, fileNo))
return __CARDPutControlBlock(card, CARD_RESULT_BUSY);
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
card->startBlock = ent->startBlock;
memset(ent, 0xff, sizeof(CARDDir));
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
result = __CARDUpdateDir(chan, DeleteCallback);
if (result < 0)
__CARDPutControlBlock(card, result);
return result;
}
s32 CARDDelete(s32 chan, const char* fileName) {
s32 result = CARDDeleteAsync(chan, fileName, __CARDSyncCallback);
if (result < 0)
return result;
return __CARDSync(chan);
}

View File

@ -0,0 +1,89 @@
#include <dolphin/card.h>
#include "__card.h"
// prototypes
static void WriteCallback(s32 chan, s32 result);
static void EraseCallback(s32 chan, s32 result);
CARDDir* __CARDGetDirBlock(CARDControl* card) {
ASSERTLINE(54, card->currentDir);
return card->currentDir;
}
static void WriteCallback(s32 chan, s32 result) {
CARDControl* card = &__CARDBlock[chan];
CARDCallback callback;
if (result >= 0) {
CARDDir* dir0 = (CARDDir*)((u8*)card->workArea + 0x2000);
CARDDir* dir1 = (CARDDir*)((u8*)card->workArea + 0x4000);
ASSERTLINE(79, card->currentDir);
if (card->currentDir == dir0) {
card->currentDir = dir1;
memcpy(dir1, dir0, 0x2000);
} else {
ASSERTLINE(87, card->currentDir == dir1);
card->currentDir = dir0;
memcpy(dir0, dir1, 0x2000);
}
}
if (!card->apiCallback)
__CARDPutControlBlock(card, result);
callback = card->eraseCallback;
if (callback) {
card->eraseCallback = NULL;
callback(chan, result);
}
}
static void EraseCallback(s32 chan, s32 result) {
CARDControl* card = &__CARDBlock[chan];
CARDCallback callback;
CARDDir* dir;
u32 addr;
if (result >= 0) {
dir = __CARDGetDirBlock(card);
addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize;
result = __CARDWrite(chan, addr, 0x2000, dir, WriteCallback);
if (result >= 0)
return;
}
if (!card->apiCallback)
__CARDPutControlBlock(card, result);
callback = card->eraseCallback;
if (callback) {
card->eraseCallback = NULL;
callback(chan, result);
}
}
s32 __CARDUpdateDir(s32 chan, CARDCallback callback) {
CARDControl* card;
CARDDirCheck* check;
u32 addr;
CARDDir* dir;
ASSERTLINE(173, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (!card->attached)
return CARD_RESULT_NOCARD;
dir = __CARDGetDirBlock(card);
check = CARDGetDirCheck(dir);
++check->checkCode;
__CARDCheckSum(dir, 0x2000 - sizeof(u32), &check->checkSum, &check->checkSumInv);
DCStoreRange(dir, 0x2000);
card->eraseCallback = callback;
addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize;
return __CARDEraseSector(chan, addr, EraseCallback);
}

View File

@ -0,0 +1,102 @@
#include <dolphin/card.h>
#include "__card.h"
static void EraseCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
u16* fat;
CARDDir* dir;
CARDDir* ent;
CARDFileInfo* fileInfo;
card = &__CARDBlock[chan];
if (result >= 0) {
fileInfo = card->fileInfo;
if (fileInfo->length < 0) {
result = CARD_RESULT_CANCELED;
goto error;
}
fileInfo->length -= card->sectorSize;
if (fileInfo->length <= 0) {
dir = __CARDGetDirBlock(card);
ent = dir + fileInfo->fileNo;
ent->time = OSTicksToSeconds(OSGetTime());
callback = card->apiCallback;
card->apiCallback = NULL;
result = __CARDUpdateDir(chan, callback);
} else {
fat = __CARDGetFatBlock(card);
fileInfo->offset += card->sectorSize;
fileInfo->iBlock = fat[fileInfo->iBlock];
if (fileInfo->iBlock < 5 || fileInfo->iBlock >= card->cBlock) {
result = CARD_RESULT_BROKEN;
goto error;
}
result = __CARDEraseSector(chan, card->sectorSize * fileInfo->iBlock, EraseCallback);
}
if (result < 0) {
goto error;
}
return;
}
error:
callback = card->apiCallback;
card->apiCallback = NULL;
__CARDPutControlBlock(card, result);
ASSERTLINE(98, callback);
callback(chan, result);
}
s32 CARDEraseAsync(CARDFileInfo* fileInfo, s32 length, s32 offset, CARDCallback callback) {
CARDControl* card;
s32 result;
CARDDir* dir;
CARDDir* ent;
ASSERTLINE(132, 0 < length);
result = __CARDSeek(fileInfo, length, offset, &card);
if (result < 0) {
return result;
}
ASSERTLINE(138, OFFSET(offset, card->sectorSize) == 0);
ASSERTLINE(139, OFFSET(length, card->sectorSize) == 0);
if (OFFSET(offset, card->sectorSize) != 0 || OFFSET(length, card->sectorSize) != 0) {
return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR);
}
dir = __CARDGetDirBlock(card);
ent = dir + fileInfo->fileNo;
result = __CARDIsWritable(card, ent);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
result = __CARDEraseSector(fileInfo->chan, card->sectorSize * fileInfo->iBlock, EraseCallback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}
s32 CARDErase(CARDFileInfo* fileInfo, s32 length, s32 offset) {
s32 result = CARDEraseAsync(fileInfo, length, offset, __CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(fileInfo->chan);
}

View File

@ -0,0 +1,137 @@
#include <dolphin/card.h>
#include "os/__os.h"
#include "__card.h"
static void FormatCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
card = &__CARDBlock[chan];
if (result < 0)
goto error;
++card->formatStep;
if (card->formatStep < CARD_NUM_SYSTEM_BLOCK) {
result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback);
if (result >= 0)
return;
} else if (card->formatStep < 2 * CARD_NUM_SYSTEM_BLOCK) {
int step = card->formatStep - CARD_NUM_SYSTEM_BLOCK;
result = __CARDWrite(chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE,
(u8* )card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step), FormatCallback);
if (result >= 0)
return;
} else {
card->currentDir = (CARDDir*)((u8*)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE);
memcpy(card->currentDir, (u8*)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE);
card->currentFat = (u16*)((u8*)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE);
memcpy(card->currentFat, (u8*)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE);
}
error:
callback = card->apiCallback;
card->apiCallback = NULL;
__CARDPutControlBlock(card, result);
ASSERTLINE(133, callback);
callback(chan, result);
}
s32 __CARDFormatRegionAsync(s32 chan, u16 encode, CARDCallback callback) {
CARDControl* card;
CARDID* id;
CARDDir* dir;
u16* fat;
s16 i;
s32 result;
OSSram* sram;
OSSramEx* sramEx;
u16 dvdstatus;
OSTime time;
OSTime rand;
ASSERTLINE(167, encode == CARD_ENCODE_ANSI || encode == CARD_ENCODE_SJIS);
ASSERTLINE(168, 0 <= chan && chan < 2);
result = __CARDGetControlBlock(chan, &card);
if (result < 0)
return result;
id = (CARDID*)card->workArea;
memset(id, 0xff, CARD_SYSTEM_BLOCK_SIZE);
dvdstatus = __VIRegs[55];
id->encode = encode;
sram = __OSLockSram();
*(u32*)&id->serial[20] = sram->counterBias;
*(u32*)&id->serial[24] = sram->language;
__OSUnlockSram(FALSE);
rand = time = OSGetTime();
sramEx = __OSLockSramEx();
for (i = 0; i < 12; i++) {
rand = (rand * 1103515245 + 12345) >> 16;
id->serial[i] = (u8)(sramEx->flashID[chan][i] + rand);
rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF;
}
__OSUnlockSramEx(FALSE);
*(u32*)&id->serial[28] = dvdstatus;
*(OSTime*)&id->serial[12] = time;
id->deviceID = 0;
id->size = card->size;
__CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &id->checkSum, &id->checkSumInv);
for (i = 0; i < 2; i++) {
CARDDirCheck* check;
dir = (CARDDir*)((u8*)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE);
memset(dir, 0xff, CARD_SYSTEM_BLOCK_SIZE);
check = CARDGetDirCheck(dir);
check->checkCode = i;
__CARDCheckSum(dir, CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &check->checkSum, &check->checkSumInv);
}
for (i = 0; i < 2; i++) {
fat = (u16*)((u8*)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE);
memset(fat, 0x00, CARD_SYSTEM_BLOCK_SIZE);
fat[CARD_FAT_CHECKCODE] = (u16)i;
fat[CARD_FAT_FREEBLOCKS] = (u16)(card->cBlock - CARD_NUM_SYSTEM_BLOCK);
fat[CARD_FAT_LASTSLOT] = CARD_NUM_SYSTEM_BLOCK - 1;
__CARDCheckSum(&fat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &fat[CARD_FAT_CHECKSUM],
&fat[CARD_FAT_CHECKSUMINV]);
}
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
DCStoreRange(card->workArea, CARD_WORKAREA_SIZE);
card->formatStep = 0;
result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback);
if (result < 0)
__CARDPutControlBlock(card, result);
return result;
}
s32 __CARDFormatRegion(s32 chan, u16 encode) {
s32 result = __CARDFormatRegionAsync(chan, encode, &__CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(chan);
}
s32 CARDFormatAsync(s32 chan, CARDCallback callback) {
return __CARDFormatRegionAsync(chan, __CARDGetFontEncode(), callback);
}
s32 CARDFormat(s32 chan) {
s32 result = __CARDFormatRegionAsync(chan, __CARDGetFontEncode(), &__CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(chan);
}

View File

@ -0,0 +1,394 @@
#include <dolphin/card.h>
#include <dolphin/exi.h>
#include "os/__os.h"
#include "__card.h"
static u32 SectorSizeTable[8] = {
8 * 1024, 16 * 1024, 32 * 1024, 64 * 1024, 128 * 1024, 256 * 1024, 0, 0,
};
static u32 LatencyTable[8] = {
4, 8, 16, 32, 64, 128, 256, 512,
};
// prototypes
static s32 DoMount(s32 chan);
static void DoUnmount(s32 chan, s32 result);
static BOOL IsCard(u32 id) {
u32 size;
s32 sectorSize;
if (id & (0xFFFF0000) && (id != 0x80000004 || __CARDVendorID == 0xFFFF)) {
return FALSE;
}
if ((id & 3) != 0) {
return FALSE;
}
size = id & 0xfc;
switch (size) {
case 4:
case 8:
case 16:
case 32:
case 64:
case 128:
break;
default:
return FALSE;
break;
}
sectorSize = SectorSizeTable[(id & 0x00003800) >> 11];
if (sectorSize == 0) {
return FALSE;
}
if ((size * 1024 * 1024 / 8) / sectorSize < 8) {
return FALSE;
}
return TRUE;
}
void __CARDDisable(BOOL disable) {
BOOL enabled = OSDisableInterrupts();
__gUnknown800030E3 &= ~0x80;
if (disable) {
__gUnknown800030E3 |= 0x80;
}
OSRestoreInterrupts(enabled);
}
int CARDProbe(s32 chan) {
if (__gUnknown800030E3 & 0x80) {
return 0;
} else {
return EXIProbe(chan);
}
}
s32 CARDProbeEx(s32 chan, s32* memSize, s32* sectorSize) {
u32 id;
CARDControl* card;
BOOL enabled;
s32 result;
int probe;
if (chan < 0 || 2 <= chan)
return CARD_RESULT_FATAL_ERROR;
if (__gUnknown800030E3 & 0x80) {
return CARD_RESULT_NOCARD;
}
card = &__CARDBlock[chan];
enabled = OSDisableInterrupts();
probe = EXIProbeEx(chan);
if (probe == -1)
result = CARD_RESULT_NOCARD;
else if (probe == 0)
result = CARD_RESULT_BUSY;
else if (card->attached) {
if (card->mountStep < 1)
result = CARD_RESULT_BUSY;
else {
if (memSize)
*memSize = card->size;
if (sectorSize)
*sectorSize = card->sectorSize;
result = CARD_RESULT_READY;
}
}
else if ((EXIGetState(chan) & 8))
result = CARD_RESULT_WRONGDEVICE;
else if (!EXIGetID(chan, 0, &id))
result = CARD_RESULT_BUSY;
else if (IsCard(id)) {
if (memSize)
*memSize = (s32)(id & 0xfc);
if (sectorSize)
*sectorSize = SectorSizeTable[(id & 0x00003800) >> 11];
result = CARD_RESULT_READY;
} else {
result = CARD_RESULT_WRONGDEVICE;
}
OSRestoreInterrupts(enabled);
return result;
}
static s32 DoMount(s32 chan) {
CARDControl* card;
u32 id;
u8 status;
s32 result;
OSSramEx* sram;
int i;
u8 checkSum;
int step;
ASSERTLINE(399, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (card->mountStep == 0) {
if (EXIGetID(chan, 0, &id) == 0) {
result = CARD_RESULT_NOCARD;
} else if (IsCard(id)) {
result = CARD_RESULT_READY;
} else {
result = CARD_RESULT_WRONGDEVICE;
}
if (result < 0)
goto error;
card->cid = id;
card->size = (u16)(id & 0xFC);
ASSERTLINE(424, card->size);
card->sectorSize = SectorSizeTable[(id & 0x00003800) >> 11];
ASSERTLINE(426, card->sectorSize);
card->cBlock = (u16)((card->size * 1024 * 1024 / 8) / card->sectorSize);
ASSERTLINE(428, 8 <= card->cBlock);
card->latency = LatencyTable[(id & 0x00000700) >> 8];
result = __CARDReadVendorID(chan, &card->vendorID);
if (result < 0)
goto error;
if (CARDGetFastMode() && (card->vendorID >> 8) == 0xEC) {
card->pageSize = 512;
} else {
card->pageSize = 128;
}
result = __CARDClearStatus(chan);
if (result < 0)
goto error;
result = __CARDReadStatus(chan, &status);
if (result < 0)
goto error;
if (!EXIProbe(chan)) {
result = CARD_RESULT_NOCARD;
goto error;
}
if (!(status & 0x40)) {
result = __CARDUnlock(chan, card->id);
if (result < 0)
goto error;
checkSum = 0;
sram = __OSLockSramEx();
for (i = 0; i < 12; i++) {
sram->flashID[chan][i] = card->id[i];
checkSum += card->id[i];
}
sram->flashIDCheckSum[chan] = (u8)~checkSum;
__OSUnlockSramEx(TRUE);
return result;
} else {
card->mountStep = 1;
checkSum = 0;
sram = __OSLockSramEx();
for (i = 0; i < 12; i++)
checkSum += sram->flashID[chan][i];
__OSUnlockSramEx(FALSE);
if (sram->flashIDCheckSum[chan] != (u8)~checkSum) {
result = CARD_RESULT_IOERROR;
goto error;
}
}
}
if (card->mountStep == 1) {
if (card->cid == 0x80000004) {
u16 vendorID;
sram = __OSLockSramEx();
vendorID = *(u16*)sram->flashID[chan];
__OSUnlockSramEx(FALSE);
if (__CARDVendorID == 0xFFFF || vendorID != __CARDVendorID) {
result = CARD_RESULT_WRONGDEVICE;
goto error;
}
}
card->mountStep = 2;
result = __CARDEnableInterrupt(chan, TRUE);
if (result < 0)
goto error;
EXISetExiCallback(chan, __CARDExiHandler);
EXIUnlock(chan);
DCInvalidateRange(card->workArea, CARD_WORKAREA_SIZE);
}
step = card->mountStep - 2;
result = __CARDRead(chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE,
(u8 *)card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step), __CARDMountCallback);
if (result < 0)
__CARDPutControlBlock(card, result);
return result;
error:
EXIUnlock(chan);
DoUnmount(chan, result);
return result;
}
void __CARDMountCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
ASSERTLINE(570, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
switch (result) {
case CARD_RESULT_READY:
if (++card->mountStep < CARD_MAX_MOUNT_STEP) {
result = DoMount(chan);
if (0 <= result)
return;
} else
result = __CARDVerify(card);
break;
case CARD_RESULT_UNLOCKED:
card->unlockCallback = __CARDMountCallback;
if (!EXILock(chan, 0, __CARDUnlockedHandler)) {
return;
}
card->unlockCallback = 0;
result = DoMount(chan);
if (result >= 0)
return;
break;
case CARD_RESULT_IOERROR:
case CARD_RESULT_NOCARD:
DoUnmount(chan, result);
break;
}
callback = card->apiCallback;
card->apiCallback = NULL;
__CARDPutControlBlock(card, result);
ASSERTLINE(620, callback);
callback(chan, result);
}
s32 CARDMountAsync(s32 chan, void* workArea, CARDCallback detachCallback, CARDCallback attachCallback) {
CARDControl* card;
BOOL enabled;
ASSERTLINE(652, workArea && ((u32) workArea % 32 == 0));
ASSERTLINE(653, 0 <= chan && chan < 2);
if (chan < 0 || 2 <= chan)
return CARD_RESULT_FATAL_ERROR;
if (__gUnknown800030E3 & 0x80) {
return CARD_RESULT_NOCARD;
}
card = &__CARDBlock[chan];
enabled = OSDisableInterrupts();
if (card->result == CARD_RESULT_BUSY) {
OSRestoreInterrupts(enabled);
return CARD_RESULT_BUSY;
}
if (!card->attached && (EXIGetState(chan) & 0x08)) {
OSRestoreInterrupts(enabled);
return CARD_RESULT_WRONGDEVICE;
}
card->result = CARD_RESULT_BUSY;
card->workArea = workArea;
card->extCallback = detachCallback;
card->apiCallback = attachCallback ? attachCallback : __CARDDefaultApiCallback;
card->exiCallback = 0;
if (!card->attached && !EXIAttach(chan, __CARDExtHandler)) {
card->result = CARD_RESULT_NOCARD;
OSRestoreInterrupts(enabled);
return CARD_RESULT_NOCARD;
}
card->mountStep = 0;
card->attached = TRUE;
EXISetExiCallback(chan, 0);
OSCancelAlarm(&card->alarm);
card->currentDir = 0;
card->currentFat = 0;
OSRestoreInterrupts(enabled);
card->unlockCallback = __CARDMountCallback;
if (!EXILock(chan, 0, __CARDUnlockedHandler))
return CARD_RESULT_READY;
card->unlockCallback = 0;
return DoMount(chan);
}
s32 CARDMount(s32 chan, void* workArea, CARDCallback detachCallback) {
s32 result = CARDMountAsync(chan, workArea, detachCallback, __CARDSyncCallback);
if (result < 0)
return result;
return __CARDSync(chan);
}
static void DoUnmount(s32 chan, s32 result) {
CARDControl* card;
BOOL enabled;
ASSERTLINE(758, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
enabled = OSDisableInterrupts();
if (card->attached) {
EXISetExiCallback(chan, 0);
EXIDetach(chan);
OSCancelAlarm(&card->alarm);
card->attached = FALSE;
card->result = result;
card->mountStep = 0;
}
OSRestoreInterrupts(enabled);
}
s32 CARDUnmount(s32 chan) {
CARDControl* card;
s32 result;
ASSERTLINE(793, 0 <= chan && chan < 2);
result = __CARDGetControlBlock(chan, &card);
if (result < 0)
return result;
DoUnmount(chan, CARD_RESULT_NOCARD);
return CARD_RESULT_READY;
}

View File

@ -0,0 +1,138 @@
#include <dolphin/card.h>
#include "os/__os.h"
#include "__card.h"
u16 __CARDVendorID = 0xFFFF;
u8 __CARDPermMask = 0x1C;
u16 CARDSetVendorID(u16 vendorID) {
u16 prevID = __CARDVendorID;
__CARDVendorID = vendorID;
return prevID;
}
u16 CARDGetVendorID() {
return __CARDVendorID;
}
s32 CARDGetSerialNo(s32 chan, u64* serialNo) {
CARDControl* card;
s32 result;
CARDID* id;
u64 code;
int i;
ASSERTLINE(105, 0 <= chan && chan < 2);
if (!(0 <= chan && chan < 2)) {
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
id = (CARDID*)card->workArea;
for (code = 0, i = 0; i < sizeof(id->serial) / sizeof(u64); ++i) {
code ^= *(u64*)&id->serial[sizeof(u64) * i];
}
*serialNo = code;
return __CARDPutControlBlock(card, CARD_RESULT_READY);
}
s32 CARDGetUniqueCode(s32 chan, u64* uniqueCode) {
CARDControl* card;
s32 result;
OSSramEx* sram;
ASSERTLINE(146, 0 <= chan && chan < 2);
if (!(0 <= chan && chan < 2)) {
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
sram = __OSLockSramEx();
memcpy(uniqueCode, &sram->flashID[chan][4], 8);
__OSUnlockSramEx(0);
return __CARDPutControlBlock(card, CARD_RESULT_READY);
}
s32 CARDGetAttributes(s32 chan, s32 fileNo, u8* attr) {
CARDDir dirent;
s32 result;
result = __CARDGetStatusEx(chan, fileNo, &dirent);
if (result == 0) {
*attr = dirent.permission;
}
return result;
}
#define CARDCheckAttr(attr, flag) ((u32)(attr & flag) != 0)
s32 CARDSetAttributesAsync(s32 chan, s32 fileNo, u8 attr, CARDCallback callback) {
CARDDir dirent;
s32 result;
if (attr & ~__CARDPermMask) {
return CARD_RESULT_NOPERM;
}
result = __CARDGetStatusEx(chan, fileNo, &dirent);
if (result < 0) {
return result;
}
if ((CARDCheckAttr(dirent.permission, 0x20) && !CARDCheckAttr(attr, 0x20)) || (CARDCheckAttr(dirent.permission, 0x40) && !CARDCheckAttr(attr, 0x40))) {
return CARD_RESULT_NOPERM;
}
if ((CARDCheckAttr(attr, 0x20) && CARDCheckAttr(attr, 0x40)) || (CARDCheckAttr(attr, 0x20) && CARDCheckAttr(dirent.permission, 0x40)) || (CARDCheckAttr(attr, 0x40) && CARDCheckAttr(dirent.permission, 0x20))) {
return CARD_RESULT_NOPERM;
}
dirent.permission = attr;
return __CARDSetStatusExAsync(chan, fileNo, &dirent, callback);
}
s32 CARDSetAttributes(s32 chan, s32 fileNo, u8 attr) {
s32 result;
result = CARDSetAttributesAsync(chan, fileNo, attr, __CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(chan);
}
static int __CARDEnablePerm(u8 perm, BOOL enable) {
int prev;
prev = __CARDPermMask & perm ? TRUE : FALSE;
if (enable) {
__CARDPermMask |= perm;
} else {
__CARDPermMask &= ~perm;
}
return prev;
}
int __CARDEnableGlobal(BOOL enable) {
return __CARDEnablePerm(0x20, enable);
}
int __CARDEnableCompany(BOOL enable) {
return __CARDEnablePerm(0x40, enable);
}

View File

@ -0,0 +1,174 @@
#include <dolphin/card.h>
#include "__card.h"
BOOL __CARDCompareFileName(CARDDir* ent, const char* fileName) {
char* entName = (char*)ent->fileName;
char c1;
char c2;
int n = CARD_FILENAME_MAX;
while (--n >= 0) {
if ((c1 = *entName++) != (c2 = *fileName++))
return FALSE;
else if (c2 == '\0')
return TRUE;
}
if (*fileName == '\0')
return TRUE;
return FALSE;
}
s32 __CARDAccess(CARDControl* card, CARDDir* ent) {
const DVDDiskID* diskID = card->diskID;
if (ent->gameName[0] == 0xFF)
return CARD_RESULT_NOFILE;
if (diskID == &__CARDDiskNone
|| (memcmp(ent->gameName, diskID->gameName, sizeof(ent->gameName)) == 0
&& memcmp(ent->company, diskID->company, sizeof(ent->company)) == 0))
return CARD_RESULT_READY;
return CARD_RESULT_NOPERM;
}
s32 __CARDIsWritable(CARDControl* card, CARDDir* ent) {
const DVDDiskID* diskID = card->diskID;
s32 result;
u8 perm;
result = __CARDAccess(card, ent);
if (result == CARD_RESULT_NOPERM) {
perm = ent->permission & __CARDPermMask;
if (perm & 0x20 && (memcmp(ent->gameName, __CARDDiskNone.gameName, sizeof(ent->gameName)) == 0 &&
memcmp(ent->company, __CARDDiskNone.company, sizeof(ent->company)) == 0))
{
return CARD_RESULT_READY;
} else if (perm & 0x40 && (memcmp(ent->gameName, __CARDDiskNone.gameName, sizeof(ent->gameName)) == 0 &&
memcmp(ent->company, diskID->company, sizeof(ent->company)) == 0))
{
return CARD_RESULT_READY;
}
}
return result;
}
s32 __CARDIsReadable(CARDControl* card, CARDDir* ent) {
s32 result = __CARDIsWritable(card, ent);
if (result == CARD_RESULT_NOPERM && (ent->permission & 0x4)) {
return CARD_RESULT_READY;
}
return result;
}
s32 __CARDGetFileNo(CARDControl* card, const char* fileName, s32* pfileNo) {
CARDDir* dir;
CARDDir* ent;
s32 fileNo;
s32 result;
if (!card->attached)
return CARD_RESULT_NOCARD;
dir = __CARDGetDirBlock(card);
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
ent = &dir[fileNo];
result = __CARDAccess(card, ent);
if (result < 0)
continue;
if (__CARDCompareFileName(ent, fileName)) {
*pfileNo = fileNo;
return CARD_RESULT_READY;
}
}
return CARD_RESULT_NOFILE;
}
s32 CARDFastOpen(s32 chan, s32 fileNo, CARDFileInfo* fileInfo) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
ASSERTLINE(278, 0 <= fileNo && fileNo < CARD_MAX_FILE);
ASSERTLINE(279, 0 <= chan && chan < 2);
if (fileNo < 0 || fileNo >= CARD_MAX_FILE)
return CARD_RESULT_FATAL_ERROR;
fileInfo->chan = -1;
result = __CARDGetControlBlock(chan, &card);
if (result < 0)
return result;
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
result = __CARDIsReadable(card, ent);
if (0 <= result) {
if (!CARDIsValidBlockNo(card, ent->startBlock))
result = CARD_RESULT_BROKEN;
else {
fileInfo->chan = chan;
fileInfo->fileNo = fileNo;
fileInfo->offset = 0;
fileInfo->iBlock = ent->startBlock;
}
}
return __CARDPutControlBlock(card, result);
}
s32 CARDOpen(s32 chan, const char* fileName, CARDFileInfo* fileInfo) {
CARDControl* card;
s32 fileNo;
s32 result;
CARDDir* dir;
CARDDir* ent;
ASSERTLINE(336, 0 <= chan && chan < 2);
fileInfo->chan = -1;
result = __CARDGetControlBlock(chan, &card);
if (result < 0)
return result;
result = __CARDGetFileNo(card, fileName, &fileNo);
if (result >= 0) {
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
if (!CARDIsValidBlockNo(card, ent->startBlock))
result = CARD_RESULT_BROKEN;
else {
fileInfo->chan = chan;
fileInfo->fileNo = fileNo;
fileInfo->offset = 0;
fileInfo->iBlock = ent->startBlock;
}
}
return __CARDPutControlBlock(card, result);
}
s32 CARDClose(CARDFileInfo* fileInfo) {
CARDControl* card;
s32 result;
ASSERTLINE(380, 0 <= fileInfo->chan && fileInfo->chan < 2);
ASSERTLINE(381, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE);
result = __CARDGetControlBlock(fileInfo->chan, &card);
if (result < 0)
return result;
fileInfo->chan = -1;
return __CARDPutControlBlock(card, CARD_RESULT_READY);
}
BOOL __CARDIsOpened(CARDControl* card, s32 fileNo) {
return FALSE;
}

View File

@ -0,0 +1,100 @@
#include <dolphin/card.h>
#include "__card.h"
#define TRUNC(n, a) (((u32)(n)) & ~((a)-1))
#define CARD_PROGRAM_SIZE 128
static void ProgramCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
u16* fat;
CARDFileInfo* fileInfo;
s32 length;
card = &__CARDBlock[chan];
if (result >= 0) {
fileInfo = card->fileInfo;
if (fileInfo->length < 0) {
result = CARD_RESULT_CANCELED;
goto error;
}
length = TRUNC(fileInfo->offset + card->sectorSize, card->sectorSize) - fileInfo->offset;
fileInfo->length -= length;
if (fileInfo->length > 0) {
fat = __CARDGetFatBlock(card);
fileInfo->offset += length;
fileInfo->iBlock = fat[fileInfo->iBlock];
if (fileInfo->iBlock < 5 || fileInfo->iBlock >= card->cBlock) {
result = CARD_RESULT_BROKEN;
goto error;
}
ASSERTLINE(94, OFFSET(fileInfo->length, CARD_PROGRAM_SIZE) == 0);
ASSERTLINE(95, OFFSET(fileInfo->offset, card->sectorSize) == 0);
result = __CARDWrite(chan, card->sectorSize * fileInfo->iBlock, fileInfo->length < card->sectorSize ? fileInfo->length : card->sectorSize, card->buffer, ProgramCallback);
if (result >= 0) {
return;
}
}
}
error:
callback = card->apiCallback;
card->apiCallback = NULL;
__CARDPutControlBlock(card, result);
ASSERTLINE(114, callback);
callback(chan, result);
}
s32 CARDProgramAsync(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset, CARDCallback callback) {
CARDControl* card;
s32 result;
CARDDir* dir;
CARDDir* ent;
ASSERTLINE(147, buf && OFFSET(buf, 32) == 0);
ASSERTLINE(148, OFFSET(offset, CARD_PROGRAM_SIZE) == 0);
ASSERTLINE(149, 0 < length && OFFSET(length, CARD_PROGRAM_SIZE) == 0);
if (offset & 0x7F || length & 0x7F) {
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDSeek(fileInfo, length, offset, &card);
if (result < 0) {
return result;
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileInfo->fileNo];
result = __CARDIsWritable(card, ent);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
DCStoreRange(buf, length);
card->apiCallback = callback ? callback : &__CARDDefaultApiCallback;
offset = fileInfo->offset & (card->sectorSize - 1);
length = length < (card->sectorSize - offset) ? length : card->sectorSize - offset;
result = __CARDWrite(fileInfo->chan, offset + (card->sectorSize * fileInfo->iBlock), length, buf, ProgramCallback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}
s32 CARDProgram(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset) {
s32 result = CARDProgramAsync(fileInfo, buf, length, offset, __CARDSyncCallback);
if (result < 0)
return result;
return __CARDSync(fileInfo->chan);
}

View File

@ -0,0 +1,82 @@
#include <dolphin/card.h>
#include "__card.h"
s32 __CARDRawReadAsync(s32 chan, void* buf, s32 length, s32 offset, CARDCallback callback) {
CARDControl* card;
s32 result;
ASSERTLINE(59, buf && ((u32) buf % 32) == 0);
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
ASSERTLINE(67, 0 < length && (length % CARD_SEG_SIZE) == 0 && length < CARD_MAX_SIZE);
ASSERTLINE(68, (offset % card->sectorSize) == 0);
DCInvalidateRange(buf, length);
result = __CARDRead(chan, offset, length, buf, callback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}
s32 __CARDRawRead(s32 chan, void* buf, s32 length, s32 offset) {
s32 result = __CARDRawReadAsync(chan, buf, length, offset, __CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(chan);
}
static void EraseCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
card = &__CARDBlock[chan];
callback = card->apiCallback;
card->apiCallback = NULL;
__CARDPutControlBlock(card, result);
ASSERTLINE(117, callback);
callback(chan, result);
}
s32 __CARDRawEraseAsync(s32 chan, s32 offset, CARDCallback callback) {
CARDControl* card;
s32 result;
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
if (offset % card->sectorSize) {
return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR);
}
if ((card->size * 1024 * 1024) / 8 <= offset) {
return __CARDPutControlBlock(card, CARD_RESULT_LIMIT);
}
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
result = __CARDEraseSector(chan, offset, EraseCallback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}
s32 __CARDRawErase(s32 chan, s32 offset) {
s32 result = __CARDRawEraseAsync(chan, offset, __CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(chan);
}

View File

@ -0,0 +1,105 @@
#include <dolphin/card.h>
#include "__card.h"
// prototypes
static void BlockReadCallback(s32 chan, s32 result);
static void BlockWriteCallback(s32 chan, s32 result);
static void BlockReadCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
card = &__CARDBlock[chan];
if ((result >= 0)) {
card->xferred += 0x200;
card->addr += 0x200;
((u8*)card->buffer) += 0x200;
if (--card->repeat > 0) {
result = __CARDReadSegment(chan, BlockReadCallback);
if (result >= 0) {
return;
}
}
}
if (!card->apiCallback) {
__CARDPutControlBlock(card, result);
}
callback = card->xferCallback;
if (callback) {
card->xferCallback = NULL;
callback(chan, result);
}
}
s32 __CARDRead(s32 chan, u32 addr, s32 length, void* dst, CARDCallback callback) {
CARDControl* card;
ASSERTLINE(91, 0 < length && length % CARD_SEG_SIZE == 0);
ASSERTLINE(92, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (card->attached == 0) {
return CARD_RESULT_NOCARD;
}
card->xferCallback = callback;
card->repeat = (length / 512u);
card->addr = addr;
card->buffer = dst;
return __CARDReadSegment(chan, BlockReadCallback);
}
static void BlockWriteCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
card = &__CARDBlock[chan];
if (result >= 0) {
card->xferred += card->pageSize;
card->addr += card->pageSize;
((u8*)card->buffer) += card->pageSize;
if (--card->repeat > 0) {
result = __CARDWritePage(chan, BlockWriteCallback);
if (result >= 0) {
return;
}
}
}
if (!card->apiCallback) {
__CARDPutControlBlock(card, result);
}
callback = card->xferCallback;
if (callback) {
card->xferCallback = NULL;
callback(chan, result);
}
}
s32 __CARDWrite(s32 chan, u32 addr, s32 length, void* dst, CARDCallback callback) {
CARDControl* card;
card = &__CARDBlock[chan];
ASSERTLINE(153, 0 < length && length % card->pageSize == 0);
ASSERTLINE(154, 0 <= chan && chan < 2);
if (card->attached == 0) {
return CARD_RESULT_NOCARD;
}
card->xferCallback = callback;
card->repeat = (length / card->pageSize);
card->addr = addr;
card->buffer = dst;
return __CARDWritePage(chan, BlockWriteCallback);
}
s32 CARDGetXferredBytes(s32 chan) {
ASSERTLINE(183, 0 <= chan && chan < 2);
return __CARDBlock[chan].xferred;
}

View File

@ -0,0 +1,174 @@
#include <dolphin/card.h>
#include "__card.h"
#define TRUNC(n, a) (((u32)(n)) & ~((a)-1))
// prototypes
static void ReadCallback(s32 chan, s32 result);
s32 __CARDSeek(CARDFileInfo* fileInfo, s32 length, s32 offset, CARDControl** pcard) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
u16* fat;
ASSERTLINE(98, 0 <= fileInfo->chan && fileInfo->chan < 2);
ASSERTLINE(99, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE);
result = __CARDGetControlBlock(fileInfo->chan, &card);
if (result < 0)
return result;
ASSERTLINE(106, CARDIsValidBlockNo(card, fileInfo->iBlock));
ASSERTLINE(107, fileInfo->offset < card->cBlock * card->sectorSize);
if (!CARDIsValidBlockNo(card, fileInfo->iBlock) || card->cBlock * card->sectorSize <= fileInfo->offset)
return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR);
dir = __CARDGetDirBlock(card);
ent = &dir[fileInfo->fileNo];
ASSERTLINE(117, ent->gameName[0] != 0xff);
if (ent->length * card->sectorSize <= offset || ent->length * card->sectorSize < offset + length)
return __CARDPutControlBlock(card, CARD_RESULT_LIMIT);
card->fileInfo = fileInfo;
fileInfo->length = length;
if (offset < fileInfo->offset) {
fileInfo->offset = 0;
fileInfo->iBlock = ent->startBlock;
if (!CARDIsValidBlockNo(card, fileInfo->iBlock))
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
}
fat = __CARDGetFatBlock(card);
while (fileInfo->offset < TRUNC(offset, card->sectorSize)) {
fileInfo->offset += card->sectorSize;
fileInfo->iBlock = fat[fileInfo->iBlock];
if (!CARDIsValidBlockNo(card, fileInfo->iBlock))
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
}
fileInfo->offset = offset;
*pcard = card;
return CARD_RESULT_READY;
}
static void ReadCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
u16* fat;
CARDFileInfo* fileInfo;
s32 length;
card = &__CARDBlock[chan];
if (result < 0)
goto error;
fileInfo = card->fileInfo;
if (fileInfo->length < 0) {
result = CARD_RESULT_CANCELED;
goto error;
}
length = TRUNC(fileInfo->offset + card->sectorSize, card->sectorSize) - fileInfo->offset;
fileInfo->length -= length;
if (fileInfo->length <= 0)
goto error;
fat = __CARDGetFatBlock(card);
fileInfo->offset += length;
fileInfo->iBlock = fat[fileInfo->iBlock];
if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) {
result = CARD_RESULT_BROKEN;
goto error;
}
ASSERTLINE(199, OFFSET(fileInfo->length, CARD_SEG_SIZE) == 0);
ASSERTLINE(200, OFFSET(fileInfo->offset, card->sectorSize) == 0);
result = __CARDRead(chan, card->sectorSize * (u32)fileInfo->iBlock,
(fileInfo->length < card->sectorSize) ? fileInfo->length : card->sectorSize, card->buffer,
ReadCallback);
if (result < 0)
goto error;
return;
error:
callback = card->apiCallback;
card->apiCallback = NULL;
__CARDPutControlBlock(card, result);
ASSERTLINE(217, callback);
callback(chan, result);
}
s32 CARDReadAsync(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset, CARDCallback callback) {
CARDControl* card;
s32 result;
CARDDir* dir;
CARDDir* ent;
ASSERTLINE(250, buf && OFFSET(buf, 32) == 0);
ASSERTLINE(251, OFFSET(offset, CARD_SEG_SIZE) == 0);
ASSERTLINE(252, 0 < length && OFFSET(length, CARD_SEG_SIZE) == 0);
if (OFFSET(offset, CARD_SEG_SIZE) != 0 || OFFSET(length, CARD_SEG_SIZE) != 0)
return CARD_RESULT_FATAL_ERROR;
result = __CARDSeek(fileInfo, length, offset, &card);
if (result < 0)
return result;
dir = __CARDGetDirBlock(card);
ent = &dir[fileInfo->fileNo];
result = __CARDIsReadable(card, ent);
if (result < 0)
return __CARDPutControlBlock(card, result);
DCInvalidateRange(buf, (u32)length);
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
offset = (s32)OFFSET(fileInfo->offset, card->sectorSize);
length = (length < card->sectorSize - offset) ? length : card->sectorSize - offset;
result = __CARDRead(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock + offset, length, buf, ReadCallback);
if (result < 0)
__CARDPutControlBlock(card, result);
return result;
}
s32 CARDRead(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset) {
s32 result = CARDReadAsync(fileInfo, buf, length, offset, __CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(fileInfo->chan);
}
s32 CARDCancel(CARDFileInfo* fileInfo) {
BOOL enabled;
s32 result;
CARDControl* card;
ASSERTLINE(338, 0 <= fileInfo->chan && fileInfo->chan < 2);
ASSERTLINE(339, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE);
enabled = OSDisableInterrupts();
card = &__CARDBlock[fileInfo->chan];
result = CARD_RESULT_READY;
if (!card->attached)
result = CARD_RESULT_NOCARD;
else if (card->result == CARD_RESULT_BUSY && card->fileInfo == fileInfo) {
fileInfo->length = -1;
result = CARD_RESULT_CANCELED;
}
OSRestoreInterrupts(enabled);
return result;
}

View File

@ -0,0 +1,70 @@
#include <dolphin/card.h>
#include "__card.h"
s32 CARDRenameAsync(s32 chan, const char* old, const char* new, CARDCallback callback) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
int fileNo;
int newNo;
int oldNo;
ASSERTLINE(0x56, 0 <= chan && chan < 2);
ASSERTLINE(0x57, *old != 0xff && *new != 0xff);
ASSERTLINE(0x58, *old != 0x00 && *new != 0x00);
if (old[0] == 0xFF || new[0] == 0xFF || old[0] == 0 || new[0] == 0)
return CARD_RESULT_FATAL_ERROR;
if (CARD_FILENAME_MAX < (u32)strlen(old) || CARD_FILENAME_MAX < (u32)strlen(new))
return CARD_RESULT_NAMETOOLONG;
result = __CARDGetControlBlock(chan, &card);
if (result < 0)
return result;
newNo = oldNo = -1;
dir = __CARDGetDirBlock(card);
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
ent = &dir[fileNo];
if (ent->gameName[0] == 0xFF)
continue;
if (memcmp(ent->gameName, card->diskID->gameName, sizeof(ent->gameName)) != 0
|| memcmp(ent->company, card->diskID->company, sizeof(ent->company)) != 0)
continue;
if (__CARDCompareFileName(ent, old))
oldNo = fileNo;
if (__CARDCompareFileName(ent, new))
newNo = fileNo;
}
if (oldNo == -1)
return __CARDPutControlBlock(card, CARD_RESULT_NOFILE);
if (newNo != -1)
return __CARDPutControlBlock(card, CARD_RESULT_EXIST);
ent = &dir[oldNo];
result = __CARDIsWritable(card, ent);
if (result < 0)
return __CARDPutControlBlock(card, result);
strncpy((char*)ent->fileName, new, CARD_FILENAME_MAX);
ent->time = (u32)OSTicksToSeconds(OSGetTime());
result = __CARDUpdateDir(chan, callback);
if (result < 0)
__CARDPutControlBlock(card, result);
return result;
}
s32 CARDRename(s32 chan, const char* old, const char* new) {
s32 result = CARDRenameAsync(chan, old, new, __CARDSyncCallback);
if (result < 0)
return result;
return __CARDSync(chan);
}

View File

@ -0,0 +1,156 @@
#include <dolphin/card.h>
#include "__card.h"
static void UpdateIconOffsets(CARDDir* ent, CARDStat* stat) {
u32 offset;
BOOL iconTlut;
int i;
offset = ent->iconAddr;
if (offset == 0xffffffff) {
stat->bannerFormat = 0;
stat->iconFormat = 0;
stat->iconSpeed = 0;
offset = 0;
}
iconTlut = FALSE;
switch (CARDGetBannerFormat(ent)) {
case CARD_STAT_BANNER_C8:
stat->offsetBanner = offset;
offset += CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT;
stat->offsetBannerTlut = offset;
offset += 2 * 256;
break;
case CARD_STAT_BANNER_RGB5A3:
stat->offsetBanner = offset;
offset += 2 * CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT;
stat->offsetBannerTlut = 0xffffffff;
break;
default:
stat->offsetBanner = 0xffffffff;
stat->offsetBannerTlut = 0xffffffff;
break;
}
for (i = 0; i < CARD_ICON_MAX; ++i) {
switch (CARDGetIconFormat(ent, i)) {
case CARD_STAT_ICON_C8:
stat->offsetIcon[i] = offset;
offset += CARD_ICON_WIDTH * CARD_ICON_HEIGHT;
iconTlut = TRUE;
break;
case CARD_STAT_ICON_RGB5A3:
stat->offsetIcon[i] = offset;
offset += 2 * CARD_ICON_WIDTH * CARD_ICON_HEIGHT;
break;
default:
stat->offsetIcon[i] = 0xffffffff;
break;
}
}
if (iconTlut) {
stat->offsetIconTlut = offset;
offset += 2 * 256;
} else {
stat->offsetIconTlut = 0xffffffff;
}
stat->offsetData = offset;
}
s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat* stat) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
ASSERTLINE(172, 0 <= chan && chan < 2);
ASSERTLINE(173, 0 <= fileNo && fileNo < CARD_MAX_FILE);
if (fileNo < 0 || CARD_MAX_FILE <= fileNo)
return CARD_RESULT_FATAL_ERROR;
result = __CARDGetControlBlock(chan, &card);
if (result < 0)
return result;
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
result = __CARDIsReadable(card, ent);
if (result >= 0) {
memcpy(stat->gameName, ent->gameName, sizeof(stat->gameName));
memcpy(stat->company, ent->company, sizeof(stat->company));
stat->length = (u32)ent->length * card->sectorSize;
memcpy(stat->fileName, ent->fileName, CARD_FILENAME_MAX);
stat->time = ent->time;
stat->bannerFormat = ent->bannerFormat;
stat->iconAddr = ent->iconAddr;
stat->iconFormat = ent->iconFormat;
stat->iconSpeed = ent->iconSpeed;
stat->commentAddr = ent->commentAddr;
UpdateIconOffsets(ent, stat);
}
return __CARDPutControlBlock(card, result);
}
s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat* stat, CARDCallback callback) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
ASSERTLINE(231, 0 <= fileNo && fileNo < CARD_MAX_FILE);
ASSERTLINE(232, 0 <= chan && chan < 2);
ASSERTMSGLINE(240, stat->iconAddr == 0xffffffff || stat->iconAddr < CARD_READ_SIZE, "CARDSetStatus[Async](): stat->iconAddr must be 0xffffffff or less than CARD_READ_SIZE.");
ASSERTMSGLINE(243, stat->commentAddr == 0xffffffff || (stat->commentAddr & 0x1FFF) <= 8128, "CARDSetStatus[Async](): comment strings (set by stat->commentAddr) must not cross 8KB byte boundary.");
if (fileNo < 0 || CARD_MAX_FILE <= fileNo ||
(stat->iconAddr != 0xffffffff && CARD_READ_SIZE <= stat->iconAddr) ||
(stat->commentAddr != 0xffffffff &&
CARD_SYSTEM_BLOCK_SIZE - CARD_COMMENT_SIZE < stat->commentAddr % CARD_SYSTEM_BLOCK_SIZE))
{
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0)
return result;
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
result = __CARDIsWritable(card, ent);
if (result < 0)
return __CARDPutControlBlock(card, result);
ent->bannerFormat = stat->bannerFormat;
ent->iconAddr = stat->iconAddr;
ent->iconFormat = stat->iconFormat;
ent->iconSpeed = stat->iconSpeed;
ent->commentAddr = stat->commentAddr;
UpdateIconOffsets(ent, stat);
if (ent->iconAddr == 0xffffffff) {
CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST);
}
ent->time = (u32)OSTicksToSeconds(OSGetTime());
result = __CARDUpdateDir(chan, callback);
if (result < 0)
__CARDPutControlBlock(card, result);
return result;
}
s32 CARDSetStatus(s32 chan, s32 fileNo, CARDStat* stat) {
s32 result = CARDSetStatusAsync(chan, fileNo, stat, __CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(chan);
}

View File

@ -0,0 +1,124 @@
#include <dolphin/dolphin.h>
#include <dolphin/card.h>
#include "__card.h"
s32 __CARDGetStatusEx(s32 chan, s32 fileNo, CARDDir* dirent) {
ASSERTLINE(85, 0 <= chan && chan < 2);
ASSERTLINE(86, 0 <= fileNo && fileNo < CARD_MAX_FILE);
if ((fileNo < 0) || (fileNo >= CARD_MAX_FILE)) {
return CARD_RESULT_FATAL_ERROR;
}
{
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
result = __CARDIsReadable(card, ent);
if (result >= 0) {
memcpy(dirent, ent, 0x40);
}
return __CARDPutControlBlock(card, result);
}
}
s32 __CARDSetStatusExAsync(s32 chan, s32 fileNo, CARDDir* dirent, CARDCallback callback) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
u8* p;
s32 i;
ASSERTLINE(142, 0 <= fileNo && fileNo < CARD_MAX_FILE);
ASSERTLINE(143, 0 <= chan && chan < 2);
ASSERTLINE(144, *dirent->fileName != 0xff && *dirent->fileName != 0x00);
ASSERTMSGLINE(152, dirent->iconAddr == 0xffffffff || dirent->iconAddr < CARD_READ_SIZE, "CARDSetStatus[Async](): stat->iconAddr must be 0xffffffff or less than CARD_READ_SIZE.");
ASSERTMSGLINE(155, dirent->commentAddr == 0xffffffff || (dirent->commentAddr & 0x1FFF) <= 8128, "CARDSetStatus[Async](): comment strings (set by stat->commentAddr) must not cross 8KB byte boundary.");
if ((fileNo < 0) || (fileNo >= CARD_MAX_FILE) || ((u8) dirent->fileName[0] == 0xFF) || ((u8) dirent->fileName[0] == 0)) {
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
result = __CARDIsWritable(card, ent);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
for (p = dirent->fileName; p < (u8*)&dirent->time; p++) {
if (*p != 0) {
continue;
}
while ((++p) < (u8*)&dirent->time) {
*p = 0;
}
break;
}
if (dirent->permission & 0x20) {
memset(dirent->gameName, 0, sizeof(dirent->gameName));
memset(dirent->company, 0, sizeof(dirent->company));
}
if (dirent->permission & 0x40) {
memset(dirent->gameName, 0, sizeof(dirent->gameName));
}
if ((memcmp(&ent->fileName, &dirent->fileName, 32) != 0) || (memcmp(ent->gameName, dirent->gameName, 4) != 0) || (memcmp(ent->company, dirent->company, 2) != 0)) {
for(i = 0; i < CARD_MAX_FILE; i++) {
if (i != fileNo) {
CARDDir* ent = &dir[i]; // sure, just redeclare ent again...
if (((u8) ent->gameName[0] != 0xFF)
&& (memcmp(&ent->gameName, &dirent->gameName, 4) == 0)
&& (memcmp(&ent->company, &dirent->company, 2) == 0)
&& (memcmp(&ent->fileName, &dirent->fileName, 0x20) == 0)) {
return __CARDPutControlBlock(card, -7);
}
}
}
memcpy(&ent->fileName, &dirent->fileName, 0x20);
memcpy(&ent->gameName, &dirent->gameName, 4);
memcpy(&ent->company, &dirent->company, 2);
}
ent->time = dirent->time;
ent->bannerFormat = dirent->bannerFormat;
ent->iconAddr = dirent->iconAddr;
ent->iconFormat = dirent->iconFormat;
ent->iconSpeed = dirent->iconSpeed;
ent->commentAddr = dirent->commentAddr;
ent->permission = dirent->permission;
ent->copyTimes = dirent->copyTimes;
result = __CARDUpdateDir(chan, callback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}
s32 __CARDSetStatusEx(s32 chan, s32 fileNo, CARDDir* dirent) {
s32 result = __CARDSetStatusExAsync(chan, fileNo, dirent, &__CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(chan);
}

View File

@ -0,0 +1,405 @@
#include <stdlib.h>
#include <dolphin/dolphin.h>
#include <dolphin/card.h>
#include "__card.h"
static u8 CardData[352] ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT) = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0xFF, 0x00, 0x21, 0x13, 0x06, 0x12, 0x03, 0x12, 0x04,
0x13, 0x05, 0x00, 0x92, 0x00, 0xFF, 0x00, 0x88, 0xFF, 0xFF, 0x00, 0x89, 0xFF, 0xFF, 0x00, 0x8A, 0xFF, 0xFF, 0x00,
0x8B, 0xFF, 0xFF, 0x8F, 0x00, 0x02, 0xBF, 0x00, 0x88, 0x16, 0xFC, 0xDC, 0xD1, 0x16, 0xFD, 0x00, 0x00, 0x16, 0xFB,
0x00, 0x01, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x03, 0x80, 0xFF, 0x00, 0x02, 0x94, 0x00, 0x27, 0x02, 0xBF, 0x00,
0x8E, 0x1F, 0xDF, 0x24, 0xFF, 0x02, 0x40, 0x0F, 0xFF, 0x00, 0x98, 0x04, 0x00, 0x00, 0x9A, 0x00, 0x10, 0x00, 0x99,
0x00, 0x00, 0x8E, 0x00, 0x02, 0xBF, 0x00, 0x94, 0x02, 0xBF, 0x86, 0x44, 0x02, 0xBF, 0x00, 0x88, 0x16, 0xFC, 0xDC,
0xD1, 0x16, 0xFD, 0x00, 0x03, 0x16, 0xFB, 0x00, 0x01, 0x8F, 0x00, 0x02, 0xBF, 0x00, 0x8E, 0x03, 0x80, 0xCD, 0xD1,
0x02, 0x94, 0x00, 0x48, 0x27, 0xFF, 0x03, 0x80, 0x00, 0x01, 0x02, 0x95, 0x00, 0x5A, 0x03, 0x80, 0x00, 0x02, 0x02,
0x95, 0x80, 0x00, 0x02, 0x9F, 0x00, 0x48, 0x00, 0x21, 0x8E, 0x00, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF,
0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC5, 0xFF, 0xFF, 0x03,
0x40, 0x0F, 0xFF, 0x1C, 0x9F, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC7, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC6,
0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC0, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x20, 0xFF, 0x03, 0x40, 0x0F,
0xFF, 0x1F, 0x5F, 0x02, 0xBF, 0x00, 0x8E, 0x21, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x23, 0xFF, 0x12, 0x05, 0x12, 0x06,
0x02, 0x9F, 0x80, 0xB5, 0x00, 0x21, 0x27, 0xFC, 0x03, 0xC0, 0x80, 0x00, 0x02, 0x9D, 0x00, 0x88, 0x02, 0xDF, 0x27,
0xFE, 0x03, 0xC0, 0x80, 0x00, 0x02, 0x9C, 0x00, 0x8E, 0x02, 0xDF, 0x2E, 0xCE, 0x2C, 0xCF, 0x00, 0xF8, 0xFF, 0xCD,
0x00, 0xF9, 0xFF, 0xC9, 0x00, 0xFA, 0xFF, 0xCB, 0x26, 0xC9, 0x02, 0xC0, 0x00, 0x04, 0x02, 0x9D, 0x00, 0x9C, 0x02,
0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static u32 next = 1;
// prototypes
static u32 exnor_1st(u32 data, u32 rshift);
static u32 exnor(u32 data, u32 lshift);
static u32 bitrev(u32 data);
static s32 ReadArrayUnlock(s32 chan, u32 data, void* rbuf, s32 rlen, int mode);
static u32 GetInitVal(void);
static s32 DummyLen(void);
static void InitCallback(void* _task);
static void DoneCallback(void* _task);
static int CARDRand(void) {
next = (next * 0x41C64E6D) + 0x3039;
return (next / 0x10000) & 0x7FFF;
}
static void CARDSrand(unsigned int seed) {
next = seed;
}
static u32 exnor_1st(u32 data, u32 rshift) {
u32 wk;
u32 work;
u32 i;
work = data;
for (i = 0; i < rshift; i++) {
wk = ~(work ^ (work >> 7) ^ (work >> 15) ^ (work >> 23));
work = (work >> 1) | ((wk << 30) & 0x40000000);
}
return work;
}
static u32 exnor(u32 data, u32 lshift) {
u32 wk;
u32 work;
u32 i;
work = data;
for (i = 0; i < lshift; i++) {
// 1bit Left Shift
wk = ~(work ^ (work << 7) ^ (work << 15) ^ (work << 23));
work = (work << 1) | ((wk >> 30) & 0x00000002);
}
return work;
}
static u32 bitrev(u32 data) {
u32 wk;
u32 i;
u32 k = 0;
u32 j = 1;
wk = 0;
for (i = 0; i < 32; i++) {
if (i > 15) {
if (i == 31)
wk |= (((data & (0x01 << 31)) >> 31) & 0x01);
else {
wk |= ((data & (0x01 << i)) >> j);
j += 2;
}
} else {
wk |= ((data & (0x01 << i)) << (31 - i - k));
k++;
}
}
return wk;
}
#define SEC_AD1(x) ((u8)(((x) >> 29) & 0x03))
#define SEC_AD2(x) ((u8)(((x) >> 21) & 0xff))
#define SEC_AD3(x) ((u8)(((x) >> 19) & 0x03))
#define SEC_BA(x) ((u8)(((x) >> 12) & 0x7f))
static s32 ReadArrayUnlock(s32 chan, u32 data, void* rbuf, s32 rlen, int mode) {
CARDControl* card;
BOOL err;
u8 cmd[5];
ASSERTLINE(240, 0 <= chan && chan < 2);
card = &__CARDBlock[chan];
if (!EXISelect(chan, 0, CARDFreq))
return CARD_RESULT_NOCARD;
data &= 0xfffff000;
memset(cmd, 0, 5);
cmd[0] = 0x52;
if (mode == 0) {
cmd[1] = SEC_AD1(data);
cmd[2] = SEC_AD2(data);
cmd[3] = SEC_AD3(data);
cmd[4] = SEC_BA(data);
} else {
cmd[1] = (u8)((data & 0xff000000) >> 24);
cmd[2] = (u8)((data & 0x00ff0000) >> 16);
}
err = FALSE;
err |= !EXIImmEx(chan, cmd, 5, 1);
err |= !EXIImmEx(chan, (u8* )card->workArea + (u32)sizeof(CARDID), card->latency, 1);
err |= !EXIImmEx(chan, rbuf, rlen, 0);
err |= !EXIDeselect(chan);
return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY;
}
static u32 GetInitVal(void) {
u32 tmp;
u32 tick;
tick = OSGetTick();
CARDSrand(tick);
tmp = 0x7fec8000;
tmp |= CARDRand();
tmp &= 0xfffff000;
return tmp;
}
static s32 DummyLen(void) {
u32 tick;
u32 wk;
s32 tmp;
u32 max;
wk = 1;
max = 0;
tick = OSGetTick();
CARDSrand(tick);
tmp = CARDRand();
tmp &= 0x0000001f;
tmp += 1;
while ((tmp < 4) && (max < 10)) {
tick = OSGetTick();
tmp = (s32)(tick << wk);
wk++;
if (wk > 16)
wk = 1;
CARDSrand((u32)tmp);
tmp = CARDRand();
tmp &= 0x0000001f;
tmp += 1;
max++;
}
if (tmp < 4)
tmp = 4;
return tmp;
}
s32 __CARDUnlock(s32 chan, u8 flashID[12]) {
u32 init_val;
u32 data;
s32 dummy;
s32 rlen;
u32 rshift;
u8 fsts;
u32 wk, wk1;
u32 Ans1 = 0;
u32 Ans2 = 0;
u32* dp;
u8 rbuf[64];
u32 para1A = 0;
u32 para1B = 0;
u32 para2A = 0;
u32 para2B = 0;
CARDControl* card;
DSPTaskInfo* task;
CARDDecParam* param;
u8* input;
u8* output;
card = &__CARDBlock[chan];
task = &card->task;
param = (CARDDecParam*)card->workArea;
input = (u8*)((u8* )param + sizeof(CARDDecParam));
input = (u8*)OSRoundUp32B(input);
output = input + 32;
fsts = 0;
init_val = GetInitVal();
dummy = DummyLen();
rlen = dummy;
if (ReadArrayUnlock(chan, init_val, rbuf, rlen, 0) < 0)
return CARD_RESULT_NOCARD;
rshift = (u32)(dummy * 8 + 1);
wk = exnor_1st(init_val, rshift);
wk1 = ~(wk ^ (wk >> 7) ^ (wk >> 15) ^ (wk >> 23));
card->scramble = (wk | ((wk1 << 31) & 0x80000000));
card->scramble = bitrev(card->scramble);
dummy = DummyLen();
rlen = 20 + dummy;
data = 0;
if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0)
return CARD_RESULT_NOCARD;
dp = (u32* )rbuf;
para1A = *dp++;
para1B = *dp++;
Ans1 = *dp++;
para2A = *dp++;
para2B = *dp++;
para1A = (para1A ^ card->scramble);
rshift = 32;
wk = exnor(card->scramble, rshift);
wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23));
card->scramble = (wk | ((wk1 >> 31) & 0x00000001));
para1B = (para1B ^ card->scramble);
rshift = 32;
wk = exnor(card->scramble, rshift);
wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23));
card->scramble = (wk | ((wk1 >> 31) & 0x00000001));
Ans1 ^= card->scramble;
rshift = 32;
wk = exnor(card->scramble, rshift);
wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23));
card->scramble = (wk | ((wk1 >> 31) & 0x00000001));
para2A = (para2A ^ card->scramble);
rshift = 32;
wk = exnor(card->scramble, rshift);
wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23));
card->scramble = (wk | ((wk1 >> 31) & 0x00000001));
para2B = (para2B ^ card->scramble);
rshift = (u32)(dummy * 8);
wk = exnor(card->scramble, rshift);
wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23));
card->scramble = (wk | ((wk1 >> 31) & 0x00000001));
rshift = 32 + 1;
wk = exnor(card->scramble, rshift);
wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23));
card->scramble = (wk | ((wk1 >> 31) & 0x00000001));
*(u32*)&input[0] = para2A;
*(u32*)&input[4] = para2B;
param->inputAddr = input;
param->inputLength = 8;
param->outputAddr = output;
param->aramAddr = 0;
DCFlushRange(input, 8);
DCInvalidateRange(output, 4);
DCFlushRange(param, sizeof(CARDDecParam));
task->priority = 255;
task->iram_mmem_addr = (u16*)OSCachedToPhysical(CardData);
task->iram_length = 0x160;
task->iram_addr = 0;
task->dsp_init_vector = 0x10;
task->init_cb = InitCallback;
task->res_cb = NULL;
task->done_cb = DoneCallback;
task->req_cb = NULL;
DSPAddTask(task);
dp = (u32*)flashID;
*dp++ = para1A;
*dp++ = para1B;
*dp = Ans1;
return CARD_RESULT_READY;
}
static void InitCallback(void* _task) {
s32 chan;
CARDControl* card;
DSPTaskInfo* task;
CARDDecParam* param;
task = _task;
for (chan = 0; chan < 2; ++chan) {
card = &__CARDBlock[chan];
if ((DSPTaskInfo*)&card->task == task)
break;
}
ASSERTLINE(514, 0 <= chan && chan < 2);
param = (CARDDecParam*)card->workArea;
DSPSendMailToDSP(0xff000000);
while (DSPCheckMailToDSP())
;
DSPSendMailToDSP((u32)param);
while (DSPCheckMailToDSP())
;
}
static void DoneCallback(void* _task) {
u8 rbuf[64];
u32 data;
s32 dummy;
s32 rlen;
u32 rshift;
u8 unk;
u32 wk, wk1;
u32 Ans2;
s32 chan;
CARDControl* card;
s32 result;
DSPTaskInfo* task;
CARDDecParam* param;
u8* input;
u8* output;
task = _task;
for (chan = 0; chan < 2; ++chan) {
card = &__CARDBlock[chan];
if ((DSPTaskInfo* )&card->task == task)
break;
}
ASSERTLINE(563, 0 <= chan && chan < 2);
param = (CARDDecParam*)card->workArea;
input = (u8*)((u8*)param + sizeof(CARDDecParam));
input = (u8*)OSRoundUp32B(input);
output = input + 32;
Ans2 = *(u32*)output;
dummy = DummyLen();
rlen = dummy;
data = ((Ans2 ^ card->scramble) & 0xffff0000);
if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) {
EXIUnlock(chan);
__CARDMountCallback(chan, CARD_RESULT_NOCARD);
return;
}
rshift = (u32)((dummy + 4 + card->latency) * 8 + 1);
wk = exnor(card->scramble, rshift);
wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23));
card->scramble = (wk | ((wk1 >> 31) & 0x00000001));
dummy = DummyLen();
rlen = dummy;
data = (((Ans2 << 16) ^ card->scramble) & 0xffff0000);
if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) {
EXIUnlock(chan);
__CARDMountCallback(chan, CARD_RESULT_NOCARD);
return;
}
result = __CARDReadStatus(chan, &unk);
if (!EXIProbe(chan)) {
EXIUnlock(chan);
__CARDMountCallback(chan, CARD_RESULT_NOCARD);
return;
}
if (result == CARD_RESULT_READY && !(unk & 0x40)) {
EXIUnlock(chan);
result = CARD_RESULT_IOERROR;
}
__CARDMountCallback(chan, result);
}

View File

@ -0,0 +1,123 @@
#include <dolphin/card.h>
#include "__card.h"
// prototypes
static void WriteCallback(s32 chan, s32 result);
static void EraseCallback(s32 chan, s32 result);
static void WriteCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
u16* fat;
CARDDir* dir;
CARDDir* ent;
CARDFileInfo* fileInfo;
card = &__CARDBlock[chan];
if (result >= 0) {
fileInfo = card->fileInfo;
if (fileInfo->length < 0) {
result = CARD_RESULT_CANCELED;
goto after;
}
fileInfo->length -= card->sectorSize;
if (fileInfo->length <= 0) {
dir = __CARDGetDirBlock(card);
ent = dir + fileInfo->fileNo;
ent->time = OSGetTime()/(__OSBusClock/4);
callback = card->apiCallback;
card->apiCallback = NULL;
result = __CARDUpdateDir(chan, callback);
goto check;
} else {
fat = __CARDGetFatBlock(card);
fileInfo->offset += card->sectorSize;
fileInfo->iBlock = fat[fileInfo->iBlock];
if ((fileInfo->iBlock < 5) || (fileInfo->iBlock >= card->cBlock)) {
result = CARD_RESULT_BROKEN;
goto after;
}
result = __CARDEraseSector(chan, card->sectorSize * fileInfo->iBlock, EraseCallback);
check:;
if (result < 0) {
goto after;
}
}
} else {
after:;
callback = card->apiCallback;
card->apiCallback = NULL;
__CARDPutControlBlock(card, result);
ASSERTLINE(0x86, callback);
callback(chan, result);
}
}
static void EraseCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
CARDFileInfo* fileInfo;
card = &__CARDBlock[chan];
if (result >= 0) {
fileInfo = card->fileInfo;
ASSERTLINE(161, OFFSET(fileInfo->offset, card->sectorSize) == 0);
result = __CARDWrite(chan, card->sectorSize * fileInfo->iBlock, card->sectorSize, card->buffer, WriteCallback);
if (result < 0) {
goto after;
}
} else {
after:;
callback = card->apiCallback;
card->apiCallback = NULL;
__CARDPutControlBlock(card, result);
ASSERTLINE(175, callback);
callback(chan, result);
}
}
s32 CARDWriteAsync(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset, CARDCallback callback) {
CARDControl* card;
s32 result;
CARDDir* dir;
CARDDir* ent;
ASSERTLINE(210, buf && ((u32) buf % 32) == 0);
ASSERTLINE(211, 0 < length);
result = __CARDSeek(fileInfo, length, offset, &card);
if (result < 0) {
return result;
}
ASSERTLINE(217, OFFSET(offset, card->sectorSize) == 0);
ASSERTLINE(218, OFFSET(length, card->sectorSize) == 0);
if (OFFSET(offset, card->sectorSize) != 0 || OFFSET(length, card->sectorSize) != 0)
return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR);
dir = __CARDGetDirBlock(card);
ent = &dir[fileInfo->fileNo];
result = __CARDIsWritable(card, ent);
if (result < 0)
return __CARDPutControlBlock(card, result);
DCStoreRange((void*)buf, (u32)length);
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
card->buffer = (void*)buf;
result = __CARDEraseSector(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock, EraseCallback);
if (result < 0)
__CARDPutControlBlock(card, result);
return result;
}
s32 CARDWrite(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset) {
s32 result = CARDWriteAsync(fileInfo, buf, length, offset, __CARDSyncCallback);
if (result < 0) {
return result;
}
return __CARDSync(fileInfo->chan);
}

View File

@ -0,0 +1,104 @@
#ifndef _REVOLUTION_CARD_INTERNAL_H_
#define _REVOLUTION_CARD_INTERNAL_H_
#include <revolution/card.h>
#include <revolution/exi.h>
#ifdef __cplusplus
extern "C" {
#endif
// CARDStatEx
s32 __CARDGetStatusEx(s32 chan, s32 fileNo, CARDDir* dirent);
s32 __CARDSetStatusExAsync(s32 chan, s32 fileNo, CARDDir* dirent, CARDCallback callback);
s32 __CARDSetStatusEx(s32 chan, s32 fileNo, CARDDir* dirent);
// CARDUnlock
s32 __CARDUnlock(s32 chan, u8 flashID[12]);
// CARDRead
s32 __CARDSeek(CARDFileInfo* fileInfo, s32 length, s32 offset, CARDControl** pcard);
// CARDRdwr
s32 __CARDRead(s32 chan, u32 addr, s32 length, void* dst, CARDCallback callback);
s32 __CARDWrite(s32 chan, u32 addr, s32 length, void* dst, CARDCallback callback);
// CARDRaw
s32 __CARDRawReadAsync(s32 chan, void* buf, s32 length, s32 offset, CARDCallback callback);
s32 __CARDRawRead(s32 chan, void* buf, s32 length, s32 offset);
s32 __CARDRawErase(s32 chan, s32 offset);
s32 __CARDRawEraseAsync(s32 chan, s32 offset, CARDCallback callback);
// CARDOpen
BOOL __CARDCompareFileName(CARDDir* ent, const char* fileName);
s32 __CARDAccess(CARDControl* card, CARDDir* ent);
s32 __CARDIsPublic(CARDDir* ent);
s32 __CARDGetFileNo(CARDControl* card, const char* fileName, s32* pfileNo);
BOOL __CARDIsOpened(CARDControl* card, s32 fileNo);
s32 __CARDIsWritable(CARDControl* card, CARDDir* ent);
s32 __CARDIsReadable(CARDControl* card, CARDDir* ent);
// CARDNet
extern u16 __CARDVendorID;
extern u8 __CARDPermMask;
int __CARDEnableGlobal(int enable);
int __CARDEnableCompany(int enable);
// CARDMount
void __CARDMountCallback(s32 chan, s32 result);
void __CARDDisable(BOOL disable);
// CARDFormat
s32 CARDFormatAsync(s32 chan, CARDCallback callback);
s32 __CARDFormatRegionAsync(s32 chan, u16 encode, CARDCallback callback);
s32 __CARDFormatRegion(s32 chan, u16 encode);
// CARDDir
CARDDir* __CARDGetDirBlock(CARDControl* card);
s32 __CARDUpdateDir(s32 chan, CARDCallback callback);
// CARDCheck
void __CARDCheckSum(void* ptr, int length, u16* checksum, u16* checksumInv);
s32 __CARDVerify(CARDControl* card);
// CARDBlock
void* __CARDGetFatBlock(CARDControl* card);
s32 __CARDAllocBlock(s32 chan, u32 cBlock, CARDCallback callback);
s32 __CARDFreeBlock(s32 chan, u16 nBlock, CARDCallback callback);
s32 __CARDUpdateFatBlock(s32 chan, u16* fat, CARDCallback callback);
// CARDBios
extern CARDControl __CARDBlock[2];
extern DVDDiskID* __CARDDiskID;
extern DVDDiskID __CARDDiskNone;
void __CARDDefaultApiCallback(s32 chan, s32 result);
void __CARDSyncCallback(s32 chan, s32 result);
void __CARDExtHandler(s32 chan, OSContext* context);
void __CARDExiHandler(s32 chan, OSContext* context);
void __CARDTxHandler(s32 chan, OSContext* context);
void __CARDUnlockedHandler(s32 chan, OSContext* context);
int __CARDReadNintendoID(s32 chan, u32* id);
s32 __CARDEnableInterrupt(s32 chan, BOOL enable);
s32 __CARDReadStatus(s32 chan, u8* status);
int __CARDReadVendorID(s32 chan, u16* id);
s32 __CARDClearStatus(s32 chan);
s32 __CARDSleep(s32 chan);
s32 __CARDWakeup(s32 chan);
s32 __CARDReadSegment(s32 chan, CARDCallback callback);
s32 __CARDWritePage(s32 chan, CARDCallback callback);
s32 __CARDErase(s32 chan, CARDCallback callback);
s32 __CARDEraseSector(s32 chan, u32 addr, CARDCallback callback);
void __CARDSetDiskID(const DVDDiskID* id);
s32 __CARDGetControlBlock(s32 chan, CARDControl **pcard);
s32 __CARDPutControlBlock(CARDControl* card, s32 result);
s32 __CARDSync(s32 chan);
u16 __CARDGetFontEncode(void);
u16 __CARDSetFontEncode(u16 encode);
#ifdef __cplusplus
}
#endif
#endif // _DOLPHIN_CARD_INTERNAL_H_

View File

@ -0,0 +1,33 @@
#include "HBMAnmController.h"
#include "nw4hbm/lyt/animation.h"
#include "nw4hbm/lyt/group.h"
namespace homebutton {
GroupAnmController::GroupAnmController() : mpGroup(), mpAnimGroup() {}
GroupAnmController::~GroupAnmController() {}
void GroupAnmController::do_calc() {
bool flag;
if (mState == ANIM_STATE_PLAY) {
calc();
flag = true;
mpAnimGroup->SetFrame(mFrame);
} else {
flag = false;
}
nw4hbm::lyt::PaneLinkList& list = mpGroup->GetPaneList();
for (nw4hbm::lyt::PaneLinkList::Iterator it = list.GetBeginIter(); it != list.GetEndIter();
it++)
{
it->mTarget->SetAnimationEnable(mpAnimGroup, flag, false);
}
}
} // namespace homebutton

View File

@ -0,0 +1,29 @@
#ifndef HOMEBUTTON_ANM_CONTROLLER_H
#define HOMEBUTTON_ANM_CONTROLLER_H
#include "HBMFrameController.h"
namespace nw4hbm {
namespace lyt {
class AnimTransform;
class Group;
} // namespace lyt
} // namespace nw4hbm
namespace homebutton {
class GroupAnmController : public FrameController {
public:
/* 0x00 (base) */
/* 0x20 */ nw4hbm::lyt::Group* mpGroup;
/* 0x24 */ nw4hbm::lyt::AnimTransform* mpAnimGroup;
GroupAnmController();
virtual ~GroupAnmController();
void do_calc();
}; // size = 0x28
} // namespace homebutton
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,295 @@
#ifndef HOMEBUTTON_BASE_H
#define HOMEBUTTON_BASE_H
#include <revolution/ax.h>
#include <revolution/axfx.h>
#include <revolution/wpad.h>
#include "HBMCommon.h"
#include "HBMController.h"
#include "HBMGUIManager.h"
#include "nw4hbm/lyt/drawInfo.h"
#include "nw4hbm/lyt/layout.h"
#include "nw4hbm/snd/DvdSoundArchive.h"
#include "nw4hbm/snd/MemorySoundArchive.h"
#include "nw4hbm/snd/NandSoundArchive.h"
#include "nw4hbm/snd/SoundArchivePlayer.h"
#include "nw4hbm/snd/SoundPlayer.h"
#include "nw4hbm/snd/SoundSystem.h"
#include "new.h"
namespace homebutton {
static void initgx();
static void drawBlackPlate(f32 left, f32 top, f32 right, f32 bottom);
static u32 get_comma_length(char* pBuf);
static void SpeakerCallback(OSAlarm* alm, OSContext* ctx);
static void MotorCallback(OSAlarm* alm, OSContext* ctx);
static void RetrySimpleSyncCallback(OSAlarm* alm, OSContext* ctx);
static void SimpleSyncCallback(s32 result, s32 num);
} // namespace homebutton
namespace nw4hbm {
namespace lyt {
class ArcResourceAccessor;
class ArcResourceLink;
class Layout;
class MultiArcResourceAccessor;
class Pane;
} // namespace lyt
namespace ut {
class ResFont;
}
} // namespace nw4hbm
namespace homebutton {
class HomeButton;
class Controller;
class GroupAnmController;
class RemoteSpk;
class HomeButtonEventHandler : public gui::EventHandler {
public:
HomeButtonEventHandler(homebutton::HomeButton* pHomeButton) : mpHomeButton(pHomeButton) {}
/* 0x08 */ virtual void onEvent(u32 uID, u32 uEvent, void* pData);
homebutton::HomeButton* getHomeButton() { return mpHomeButton; }
private:
/* 0x00 (base) */
/* 0x08 */ HomeButton* mpHomeButton;
}; // size = 0x0C
class HomeButton {
private:
typedef enum {
/* 0 */ eSeq_Normal,
/* 1 */ eSeq_Control,
/* 2 */ eSeq_Cmn,
} eSeq;
class BlackFader {
public:
BlackFader(int maxFrame) {
init(maxFrame);
setColor(0, 0, 0);
}
void setColor(u8 r, u8 g, u8 b) {
red_ = r;
green_ = g;
blue_ = b;
}
int getFrame() const { return frame_; }
int getMaxFrame() const { return maxFrame_; }
void start() { state_ = 1; }
GXColor GetColor(u8 alpha) { return (GXColor){red_, green_, blue_, alpha}; }
bool isDone();
void init(int maxFrame);
void calc();
void draw();
private:
/* 0x00 */ int frame_;
/* 0x04 */ int maxFrame_;
/* 0x08 */ int state_;
/* 0x0D */ u8 red_;
/* 0x0E */ u8 green_;
/* 0x0F */ u8 blue_;
}; // size = 0x10
public:
HomeButton(const HBMDataInfo* dataInfo);
~HomeButton();
int getVolume();
HBMSelectBtnNum getSelectBtnNum();
bool isActive() const;
bool isUpBarActive() const;
bool isDownBarActive();
void setAdjustFlag(int flag);
void setForcusSE();
void setSimpleSyncAlarm(int type);
void setSpeakerAlarm(int chan, int msec);
void setVolume(int vol);
bool getVibFlag();
int getPaneNo(const char*);
void setVibFlag(bool flag);
void create();
void init();
void calc(const HBMControllerData* pController);
void draw();
void update(const HBMControllerData* pController);
void updateTrigPane();
void startPointEvent(const char* pPane, void* pData);
void startLeftEvent(const char* pPane);
void startTrigEvent(const char* pPane);
int findAnimator(int pane, int anm);
int findGroupAnimator(int pane, int anm);
void callSimpleSyncCallback(s32 result, s32 num);
void startBlackOut();
const HBMDataInfo* getHBMDataInfo() { return mpHBInfo; }
Controller* getController(int chan) { return mpController[chan]; }
const char* getFuncPaneName(int no) { return scFuncTouchPaneName[no]; }
const char* getPaneName(int no) { return scBtnName[no]; }
bool getReassignedFlag() const { return mReassignedFlag; }
HomeButtonEventHandler* getEventHandler() const { return mpHomeButtonEventHandler; }
nw4hbm::snd::SoundArchivePlayer* GetSoundArchivePlayer() { return mpSoundArchivePlayer; }
void setEndSimpleSyncFlag(bool flag) { mEndSimpleSyncFlag = flag; }
void setReassignedFlag(bool flag) { mReassignedFlag = flag; }
void setSimpleSyncFlag(bool flag) { mSimpleSyncFlag = flag; }
static void createInstance(const HBMDataInfo* dataInfo);
static HomeButton* getInstance() { return spHomeButtonObj; }
static void deleteInstance();
private:
void init_battery(const HBMControllerData* pController);
void calc_battery(int chan);
void reset_battery();
void init_sound();
void fadeout_sound(f32 gain);
void init_msg();
void init_vib();
void init_volume();
void set_config();
void set_text();
void calc_fadeoutAnm();
void update_controller(int id);
void update_posController(int id);
void reset_btn();
void reset_control();
void reset_guiManager(int num);
void reset_window();
public:
void play_sound(int id);
void createSound(nw4hbm::snd::NandSoundArchive* pNandSoundArchive, bool bCreateSoundHeap);
void deleteSound();
void draw_impl();
void updateSoundArchivePlayer();
void setSoundVolume(f32 volume);
inline void stopSound(bool checkFlag);
void initSound(const char* path);
void updateSound();
void PlaySeq(int num) {
if (mpSoundArchivePlayer != NULL && mpSoundHandle != NULL) {
mpSoundHandle->DetachSound();
mpSoundArchivePlayer->StartSound(mpSoundHandle, num);
}
}
private:
/* 0x000 */ eSeq mSequence;
/* 0x004 */ const HBMDataInfo* mpHBInfo;
/* 0x008 */ int mButtonNum;
/* 0x00C */ int mAnmNum;
/* 0x010 */ int mState;
/* 0x014 */ int mSelectAnmNum;
/* 0x018 */ int mMsgCount;
/* 0x01C */ int mPaneCounter[14];
/* 0x054 */ int mPadDrawTime[WPAD_MAX_CONTROLLERS];
/* 0x064 */ int mForcusSEWaitTime;
/* 0x068 */ int mBar0AnmRev;
/* 0x06C */ int mBar1AnmRev;
/* 0x070 */ int mBar0AnmRevHold;
/* 0x074 */ int mBar1AnmRevHold;
/* 0x078 */ int mGetPadInfoTime;
/* 0x07C */ bool mControllerFlag[WPAD_MAX_CONTROLLERS];
/* 0x080 */ int mVolumeNum;
/* 0x084 */ bool mVibFlag;
/* 0x085 */ bool mControlFlag;
/* 0x086 */ bool mLetterFlag;
/* 0x087 */ bool mAdjustFlag;
/* 0x088 */ bool mReassignedFlag;
/* 0x089 */ bool mSimpleSyncFlag;
/* 0x08A */ bool mEndSimpleSyncFlag;
/* 0x08B */ bool mInitFlag;
/* 0x08C */ bool mForceSttInitProcFlag;
/* 0x08D */ bool mForceSttFadeInProcFlag;
/* 0x08E */ bool mEndInitSoundFlag;
/* 0x08F */ bool mForceStopSyncFlag;
/* 0x090 */ bool mForceEndMsgAnmFlag;
#if HBM_REVISION > 1
/* 0x094 */ int mSoundRetryCnt;
#endif
/* 0x098 */ int mDialogFlag[4];
/* 0x0A8 */ char* mpLayoutName;
/* 0x0AC */ char* mpAnmName;
/* 0x0B0 */ HBMSelectBtnNum mSelectBtnNum;
/* 0x0B4 */ wchar_t* mpText[7][6];
/* 0x15C */ WPADInfo mWpadInfo[WPAD_MAX_CONTROLLERS];
/* 0x1BC */ WPADSimpleSyncCallback mSimpleSyncCallback;
/* 0x1CC */ f32 mOnPaneVibFrame[4];
/* 0x1DC */ f32 mOnPaneVibWaitFrame[4];
/* 0x1E0 */ int mWaitStopMotorCount;
/* 0x1E4 */ nw4hbm::lyt::Layout* mpLayout;
/* 0x1E8 */ nw4hbm::lyt::Layout* mpCursorLayout[WPAD_MAX_CONTROLLERS];
/* 0x1F8 */ nw4hbm::lyt::ArcResourceAccessor* mpResAccessor;
/* 0x1FC */ gui::PaneManager* mpPaneManager;
/* 0x200 */ HomeButtonEventHandler* mpHomeButtonEventHandler;
/* 0x204 */ nw4hbm::lyt::DrawInfo mDrawInfo;
/* 0x258 */ Controller* mpController[WPAD_MAX_CONTROLLERS];
/* 0x268 */ RemoteSpk* mpRemoteSpk;
/* 0x26C */ GroupAnmController* mpAnmController[12];
/* 0x29C */ GroupAnmController* mpGroupAnmController[74];
/* 0x3C4 */ GroupAnmController* mpPairGroupAnmController[15];
/* 0x400 */ BlackFader mFader;
/* 0x410 */ OSAlarm mAlarm[WPAD_MAX_CONTROLLERS];
/* 0x4D0 */ OSAlarm mSpeakerAlarm[WPAD_MAX_CONTROLLERS];
/* 0x590 */ OSAlarm mSimpleSyncAlarm;
/* 0x5C0 */ nw4hbm::snd::SoundArchivePlayer* mpSoundArchivePlayer;
/* 0x5C4 */ nw4hbm::snd::DvdSoundArchive* mpDvdSoundArchive;
/* 0x5C8 */ nw4hbm::snd::MemorySoundArchive* mpMemorySoundArchive;
/* 0x5CC */ nw4hbm::snd::NandSoundArchive* mpNandSoundArchive;
/* 0x5D0 */ nw4hbm::snd::SoundHeap* mpSoundHeap;
/* 0x5D4 */ nw4hbm::snd::SoundHandle* mpSoundHandle;
/* 0x5D8 */ u16 mAppVolume[3];
/* 0x5E0 */ AXFXAllocFunc mAxFxAlloc;
/* 0x5E4 */ AXFXFreeFunc mAxFxFree;
/* 0x5E8 */ AXFX_REVERBHI mAxFxReverb;
/* 0x748 */ AXAuxCallback mAuxCallback;
/* 0x74C */ void* mpAuxContext;
/* 0x750 */ f32 mFadeOutSeTime;
// static members
private:
static HomeButton* spHomeButtonObj;
static const char* scCursorLytName[WPAD_MAX_CONTROLLERS];
static const char* scCursorPaneName;
static const char* scCursorRotPaneName;
static const char* scCursorSRotPaneName;
static const char* scBtnName[4];
static const char* scTxtName[4];
static const char* scGrName[8];
static const char* scAnimName[3];
static const char* scPairGroupAnimName[15];
static const char* scPairGroupName[15];
static const char* scGroupAnimName[22];
static const char* scGroupName[35];
static const char* scFuncPaneName[5];
static const char* scFuncTouchPaneName[10];
static const char* scFuncTextPaneName[3];
static const char* scBatteryPaneName[WPAD_MAX_CONTROLLERS][4];
}; // size = 0x740
} // namespace homebutton
#endif

View File

@ -0,0 +1,11 @@
#ifndef HOMEBUTTON_COMMON_H
#define HOMEBUTTON_COMMON_H
#include <revolution/mem.h>
extern "C" MEMAllocator* spAllocator;
void* HBMAllocMem(u32 length);
void HBMFreeMem(void* ptr);
#endif

View File

@ -0,0 +1,356 @@
#include "HBMController.h"
namespace homebutton {
bool Controller::sBatteryFlag[WPAD_MAX_CONTROLLERS];
OSAlarm Controller::sAlarm[WPAD_MAX_CONTROLLERS];
OSAlarm Controller::sAlarmSoundOff[WPAD_MAX_CONTROLLERS];
Controller* Controller::sThis[WPAD_MAX_CONTROLLERS];
bool Controller::sSetInfoAsync[WPAD_MAX_CONTROLLERS];
RemoteSpk* Controller::sPInstance;
s32 Controller::lbl_8025DBBC;
void Controller::wpadConnectCallback(s32 chan, s32 result) {
switch (result) {
case WPAD_ESUCCESS:
if (!sThis[chan]->mCallbackFlag) {
sThis[chan]->mOldExtensionCallback =
WPADSetExtensionCallback(chan, wpadExtensionCallback);
sThis[chan]->mCallbackFlag = true;
}
WPADControlSpeaker(chan, WPAD_SPEAKER_DISABLE, NULL);
break;
case WPAD_ENODEV:
WPADSetExtensionCallback(chan, sThis[chan]->mOldExtensionCallback);
sThis[chan]->mOldExtensionCallback = NULL;
sThis[chan]->mCallbackFlag = false;
sThis[chan]->mCheckSoundTimeFlag = false;
sThis[chan]->mCheckSoundIntervalFlag = false;
break;
}
if (sThis[chan]->mOldConnectCallback) {
(*sThis[chan]->mOldConnectCallback)(chan, result);
}
}
void Controller::wpadExtensionCallback(s32 chan, s32 result) {
switch (result) {
case WPAD_DEV_INITIALIZING:
sThis[chan]->soundOff(1000);
break;
}
if (sThis[chan]->mOldExtensionCallback) {
(*sThis[chan]->mOldExtensionCallback)(chan, result);
}
}
void Controller::soundOnCallback(OSAlarm* alm, OSContext*) {
int chan = (int)OSGetAlarmUserData(alm);
sThis[chan]->soundOn();
}
Controller::Controller(int chan, RemoteSpk* spk) {
mHBController.chan = chan;
mHBController.rumble = false;
mHBController.spVol = 1.0f;
remotespk = spk;
mOldConnectCallback = NULL;
mOldExtensionCallback = NULL;
mCallbackFlag = false;
mSoundOffFlag = false;
if (chan < WPAD_MAX_CONTROLLERS) {
sBatteryFlag[chan] = false;
OSCreateAlarm(&sAlarm[chan]);
OSCreateAlarm(&sAlarmSoundOff[chan]);
sThis[chan] = this;
}
}
Controller::~Controller() {
OSCancelAlarm(&sAlarm[mHBController.chan]);
OSCancelAlarm(&sAlarmSoundOff[mHBController.chan]);
}
void Controller::initCallback() {
u32 type;
mOldConnectCallback = WPADSetConnectCallback(mHBController.chan, &wpadConnectCallback);
switch (WPADProbe(mHBController.chan, &type)) {
case WPAD_ESUCCESS:
mOldExtensionCallback =
WPADSetExtensionCallback(mHBController.chan, &wpadExtensionCallback);
mCallbackFlag = true;
break;
case WPAD_ENODEV:
mCallbackFlag = false;
break;
}
}
void Controller::clearCallback() {
WPADSetConnectCallback(mHBController.chan, mOldConnectCallback);
mOldConnectCallback = NULL;
WPADSetExtensionCallback(mHBController.chan, mOldExtensionCallback);
mOldExtensionCallback = NULL;
}
void Controller::setKpad(const HBMKPadData* con, bool updatePos) {
if (!con->kpad) {
return;
}
if (updatePos) {
if (con->kpad->dev_type == WPAD_DEV_CLASSIC && con->use_devtype == WPAD_DEV_CLASSIC) {
mHBController.x = con->pos.x;
mHBController.y = con->pos.y;
} else {
mHBController.x = con->kpad->pos.x;
mHBController.y = con->kpad->pos.y;
}
}
mHBController.trig = con->kpad->trig;
mHBController.hold = con->kpad->hold;
mHBController.release = con->kpad->release;
if (con->kpad->dev_type == WPAD_DEV_CLASSIC) {
u32 h = con->kpad->ex_status.cl.hold;
u32 t = con->kpad->ex_status.cl.trig;
u32 r = con->kpad->ex_status.cl.release;
if (h & WPAD_BUTTON_CL_A) {
mHBController.hold |= WPAD_BUTTON_A;
}
if (t & WPAD_BUTTON_CL_A) {
mHBController.trig |= WPAD_BUTTON_A;
}
if (r & WPAD_BUTTON_CL_A) {
mHBController.release |= WPAD_BUTTON_A;
}
if (h & WPAD_BUTTON_CL_PLUS) {
mHBController.hold |= WPAD_BUTTON_PLUS;
}
if (t & WPAD_BUTTON_CL_PLUS) {
mHBController.trig |= WPAD_BUTTON_PLUS;
}
if (r & WPAD_BUTTON_CL_PLUS) {
mHBController.release |= WPAD_BUTTON_PLUS;
}
if (h & WPAD_BUTTON_CL_MINUS) {
mHBController.hold |= WPAD_BUTTON_MINUS;
}
if (t & WPAD_BUTTON_CL_MINUS) {
mHBController.trig |= WPAD_BUTTON_MINUS;
}
if (r & WPAD_BUTTON_CL_MINUS) {
mHBController.release |= WPAD_BUTTON_MINUS;
}
if (h & WPAD_BUTTON_CL_HOME) {
mHBController.hold |= WPAD_BUTTON_HOME;
}
if (t & WPAD_BUTTON_CL_HOME) {
mHBController.trig |= WPAD_BUTTON_HOME;
}
if (r & WPAD_BUTTON_CL_HOME) {
mHBController.release |= WPAD_BUTTON_HOME;
}
}
}
void Controller::clrKpadButton() {
mHBController.trig = 0;
mHBController.hold = 0;
mHBController.release = 0;
}
void Controller::setInValidPos() {
mHBController.x = -10000.0f;
mHBController.y = -10000.0f;
}
int Controller::getChan() const {
return mHBController.chan;
}
void Controller::connect() {
getRemoteSpk()->Connect(getChan());
}
void Controller::disconnect() { /* ... */ }
void Controller::setSpeakerVol(f32 vol) {
mHBController.spVol = vol;
}
f32 Controller::getSpeakerVol() const {
return mHBController.spVol;
}
void Controller::playSound(nw4hbm::snd::SoundArchivePlayer* pSoundArchivePlayer, int id) {
if (!mSoundOffFlag) {
getRemoteSpk()->Play(getChan(), id, getSpeakerVol() * 10.0f);
if (WPADIsSpeakerEnabled(getChan())) {
if (!mCheckSoundTimeFlag) {
mPlaySoundTime = OSGetTime();
}
mCheckSoundTimeFlag = true;
mCheckSoundIntervalFlag = false;
}
}
}
bool Controller::isPlayingSound() const {
return getRemoteSpk()->isPlaying(getChan());
}
bool Controller::isPlayingSoundId(int id) const {
if (!isPlayingSound()) {
return false;
}
if (!getRemoteSpk()->isPlayingId(getChan(), id)) {
return false;
}
return true;
}
void Controller::initSound() {
mCheckSoundTimeFlag = false;
mCheckSoundIntervalFlag = false;
}
void Controller::updateSound() {
int chan = getChan();
if (!isPlayingSound()) {
if (mCheckSoundTimeFlag) {
if (!mCheckSoundIntervalFlag) {
mStopSoundTime = OSGetTime();
mCheckSoundIntervalFlag = true;
} else {
OSTime time = OSGetTime();
if (OSTicksToMilliseconds(time - mStopSoundTime) >= 1000) {
mCheckSoundTimeFlag = false;
mCheckSoundIntervalFlag = false;
}
}
}
return;
} else {
if (mCheckSoundTimeFlag) {
mCheckSoundIntervalFlag = false;
OSTime time = OSGetTime();
if (OSTicksToMilliseconds(time - mPlaySoundTime) >= 480000) {
mCheckSoundTimeFlag = false;
mCheckSoundIntervalFlag = false;
soundOff(1000);
return;
}
}
// Average radio sensitivity is 80 (see __wpadCalcRadioQuality)
if (!mSoundOffFlag && WPADGetRadioSensitivity(chan) <= 85) {
soundOff(1000);
}
}
}
void Controller::soundOff(int msec) {
int chan = getChan();
if (!WPADIsSpeakerEnabled(chan)) {
return;
}
WPADControlSpeaker(chan, WPAD_SPEAKER_MUTE, NULL);
OSSetAlarmUserData(&sAlarmSoundOff[chan], (void*)chan);
OSCancelAlarm(&sAlarmSoundOff[chan]);
OSSetAlarm(&sAlarmSoundOff[chan], OSMillisecondsToTicks(msec), &soundOnCallback);
mSoundOffFlag = true;
}
void Controller::soundOn() {
int chan = getChan();
if (WPADIsSpeakerEnabled(chan)) {
WPADControlSpeaker(chan, WPAD_SPEAKER_UNMUTE, NULL);
}
mSoundOffFlag = false;
}
bool Controller::isPlayReady() const {
return getRemoteSpk()->isPlayReady(getChan());
}
HBController* Controller::getController() {
return &mHBController;
}
void Controller::startMotor() {
if (getChan() < WPAD_MAX_CONTROLLERS && !isPlayingSound()) {
setRumble();
WPADControlMotor(getChan(), WPAD_MOTOR_RUMBLE);
}
}
void Controller::stopMotor() {
if (getChan() < WPAD_MAX_CONTROLLERS && isRumbling()) {
clrRumble();
WPADControlMotor(getChan(), WPAD_MOTOR_STOP);
}
}
s32 Controller::getInfoAsync(WPADInfo* info) {
if (getChan() >= WPAD_MAX_CONTROLLERS) {
return -2;
}
if (isPlayingSound() || isRumbling()) {
return -2;
}
return WPADGetInfoAsync(getChan(), info, &ControllerCallback);
}
void Controller::ControllerCallback(s32 chan, s32 result) {
if (result == WPAD_ESUCCESS && chan < WPAD_MAX_CONTROLLERS) {
sBatteryFlag[chan] = true;
}
}
bool Controller::getBatteryFlag() const {
if (getChan() >= WPAD_MAX_CONTROLLERS) {
return false;
}
return sBatteryFlag[getChan()];
}
void Controller::clrBatteryFlag() {
if (getChan() >= WPAD_MAX_CONTROLLERS) {
return;
}
sBatteryFlag[getChan()] = false;
}
} // namespace homebutton

View File

@ -0,0 +1,102 @@
#ifndef HOMEBUTTON_CONTROLLER_H
#define HOMEBUTTON_CONTROLLER_H
#include <revolution/mtx.h>
#include <revolution/os.h>
#include <revolution/wpad.h>
#include "HBMCommon.h"
#include "HBMRemoteSpk.h"
#include "nw4hbm/snd/SoundArchivePlayer.h"
#include "nw4hbm/snd/SoundHandle.h"
struct HBController {
/* 0x00 */ int chan;
/* 0x04 */ f32 spVol;
/* 0x08 */ f32 x;
/* 0x0C */ f32 y;
/* 0x10 */ u32 trig;
/* 0x14 */ u32 hold;
/* 0x18 */ u32 release;
/* 0x1C */ bool rumble;
}; // size = 0x20
namespace homebutton {
class Controller {
public:
Controller(int chan, RemoteSpk* spk);
~Controller();
HBController* getController();
int getChan() const;
f32 getSpeakerVol() const;
RemoteSpk* getRemoteSpk() const { return remotespk; }
bool isRumbling() { return mHBController.rumble; }
bool getBatteryFlag() const;
void setSpeakerVol(f32 vol);
void setRumble() { mHBController.rumble = true; }
void clrRumble() { mHBController.rumble = false; }
s32 getInfoAsync(WPADInfo* info);
bool isPlayReady() const;
bool isPlayingSound() const;
bool isPlayingSoundId(int id) const;
void setKpad(const HBMKPadData* con, bool updatePos);
void setInValidPos();
void clrBatteryFlag();
void clrKpadButton();
void connect();
void disconnect();
void initSound();
void updateSound();
void playSound(nw4hbm::snd::SoundArchivePlayer* pSoundArchivePlayer, int id);
void soundOn();
void soundOff(int msec);
void startMotor();
void stopMotor();
void initCallback();
void clearCallback();
static RemoteSpk* GetInstance() { return sPInstance; }
static void SetInstance(RemoteSpk* p) { sPInstance = p; }
private:
static void wpadConnectCallback(s32 chan, s32 result);
static void wpadExtensionCallback(s32 chan, s32 result);
static void soundOnCallback(OSAlarm* alm, OSContext* context);
static void ControllerCallback(s32 chan, s32 result);
private:
/* 0x00 */ HBController mHBController;
/* 0x20 */ nw4hbm::snd::SoundHandle mSoundHandle;
/* 0x24 */ RemoteSpk* remotespk;
/* 0x28 */ WPADConnectCallback mOldConnectCallback;
/* 0x2C */ WPADExtensionCallback mOldExtensionCallback;
/* 0x30 */ OSTime mPlaySoundTime;
/* 0x38 */ OSTime mStopSoundTime;
/* 0x40 */ bool mCallbackFlag;
/* 0x41 */ bool mSoundOffFlag;
/* 0x42 */ bool mCheckSoundTimeFlag;
/* 0x43 */ bool mCheckSoundIntervalFlag;
private:
static bool sBatteryFlag[WPAD_MAX_CONTROLLERS];
static OSAlarm sAlarm[WPAD_MAX_CONTROLLERS];
static OSAlarm sAlarmSoundOff[WPAD_MAX_CONTROLLERS];
static Controller* sThis[WPAD_MAX_CONTROLLERS];
static bool sSetInfoAsync[WPAD_MAX_CONTROLLERS];
static RemoteSpk* sPInstance;
static s32 lbl_8025DBBC;
}; // size = 0x44
} // namespace homebutton
#endif

View File

@ -0,0 +1,68 @@
#include "HBMFrameController.h"
namespace homebutton {
void FrameController::init(int anm_type, f32 max_frame, f32 min_frame, f32 delta) {
mAnmType = anm_type;
mMaxFrame = max_frame;
mMinFrame = min_frame;
mDelta = delta;
mState = ANIM_STATE_STOP;
mbAlternateBack = false;
initFrame();
}
void FrameController::initFrame() {
mFrame = mAnmType == ANIM_TYPE_BACKWARD ? mMaxFrame : mMinFrame;
}
void FrameController::calc() {
if (mState != ANIM_STATE_PLAY) {
return;
}
switch (mAnmType) {
case ANIM_TYPE_FORWARD:
if ((mFrame += mDelta) >= getLastFrame()) {
mFrame = getLastFrame();
stop();
}
break;
case ANIM_TYPE_BACKWARD:
if ((mFrame -= mDelta) <= mMinFrame) {
mFrame = mMinFrame;
stop();
}
break;
case ANIM_TYPE_LOOP:
if ((mFrame += mDelta) >= mMaxFrame) {
mFrame -= mMaxFrame - mMinFrame;
}
break;
case ANIM_TYPE_ALTERNATE:
if (!mbAlternateBack) {
if ((mFrame += mDelta) >= getLastFrame()) {
mFrame = getLastFrame();
mbAlternateBack = true;
}
} else {
if ((mFrame -= mDelta) <= mMinFrame) {
mFrame = mMinFrame;
mbAlternateBack = false;
}
}
break;
}
}
} // namespace homebutton

View File

@ -0,0 +1,76 @@
#ifndef HOMEBUTTON_FRAME_CONTROLLER_H
#define HOMEBUTTON_FRAME_CONTROLLER_H
#include <revolution/types.h>
namespace homebutton {
enum {
/* 0 */ ANIM_TYPE_FORWARD = 0,
/* 1 */ ANIM_TYPE_BACKWARD,
/* 2 */ ANIM_TYPE_LOOP,
/* 3 */ ANIM_TYPE_ALTERNATE
};
enum {
/* 0 */ ANIM_STATE_STOP = 0,
/* 1 */ ANIM_STATE_PLAY,
/* 2 */ ANIM_STATE_STOP_REQ,
};
class FrameController {
public:
FrameController() {}
/* 0x08 */ virtual ~FrameController() {}
/* 0x0C */ virtual void calc();
void init(int type, f32 maxFrame, f32 minFrame, f32 delta);
void initFrame();
void setMaxFrame(f32 value) { mMaxFrame = value; }
f32 getMaxFrame() const { return mMaxFrame; }
f32 getLastFrame() const { return mMaxFrame - 1.0f; }
void setMinFrame(f32 value) { mMinFrame = value; }
f32 getMinFrame() const { return mMinFrame; }
void setCurrentFrame(f32 value) { mFrame = value; }
f32 getCurrentFrame() const { return mFrame; }
void setDelta(f32 value) { mDelta = value; }
f32 getDelta() const { return mDelta; }
void setState(int value) { mState = value; }
int getState() const { return mState; }
void setAnimType(int value) { mAnmType = value; }
int getAnimType() const { return mAnmType; }
bool isPlaying() const { return mState == ANIM_STATE_PLAY; }
void start() {
initFrame();
restart();
}
void restart() { mState = ANIM_STATE_PLAY; }
void stop() { mState = ANIM_STATE_STOP; }
protected:
/* 0x00 (vtable) */
/* 0x04 */ f32 mMaxFrame;
/* 0x08 */ f32 mMinFrame;
/* 0x0C */ f32 mFrame;
/* 0x10 */ f32 mDelta;
/* 0x14 */ int mState;
/* 0x18 */ int mAnmType;
private:
/* 0x1C */ bool mbAlternateBack;
};
} // namespace homebutton
#endif

View File

@ -0,0 +1,433 @@
#include "HBMGUIManager.h"
#include "nw4hbm/lyt/bounding.h"
#include "nw4hbm/lyt/layout.h"
#include "nw4hbm/lyt/picture.h"
#include "nw4hbm/lyt/window.h"
#include "new.h"
namespace homebutton {
namespace gui {
u32 PaneManager::suIDCounter;
static void drawLine_(f32 x0, f32 y0, f32 x1, f32 y1, f32 z, u8 uWidth, GXColor& rColor);
static bool is_visible(nw4hbm::lyt::Pane* pPane);
static void drawLine_(f32 x0, f32 y0, f32 x1, f32 y1, f32 z, u8 uWidth, GXColor& rColor) {
static const f32 cubeScale = 1.0f;
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetCullMode(GX_CULL_NONE);
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE,
GX_AF_NONE);
GXSetNumTexGens(0);
GXSetNumTevStages(1);
GXSetTevOp(GX_TEVSTAGE0, GX_BLEND);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_NOOP);
Mtx modelMtx;
PSMTXTrans(modelMtx, 0.0f, 0.0f, 0.0f);
GXLoadPosMtxImm(modelMtx, 0);
GXSetLineWidth(uWidth, GX_TO_ZERO);
GXBegin(GX_LINES, GX_VTXFMT0, 2);
GXPosition3f32(x0, y0, z);
GXColor1u32(*reinterpret_cast<u32*>(&rColor));
GXPosition3f32(x1, y1, z);
GXColor1u32(*reinterpret_cast<u32*>(&rColor));
GXEnd();
}
bool Component::update(int i, f32 x, f32 y, u32, u32, u32, void* pData) {
bool bTouched = false;
if (!isVisible()) {
/* nothing */
} else {
if (contain(x, y)) {
if (isPointed(i)) {
onMove(x, y);
mpManager->onEvent(getID(), 3, pData);
} else {
setPointed(i, true);
onPoint();
mpManager->onEvent(getID(), 1, pData);
}
bTouched = true;
} else {
if (isPointed(i)) {
setPointed(i, false);
offPoint();
mpManager->onEvent(getID(), 2, pData);
}
}
}
return bTouched;
}
Manager::~Manager() {
void* p = nw4hbm::ut::List_GetFirst(&mIDToComponent);
for (; p; p = nw4hbm::ut::List_GetFirst(&mIDToComponent)) {
nw4hbm::ut::List_Remove(&mIDToComponent, p);
if (mpAllocator) {
MEMFreeToAllocator(mpAllocator, p);
} else {
delete static_cast<IDToComponent*>(p);
}
}
}
void Manager::init() {
for (u32 i = 0; i < nw4hbm::ut::List_GetSize(&mIDToComponent); i++) {
const IDToComponent* p =
static_cast<const IDToComponent*>(nw4hbm::ut::List_GetNth(&mIDToComponent, i));
p->mpComponent->init();
}
}
void Manager::addComponent(Component* pComponent) {
u32 uID = pComponent->getID();
pComponent->setManager(this);
if (mpAllocator) {
void* p = MEMAllocFromAllocator(mpAllocator, sizeof(IDToComponent));
nw4hbm::ut::List_Append(&mIDToComponent, new (p) IDToComponent(uID, pComponent));
} else {
nw4hbm::ut::List_Append(&mIDToComponent, new IDToComponent(uID, pComponent));
}
}
void Manager::delComponent(Component* pComponent) {
IDToComponent* p =
static_cast<IDToComponent*>(nw4hbm::ut::List_GetNext(&mIDToComponent, NULL));
while (p) {
if (p->mpComponent == pComponent) {
break;
}
p = static_cast<IDToComponent*>(nw4hbm::ut::List_GetNext(&mIDToComponent, p));
}
nw4hbm::ut::List_Remove(&mIDToComponent, p);
if (mpAllocator) {
MEMFreeToAllocator(mpAllocator, p);
} else {
delete p;
}
}
Component* Manager::getComponent(u32 uID) {
const IDToComponent* p =
static_cast<const IDToComponent*>(nw4hbm::ut::List_GetNth(&mIDToComponent, uID));
return p->mpComponent;
}
bool Manager::update(int i, f32 x, f32 y, u32 uTrigFlag, u32 uHoldFlag, u32 uReleaseFlag,
void* pData) {
bool bTouched = false;
Component* pLastContainedComponent = NULL;
for (u32 n = 0; n < nw4hbm::ut::List_GetSize(&mIDToComponent); n++) {
const IDToComponent* p =
static_cast<const IDToComponent*>(nw4hbm::ut::List_GetNth(&mIDToComponent, n));
if (p->mpComponent->update(i, x, y, uTrigFlag, uHoldFlag, uReleaseFlag, pData)) {
if (p->mpComponent->isTriggerTarger()) {
pLastContainedComponent = p->mpComponent;
}
bTouched = true;
}
}
if (pLastContainedComponent) {
if (uTrigFlag) {
Vec pos;
pLastContainedComponent->onTrig(uTrigFlag, pos);
onEvent(pLastContainedComponent->getID(), 0, pData);
}
if (uReleaseFlag) {
Vec pos;
pLastContainedComponent->onTrig(uReleaseFlag, pos);
onEvent(pLastContainedComponent->getID(), 5, pData);
}
}
return bTouched;
}
void Manager::calc() {
for (u32 i = 0; i < nw4hbm::ut::List_GetSize(&mIDToComponent); i++) {
const IDToComponent* p =
static_cast<const IDToComponent*>(nw4hbm::ut::List_GetNth(&mIDToComponent, i));
p->mpComponent->calc();
}
}
void Manager::draw() {
for (u32 i = 0; i < nw4hbm::ut::List_GetSize(&mIDToComponent); i++) {
const IDToComponent* p =
static_cast<const IDToComponent*>(nw4hbm::ut::List_GetNth(&mIDToComponent, i));
p->mpComponent->draw();
}
}
void Manager::setAllComponentTriggerTarget(bool b) {
for (u32 i = 0; i < nw4hbm::ut::List_GetSize(&mIDToComponent); i++) {
const IDToComponent* p =
static_cast<const IDToComponent*>(nw4hbm::ut::List_GetNth(&mIDToComponent, i));
p->mpComponent->setTriggerTarget(b);
}
}
PaneManager::~PaneManager() {
PaneToComponent* pPaneToComponent =
static_cast<PaneToComponent*>(nw4hbm::ut::List_GetFirst(&mPaneToComponent));
for (; pPaneToComponent; pPaneToComponent = static_cast<PaneToComponent*>(
nw4hbm::ut::List_GetFirst(&mPaneToComponent)))
{
nw4hbm::ut::List_Remove(&mPaneToComponent, pPaneToComponent);
if (mpAllocator) {
MEMFreeToAllocator(mpAllocator, pPaneToComponent->mpComponent);
MEMFreeToAllocator(mpAllocator, pPaneToComponent);
} else {
delete pPaneToComponent->mpComponent;
delete pPaneToComponent;
}
}
}
void PaneManager::createLayoutScene(const nw4hbm::lyt::Layout& rLayout) {
suIDCounter = 0;
nw4hbm::lyt::Pane* pRootPane = rLayout.GetRootPane();
walkInChildren(pRootPane->GetChildList());
}
void PaneManager::addLayoutScene(const nw4hbm::lyt::Layout& rLayout) {
nw4hbm::lyt::Pane* pRootPane = rLayout.GetRootPane();
walkInChildren(pRootPane->GetChildList());
}
void PaneManager::walkInChildren(nw4hbm::lyt::PaneList& rPaneList) {
for (nw4hbm::lyt::PaneList::Iterator it = rPaneList.GetBeginIter();
it != rPaneList.GetEndIter(); it++)
{
PaneComponent* pPaneComponent = NULL;
PaneToComponent* pPaneToComponent = NULL;
if (mpAllocator) {
void* p1 = MEMAllocFromAllocator(mpAllocator, sizeof(*pPaneComponent));
void* p2 = MEMAllocFromAllocator(mpAllocator, sizeof(*pPaneToComponent));
pPaneComponent = new (p1) PaneComponent(suIDCounter);
pPaneToComponent = new (p2) PaneToComponent(&(*it), pPaneComponent);
} else {
pPaneComponent = new PaneComponent(suIDCounter);
pPaneToComponent = new PaneToComponent(&(*it), pPaneComponent);
}
nw4hbm::ut::List_Append(&mPaneToComponent, pPaneToComponent);
suIDCounter++;
pPaneComponent->setPane(&(*it));
if (nw4hbm::ut::DynamicCast<nw4hbm::lyt::Picture*>(&(*it))) {
pPaneComponent->setTriggerTarget(true);
}
if (nw4hbm::ut::DynamicCast<nw4hbm::lyt::Window*>(&(*it))) {
pPaneComponent->setTriggerTarget(true);
}
addComponent(pPaneComponent);
walkInChildren(it->GetChildList());
}
}
void PaneManager::delLayoutScene(const nw4hbm::lyt::Layout& rLayout) {
nw4hbm::lyt::Pane* pRootPane = rLayout.GetRootPane();
walkInChildrenDel(pRootPane->GetChildList());
}
void PaneManager::walkInChildrenDel(nw4hbm::lyt::PaneList& rPaneList) {
for (nw4hbm::lyt::PaneList::Iterator it = rPaneList.GetBeginIter();
it != rPaneList.GetEndIter(); it++)
{
PaneToComponent* pPaneToComponent = static_cast<PaneToComponent*>(
nw4hbm::ut::List_GetNext(&mPaneToComponent, NULL));
while (pPaneToComponent) {
if (pPaneToComponent->mpPane == &(*it)) {
break;
}
pPaneToComponent = static_cast<PaneToComponent*>(
nw4hbm::ut::List_GetNext(&mPaneToComponent, pPaneToComponent));
}
delComponent(pPaneToComponent->mpComponent);
nw4hbm::ut::List_Remove(&mPaneToComponent, pPaneToComponent);
suIDCounter--;
if (mpAllocator) {
MEMFreeToAllocator(mpAllocator, pPaneToComponent->mpComponent);
MEMFreeToAllocator(mpAllocator, pPaneToComponent);
} else {
delete pPaneToComponent->mpComponent;
delete pPaneToComponent;
}
walkInChildrenDel(it->GetChildList());
}
}
PaneComponent* PaneManager::getPaneComponentByPane(nw4hbm::lyt::Pane* pPane) {
for (u32 i = 0; i < nw4hbm::ut::List_GetSize(&mIDToComponent); i++) {
PaneToComponent* p =
static_cast<PaneToComponent*>(nw4hbm::ut::List_GetNth(&mPaneToComponent, i));
if (p->mpPane == pPane) {
return p->mpComponent;
}
}
return NULL;
}
#pragma push
#pragma opt_propagation off // ???
void PaneManager::setAllBoundingBoxComponentTriggerTarget(bool b) {
for (u32 i = 0; i < nw4hbm::ut::List_GetSize(&mIDToComponent); i++) {
PaneToComponent* p =
static_cast<PaneToComponent*>(nw4hbm::ut::List_GetNth(&mPaneToComponent, i));
if (nw4hbm::ut::DynamicCast<nw4hbm::lyt::Bounding*>(p->mpPane)) {
p->mpComponent->setTriggerTarget(b);
}
}
}
#pragma pop
bool PaneComponent::contain(f32 x_, f32 y_) {
if (!mpManager) {
return false;
}
// goes into PaneManager vtable?
const nw4hbm::lyt::DrawInfo* pDrawInfo =
static_cast<PaneManager*>(mpManager)->getDrawInfo();
if (!pDrawInfo) {
return false;
}
nw4hbm::math::MTX34 invGlbMtx;
PSMTXInverse(mpPane->GetGlobalMtx(), invGlbMtx);
nw4hbm::math::VEC3 lclPos;
PSMTXMultVec(invGlbMtx, nw4hbm::math::VEC3(x_, y_, 0.0f), lclPos);
nw4hbm::ut::Rect rect = mpPane->GetPaneRect(*pDrawInfo);
if (rect.left <= lclPos.x && lclPos.x <= rect.right && rect.bottom <= lclPos.y &&
lclPos.y <= rect.top)
{
return true;
} else {
return false;
}
}
void PaneComponent::draw() {
const nw4hbm::lyt::DrawInfo* pDrawInfo =
static_cast<PaneManager*>(mpManager)->getDrawInfo();
if (!pDrawInfo) {
return;
}
// some stripped debug thing?
const nw4hbm::math::VEC3& translate = mpPane->GetTranslate();
nw4hbm::lyt::Size size = mpPane->GetSize();
const nw4hbm::math::MTX34& gmtx = mpPane->GetGlobalMtx();
f32 x = gmtx.mtx[0][3];
f32 y = gmtx.mtx[1][3];
GXColor color = {0xff, 0x00, 0x00, 0xff}; // red
if (mabPointed[0]) {
color.r = 0x00;
color.b = 0xff; // now blue
}
// start at top left, go clockwise
drawLine_(x - size.width / 2.0f, y - size.height / 2.0f, x + size.width / 2.0f,
y - size.height / 2.0f, 0.0f, 8, color);
drawLine_(x + size.width / 2.0f, y - size.height / 2.0f, x + size.width / 2.0f,
y + size.height / 2.0f, 0.0f, 8, color);
drawLine_(x + size.width / 2.0f, y + size.height / 2.0f, x - size.width / 2.0f,
y + size.height / 2.0f, 0.0f, 8, color);
drawLine_(x - size.width / 2.0f, y + size.height / 2.0f, x - size.width / 2.0f,
y - size.height / 2.0f, 0.0f, 8, color);
}
#pragma global_optimizer off // ...ok!
static bool is_visible(nw4hbm::lyt::Pane* pPane) {
if (!pPane->IsVisible()) {
return false;
}
if (!pPane->GetParent()) {
return true;
}
return is_visible(pPane->GetParent());
}
bool PaneComponent::isVisible() {
return is_visible(mpPane);
}
#pragma global_optimizer reset
} // namespace gui
} // namespace homebutton

View File

@ -0,0 +1,234 @@
#ifndef HOMEBUTTON_GUI_MANAGER_H
#define HOMEBUTTON_GUI_MANAGER_H
#include <revolution/kpad.h>
#include <revolution/mem.h>
#include <revolution/mtx.h>
#include "nw4hbm/lyt/pane.h"
#include "nw4hbm/ut/list.h"
namespace nw4hbm {
namespace lyt {
class DrawInfo;
class Layout;
} // namespace lyt
} // namespace nw4hbm
namespace homebutton {
namespace gui {
class Manager;
class PaneComponent;
class Interface {
public:
Interface() {}
/* 0x08 */ virtual void create() {}
/* 0x0C */ virtual void init() {}
/* 0x10 */ virtual void calc() {}
/* 0x14 */ virtual void draw(Mtx&) {}
/* 0x18 */ virtual void draw() {}
/* 0x1C */ virtual ~Interface() {}
private:
/* 0x00 (vtable) */
}; // size = 0x04
class EventHandler {
public:
EventHandler() {}
/* 0x08 */ virtual void onEvent(u32, u32, void*) {}
/* 0x0C */ virtual void setManager(Manager* pManager) { mpManager = pManager; }
protected:
/* 0x00 (vtable) */
/* 0x04 */ Manager* mpManager;
}; // size = 0x08
class Component : public Interface {
public:
Component(u32 uID)
: mDragStartPos(), mbDragging(), muDraggingButton(), muID(uID), mbTriggerTarger(),
mpManager() {
init();
}
/* 0x0C */ virtual void init() {
mbDragging = false;
for (int i = 0; i < (int)ARRAY_SIZE(mabPointed); i++) {
mabPointed[i] = false;
}
}
/* 0x1C */ virtual ~Component() {}
/* 0x20 */ virtual u32 getID() { return muID; }
/* 0x24 */ virtual int isPointed(int n) { return mabPointed[n]; }
/* 0x28 */ virtual void setPointed(int n, bool b) { mabPointed[n] = b; }
/* 0x2C */ virtual void onPoint() {}
/* 0x30 */ virtual void offPoint() {}
/* 0x34 */ virtual void onDrag(f32, f32) {}
/* 0x38 */ virtual void onMove(f32, f32) {}
/* 0x3C */ virtual void onTrig(u32 uFlag, Vec& vec) {
if (uFlag & muDraggingButton) {
mDragStartPos = vec;
mbDragging = true;
}
}
/* 0x40 */ virtual void setDraggingButton(u32 uDraggingButton) {
muDraggingButton = uDraggingButton;
}
/* 0x44 */ virtual bool update(int, const KPADStatus*, f32, f32, void*) {
return false;
}
/* 0x48 */ virtual bool update(int i, f32 x, f32 y, u32 uTrigFlag, u32 uHoldFlag,
u32 uReleaseFlag, void* pData);
/* 0x4C */ virtual bool isTriggerTarger() { return mbTriggerTarger; }
/* 0x50 */ virtual void setTriggerTarget(bool bTriggerTarget) {
mbTriggerTarger = bTriggerTarget;
}
/* 0x54 */ virtual void setManager(Manager* pManager) { mpManager = pManager; }
/* 0x58 */ virtual bool isVisible() { return true; }
/* 0x5C */ virtual bool contain(f32 x_, f32 y_) = 0;
protected:
/* 0x00 (base) */
/* 0x04 */ bool mabPointed[8];
/* 0x0C */ Vec mDragStartPos;
/* 0x18 */ bool mbDragging;
/* 0x1C */ u32 muDraggingButton;
/* 0x20 */ u32 muID;
/* 0x24 */ bool mbTriggerTarger;
/* 0x28 */ Manager* mpManager;
}; // size = 0x2C
class Manager : public Interface {
// nested types
private:
struct IDToComponent {
public:
/* 0x00 */ u32 muID;
/* 0x04 */ Component* mpComponent;
/* 0x08 */ nw4hbm::ut::Link mLink;
IDToComponent(u32 uID, Component* pComponent)
: muID(uID), mpComponent(pComponent) {}
}; // size = 0x10
public:
Manager(EventHandler* pEventHandler, MEMAllocator* pAllocator)
: mpEventHandler(pEventHandler), mpAllocator(pAllocator) {
if (mpEventHandler) {
mpEventHandler->setManager(this);
}
nw4hbm::ut::List_Init(&mIDToComponent, 8);
}
/* 0x0C */ virtual void init();
/* 0x10 */ virtual void calc();
/* 0x18 */ virtual void draw();
/* 0x1C */ virtual ~Manager();
/* 0x20 */ virtual void addComponent(Component* pComponent);
/* 0x24 */ virtual Component* getComponent(u32 uID);
/* 0x28 */ virtual bool update(int, const KPADStatus*, f32, f32, void*) {
return false;
}
/* 0x2C */ virtual bool update(int i, f32 x, f32 y, u32 uTrigFlag, u32 uHoldFlag,
u32 uReleaseFlag, void* pData);
/* 0x30 */ virtual void onEvent(u32 uID, u32 uEvent, void* pData) {
if (mpEventHandler) {
mpEventHandler->onEvent(uID, uEvent, pData);
}
}
/* 0x34 */ virtual void setAllComponentTriggerTarget(bool b);
/* 0x38 */ virtual void setEventHandler(EventHandler* pEventHandler) {
mpEventHandler = pEventHandler;
if (mpEventHandler) {
mpEventHandler->setManager(this);
}
}
void delComponent(Component* pComponent);
protected:
/* 0x00 (base) */
/* 0x04 */ EventHandler* mpEventHandler;
/* 0x08 */ nw4hbm::ut::List mIDToComponent;
/* 0x14 */ MEMAllocator* mpAllocator;
}; // size = 0x18
class PaneManager : public Manager {
// nested types
private:
struct PaneToComponent {
public:
PaneToComponent(nw4hbm::lyt::Pane* pPane, PaneComponent* pComponent)
: mpPane(pPane), mpComponent(pComponent) {}
public:
/* 0x00 */ nw4hbm::lyt::Pane* mpPane;
/* 0x04 */ PaneComponent* mpComponent;
/* 0x08 */ nw4hbm::ut::Link mLink;
}; // size = 0x10
public:
PaneManager(EventHandler* pEventHandler, const nw4hbm::lyt::DrawInfo* pDrawInfo,
MEMAllocator* pAllocator)
: Manager(pEventHandler, pAllocator), mpDrawInfo(pDrawInfo) {
nw4hbm::ut::List_Init(&mPaneToComponent, 8);
}
/* 0x1C */ virtual ~PaneManager();
/* 0x30 */ virtual void createLayoutScene(const nw4hbm::lyt::Layout& rLayout);
/* 0x34 */ virtual PaneComponent* getPaneComponentByPane(nw4hbm::lyt::Pane* pPane);
/* 0x38 */ virtual const nw4hbm::lyt::DrawInfo* getDrawInfo() { return mpDrawInfo; }
/* 0x3C */ virtual void setDrawInfo(const nw4hbm::lyt::DrawInfo* pDrawInfo) {
mpDrawInfo = pDrawInfo;
}
/* 0x40 */ virtual void setAllBoundingBoxComponentTriggerTarget(bool b);
/* 0x44 */ virtual void walkInChildren(nw4hbm::lyt::PaneList& rPaneList);
void walkInChildrenDel(nw4hbm::lyt::PaneList& rPaneList);
void delLayoutScene(const nw4hbm::lyt::Layout& rLayout);
void addLayoutScene(const nw4hbm::lyt::Layout& rLayout);
private:
/* 0x00 (base) */
/* 0x18 */ nw4hbm::ut::List mPaneToComponent;
/* 0x24 */ const nw4hbm::lyt::DrawInfo* mpDrawInfo;
/* 0x28 */ u16 muNumPoint;
u16 muPadding;
// static members
static u32 suIDCounter;
}; // size = 0x2C
class PaneComponent : public Component {
public:
PaneComponent(u32 uID) : Component(uID), mpPane() {}
/* 0x18 */ virtual void draw();
/* 0x1C */ virtual ~PaneComponent() {}
/* 0x20 */ virtual bool isVisible();
/* 0x24 */ virtual bool contain(f32 x_, f32 y_);
/* 0x28 */ virtual void setPane(nw4hbm::lyt::Pane* pPane) { mpPane = pPane; }
/* 0x2C */ virtual nw4hbm::lyt::Pane* getPane() { return mpPane; }
protected:
/* 0x00 (base) */
/* 0x2C */ nw4hbm::lyt::Pane* mpPane;
}; // size = 0x30
} // namespace gui
} // namespace homebutton
#endif

View File

@ -0,0 +1,259 @@
#include "HBMRemoteSpk.h"
#include "HBMController.h"
#include "string.h"
namespace homebutton {
static bool MakeVolumeData(const s16* src, s16* dst, int vol, u32 size);
void RemoteSpk::SetInstance(RemoteSpk* pThis) {
Controller::SetInstance(pThis);
}
RemoteSpk* RemoteSpk::GetInstance(void) {
return Controller::GetInstance();
}
void RemoteSpk::GetPCMFromSeID(int in_ID, s16*& out_wave, int& out_length) {
ARCFileInfo af;
ARCFastOpen(&handle, in_ID, &af);
out_wave = static_cast<s16*>(ARCGetStartAddrInMem(&af));
out_length = ARCGetLength(&af);
ARCClose(&af);
}
static bool MakeVolumeData(const s16* src, s16* dst, int vol, u32 size) {
u32 enc_size = size <= 40 ? size : 40;
for (int i = 0; (u32)i < enc_size; i++) {
*dst++ = static_cast<s16>(*src++ * vol / 10);
}
if (size > 40) {
return false;
}
u32 zero_size = 40 - size;
for (int i = 0; (u32)i < zero_size; i++) {
*dst++ = 0;
}
return true;
}
void RemoteSpk::UpdateSpeaker(OSAlarm*, OSContext*) {
s16 pcmBuffer[40];
u8 adpcmBuffer[20];
if (!GetInstance()) {
return;
}
ChanInfo* pinfo = GetInstance()->info;
for (int i = 0; i < WPAD_MAX_CONTROLLERS; i++, pinfo++) {
if (pinfo->in_pcm && WPADIsSpeakerEnabled(i)) {
int intrStatus = OSDisableInterrupts(); /* int intr */
if (WPADCanSendStreamData(i)) {
MakeVolumeData(pinfo->in_pcm, pcmBuffer, pinfo->vol,
static_cast<u32>(pinfo->length) / sizeof(s16));
WENCGetEncodeData(&pinfo->wencinfo, pinfo->first ? 0 : 1, pcmBuffer, 40,
adpcmBuffer);
WPADSendStreamData(i, adpcmBuffer, 20);
pinfo->first = false;
pinfo->cannotSendCnt = 0;
pinfo->in_pcm += 40;
pinfo->length -= 40 * sizeof(s16);
if (pinfo->length <= 0) {
pinfo->seId = -1;
pinfo->in_pcm = NULL;
}
} else {
pinfo->cannotSendCnt++;
#if HBM_REVISION == 1
if (pinfo->cannotSendCnt > 300) {
pinfo->in_pcm = NULL;
}
#else
if (pinfo->cannotSendCnt > 60) {
pinfo->in_pcm = NULL;
}
#endif
}
OSRestoreInterrupts(intrStatus);
}
}
}
void RemoteSpk::ClearPcm(void) {
ChanInfo* info = GetInstance()->info;
info->seId = -1;
info->in_pcm = NULL;
}
RemoteSpk::RemoteSpk(void* spkSeBuf) {
SetInstance(this);
if (spkSeBuf) {
available = ARCInitHandle(spkSeBuf, &handle) ? TRUE : FALSE;
} else {
available = false;
}
OSCreateAlarm(&speakerAlarm);
for (int i = 0; i < WPAD_MAX_CONTROLLERS; i++) {
OSCreateAlarm(&info[i].alarm);
info[i].in_pcm = NULL;
info[i].seId = -1;
info[i].first = true;
info[i].playReady = true;
}
}
RemoteSpk::~RemoteSpk(void) {
#if HBM_REVISION > 1
SetInstance(NULL);
#endif
available = false;
OSCancelAlarm(&speakerAlarm);
for (int i = 0; i < WPAD_MAX_CONTROLLERS; i++) {
#if HBM_REVISION == 1
WPADControlSpeaker(i, WPAD_SPEAKER_OFF, NULL);
#endif
OSCancelAlarm(&info[i].alarm);
}
#if HBM_REVISION == 1
SetInstance(NULL);
#endif
}
void RemoteSpk::Start(void) {
if (!available) {
return;
}
OSCreateAlarm(&speakerAlarm);
OSSetPeriodicAlarm(&speakerAlarm, OSGetTime(), OSNanosecondsToTicks(6666667),
&UpdateSpeaker);
}
void RemoteSpk::Stop(void) {
OSCancelAlarm(&speakerAlarm);
}
void RemoteSpk::DelaySpeakerOnCallback(OSAlarm* alarm, OSContext*) {
s32 chan = (s32)OSGetAlarmUserData(alarm);
s32 result = WPADControlSpeaker(chan, WPAD_SPEAKER_ENABLE, SpeakerOnCallback);
}
void RemoteSpk::SpeakerOnCallback(s32 chan, s32 result) {
RemoteSpk* pRmtSpk = GetInstance();
if (!pRmtSpk) {
return;
}
switch (result) {
case WPAD_ESUCCESS:
pRmtSpk->info[chan].first = true;
result = WPADControlSpeaker(chan, WPAD_SPEAKER_PLAY, &SpeakerPlayCallback);
break;
case WPAD_EBUSY:
OSSetAlarmUserData(&pRmtSpk->info[chan].alarm, (void*)chan);
OSCancelAlarm(&pRmtSpk->info[chan].alarm);
OSSetAlarm(&pRmtSpk->info[chan].alarm, OSMillisecondsToTicks(50),
&DelaySpeakerOnCallback);
break;
}
}
void RemoteSpk::DelaySpeakerPlayCallback(OSAlarm* alarm, OSContext*) {
s32 chan = (s32)OSGetAlarmUserData(alarm);
s32 result = WPADControlSpeaker(chan, WPAD_SPEAKER_PLAY, &SpeakerPlayCallback);
}
void RemoteSpk::SpeakerPlayCallback(s32 chan, s32 result) {
RemoteSpk* pRmtSpk = GetInstance();
if (!pRmtSpk) {
return;
}
switch (result) {
case WPAD_ESUCCESS:
pRmtSpk->info[chan].playReady = true;
break;
case WPAD_ENODEV:
pRmtSpk->info[chan].playReady = false;
break;
case WPAD_EBUSY:
OSSetAlarmUserData(&pRmtSpk->info[chan].alarm, (void*)chan);
OSCancelAlarm(&pRmtSpk->info[chan].alarm);
OSSetAlarm(&pRmtSpk->info[chan].alarm, OSMillisecondsToTicks(50),
&DelaySpeakerPlayCallback);
break;
}
}
void RemoteSpk::Connect(s32 chan) {
if (!available) {
return;
}
// int?
int result = WPADControlSpeaker(chan, WPAD_SPEAKER_ENABLE, &SpeakerOnCallback);
u32* p = reinterpret_cast<u32*>(&info[chan].wencinfo);
memset(p, 0, sizeof(WENCInfo));
info[chan].first = true;
info[chan].playReady = false;
}
void RemoteSpk::Play(s32 chan, int seID, s8 vol) {
if (!available) {
return;
}
s16* pcm;
int length;
GetPCMFromSeID(seID, pcm, length);
info[chan].cannotSendCnt = 0;
info[chan].seId = seID;
info[chan].length = length;
info[chan].vol = vol;
info[chan].in_pcm = pcm;
}
bool RemoteSpk::isPlaying(s32 chan) const {
return info[chan].in_pcm != NULL;
}
bool RemoteSpk::isPlayingId(s32 chan, int seId) const {
if (isPlaying(chan) && info[chan].seId == seId) {
return true;
} else {
return false;
}
}
bool RemoteSpk::isPlayReady(s32 chan) const {
return info[chan].playReady != false;
}
} // namespace homebutton

View File

@ -0,0 +1,65 @@
#ifndef HOMEBUTTON_REMOTE_SPK_H
#define HOMEBUTTON_REMOTE_SPK_H
#include <revolution/arc.h>
#include <revolution/os.h>
#include <revolution/wenc.h>
#include <revolution/wpad.h>
namespace homebutton {
class RemoteSpk {
private:
struct ChanInfo {
/* 0x00 */ OSAlarm alarm;
/* 0x30 */ WENCInfo wencinfo;
/* 0x50 */ const s16* in_pcm;
/* 0x54 */ int length;
/* 0x58 */ int seId;
/* 0x5C */ bool first;
/* 0x5D */ s8 vol;
/* 0x5E */ s8 cannotSendCnt;
/* 0x60 */ u16 pad_60;
/* 0x62 */ bool playReady;
}; // size = 0x68
public:
RemoteSpk(void* spkSeBuf);
bool isPlayReady(s32 chan) const;
bool isPlaying(s32 chan) const;
bool isPlayingId(s32 chan, int seId) const;
void GetPCMFromSeID(int in_ID, s16*& out_wave, int& out_length);
void ClearPcm();
void Start();
void Stop();
void Connect(s32 chan);
void Play(s32 chan, int seID, s8 vol);
static void SetInstance(RemoteSpk* pThis);
static RemoteSpk* GetInstance();
private:
static void UpdateSpeaker(OSAlarm* alarm, OSContext* context);
static void SpeakerOnCallback(s32 chan, s32 result);
static void DelaySpeakerOnCallback(OSAlarm* alarm, OSContext* context);
static void SpeakerPlayCallback(s32 chan, s32 result);
static void DelaySpeakerPlayCallback(OSAlarm* alarm, OSContext* context);
private:
/* 0x000 */ ChanInfo info[WPAD_MAX_CONTROLLERS];
/* 0x1A0 */ OSAlarm speakerAlarm;
/* 0x1D0 */ ARCHandle handle;
/* 0x1EC */ bool available;
/* 0x1F0 (vtable) */
public:
/* 0x08 */ virtual ~RemoteSpk();
}; // size = 0x1F8
} // namespace homebutton
#endif

View File

@ -0,0 +1,12 @@
#ifndef NW4R_DB_DBG_PRINT_BASE_H
#define NW4R_DB_DBG_PRINT_BASE_H
#include <revolution/types.h>
namespace nw4hbm {
namespace db {
}
} // namespace nw4r
#endif

View File

@ -0,0 +1,111 @@
#ifndef NW4R_DB_ASSERT_H
#define NW4R_DB_ASSERT_H
#include <revolution/types.h>
#include <stdio.h>
namespace nw4hbm {
namespace db {
// Forward declarations
namespace detail {
class ConsoleHead;
}
/* DECL_WEAK */ void VPanic(const char* file, int line, const char* fmt, std::va_list vlist);
/* DECL_WEAK */ void VWarning(const char* file, int line, const char* fmt, std::va_list vlist);
namespace detail {
void Log(const char* fmt, ...);
/* DECL_WEAK */ void Panic(const char* file, int line, const char* fmt, ...);
/* DECL_WEAK */ void Warning(const char* file, int line, const char* msg, ...);
}
detail::ConsoleHead* Assertion_SetConsole(detail::ConsoleHead* console);
detail::ConsoleHead* Assertion_GetConsole();
void Assertion_ShowConsole(u32 time);
void Assertion_HideConsole();
void Assertion_SetWarningTime(u32 time);
bool Assertion_SetAutoWarning(bool enable);
} // namespace db
} // namespace nw4r
#if NW4HBM_DEBUG
#define NW4R_DB_WARNING(line, exp, ...) \
(void)((exp) || (nw4hbm::db::detail::Warning(__FILE__, line, __VA_ARGS__), 0))
#define NW4R_DB_ASSERTMSG(line, exp, ...) \
(void)((exp) || (nw4hbm::db::detail::Panic(__FILE__, line, __VA_ARGS__), 0))
#else
#define NW4R_DB_WARNING(line, exp, ...) (void)0
#define NW4R_DB_ASSERTMSG(line, exp, ...) (void)0
#endif
#define NW4R_ASSERT(line, exp) \
NW4R_DB_ASSERTMSG(line, (exp), "Failed assertion " #exp)
#define NW4R_ASSERT_CHECK_NULL(line, ptr) \
NW4R_DB_ASSERTMSG(line, (ptr != NULL), "Pointer must not be NULL ("#ptr")")
#define POINTER_VALID_TEST(ptr_) \
(((unsigned long)ptr_ & 0xFF000000) == 0x80000000 || ((unsigned long)ptr_ & 0xFF800000) == 0x81000000 || \
((unsigned long)ptr_ & 0xF8000000) == 0x90000000 || ((unsigned long)ptr_ & 0xFF000000) == 0xC0000000 || \
((unsigned long)ptr_ & 0xFF800000) == 0xC1000000 || ((unsigned long)ptr_ & 0xF8000000) == 0xD0000000 || \
((unsigned long)ptr_ & 0xFFFFC000) == 0xE0000000)
#define NW4R_ASSERT_VALID_PTR(line, ptr) \
NW4R_DB_ASSERTMSG(line, POINTER_VALID_TEST(ptr), "Pointer Error\n" #ptr "(=%p) is not valid pointer.", ptr)
#define NW4R_ASSERT_MIN(line_, var_, minValue_) \
NW4R_DB_ASSERTMSG(line_, minValue_ <= var_, \
#var_ " is out of bounds(%d)\n%d <= " #var_ " not satisfied.", (int)(var_), \
(int)(minValue_))
#define NW4R_ASSERT_MINMAX(line_, var_, minValue_, maxValue_) \
NW4R_DB_ASSERTMSG(line_, (var_) >= (minValue_) && (var_) < (maxValue_), \
#var_ " is out of bounds(%d)\n%d <= " #var_ " < %d not satisfied.", (int)(var_), \
(int)(minValue_), (int)(maxValue_))
#define NW4R_ASSERT_MINMAXLT(line_, var_, minValue_, maxValue_) \
NW4R_DB_ASSERTMSG(line_, (var_) >= (minValue_) && (var_) <= (maxValue_), \
#var_ " is out of bounds(%d)\n%d <= " #var_ " <= %d not satisfied.", (int)(var_), \
(int)(minValue_), (int)(maxValue_))
#define NW4R_IS_ALIGNED_(x, align) \
(((unsigned long)(x) & ((align) - 1)) == 0)
#define NW4R_ASSERT_ALIGN2(line, exp) \
NW4R_DB_ASSERTMSG(line, NW4R_IS_ALIGNED_(exp, 2), \
"Alignment Error(0x%x)\n" #exp " must be aligned to 2 bytes boundary.", \
exp)
#define NW4R_ASSERT_ALIGN32(line, exp) \
NW4R_DB_ASSERTMSG(line, NW4R_IS_ALIGNED_(exp, 32), \
"Alignment Error(0x%x)\n" #exp " must be aligned to 32 bytes boundary.", \
exp)
// NW4HBM variants
#define NW4HBM_ASSERT_CHECK_NULL(line, ptr) \
NW4R_DB_ASSERTMSG(line, (ptr != NULL), "NW4HBM:Pointer must not be NULL ("#ptr")")
#define NW4HBM_ASSERT(line, exp) \
NW4R_DB_ASSERTMSG(line, (exp), "NW4HBM:Failed assertion " #exp)
#define NW4HBM_ASSERT_VALID_PTR(line, ptr) \
NW4R_DB_ASSERTMSG(line, POINTER_VALID_TEST(ptr), "NW4HBM:Pointer Error\n" #ptr "(=%p) is not valid pointer.", ptr)
#define NW4HBM_ASSERT_ALIGN2(line, exp) \
NW4R_DB_ASSERTMSG(line, NW4R_IS_ALIGNED_(exp, 2), \
"NW4HBM:Alignment Error(0x%x)\n" #exp " must be aligned to 2 bytes boundary.", \
exp)
#define NW4HBM_ASSERT_ALIGN32(line, exp) \
NW4R_DB_ASSERTMSG(line, NW4R_IS_ALIGNED_(exp, 32), \
"NW4HBM:Alignment Error(0x%x)\n" #exp " must be aligned to 32 bytes boundary.", \
exp)
#define NW4HBM_ASSERT_ALIGNED(line, exp, align) \
NW4R_DB_ASSERTMSG(line, NW4R_IS_ALIGNED_(exp, align), \
"NW4HBM:Alignment Error(0x%x)\n" #exp " must be aligned to " #align " bytes boundary.", \
exp)
#endif

View File

@ -0,0 +1,104 @@
#ifndef NW4R_DB_CONSOLE_H
#define NW4R_DB_CONSOLE_H
#include <revolution/types.h>
#include "assert.h"
#include "../ut/CharWriter.h"
#include "../ut/TextWriterBase.h"
namespace nw4hbm {
namespace db {
namespace detail {
struct ConsoleHead {
/* 0x00 */ u8* textBuf;
/* 0x04 */ u16 width;
/* 0x06 */ u16 height;
/* 0x08 */ u16 priority;
/* 0x0A */ u16 attr;
/* 0x0C */ u16 printTop;
/* 0x0E */ u16 printXPos;
/* 0x10 */ u16 printTopUsed;
/* 0x12 */ u16 ringTop;
/* 0x14 */ s32 ringTopLineCnt;
/* 0x18 */ s32 viewTopLine;
/* 0x1C */ s16 viewPosX;
/* 0x1E */ s16 viewPosY;
/* 0x20 */ u16 viewLines;
/* 0x22 */ bool isVisible;
/* 0x23 */ u8 padding_[1];
/* 0x24 */ ut::TextWriterBase<char>* writer;
/* 0x28 */ ConsoleHead* next;
};
} // namespace detail
enum ConsoleOutputType {
CONSOLE_OUTPUT_NONE,
CONSOLE_OUTPUT_TERMINAL,
CONSOLE_OUTPUT_DISPLAY,
CONSOLE_OUTPUT_ALL,
};
typedef detail::ConsoleHead* ConsoleHandle;
typedef void (*VisitStringCallback)(detail::ConsoleHead* console, u8* r4, long r5, u32 r6);
detail::ConsoleHead* Console_Create(void* buffer, u16 width, u16 height, u16 viewHeight,
u16 priority, u16 attr);
void Console_Destroy(detail::ConsoleHead* console);
void Console_Clear(detail::ConsoleHead* console);
void Console_Draw(detail::ConsoleHead* console, ut::TextWriterBase<char>& writer);
void Console_DrawDirect(detail::ConsoleHead* console);
void Console_DrawAll();
void Console_DrawDirectAll();
void Console_VFPrintf(ConsoleOutputType type, detail::ConsoleHead* console,
const char* format, std::va_list vlist);
void Console_FPrintf(ConsoleOutputType type, detail::ConsoleHead* console,
const char* format);
void Console_Printf(detail::ConsoleHead* console, const char* format, ...);
void Console_PrintfD(detail::ConsoleHead* console, const char* format, ...);
void Console_PrintfT(detail::ConsoleHead* console, const char* format, ...);
u16 Console_ChangePriority(detail::ConsoleHead* console, u16 r4);
void Console_VisitString(detail::ConsoleHead* console, VisitStringCallback visitor);
long Console_GetTotalLines(detail::ConsoleHead* console);
static long Console_SetViewBaseLine(detail::ConsoleHead* console, long line);
static u16 Console_GetViewHeight(detail::ConsoleHead* console);
static void Console_VPrintf(detail::ConsoleHead* console, const char* format, std::va_list vlist);
static long Console_ShowLatestLine(detail::ConsoleHead* console) {
long baseLine = Console_GetTotalLines(console) - Console_GetViewHeight(console);
if (baseLine < 0)
baseLine = 0;
Console_SetViewBaseLine(console, baseLine);
return baseLine;
}
static u16 Console_GetViewHeight(detail::ConsoleHead* console) {
NW4R_ASSERT_CHECK_NULL(434, console);
return console->viewLines;
}
static bool Console_SetVisible(detail::ConsoleHead* console, bool isVisible) {
NW4R_ASSERT_CHECK_NULL(497, console);
bool before = console->isVisible;
console->isVisible = isVisible;
return before;
}
static long Console_SetViewBaseLine(detail::ConsoleHead* console, long line) {
NW4R_ASSERT_CHECK_NULL(557, console);
long before = console->viewTopLine;
console->viewTopLine = line;
return before;
}
} // namespace db
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,17 @@
#include "DbgPrintBase.h"
#include "../ut/Color.h"
#include "../ut/CharWriter.h"
// Unused file. Only here to force the function CharWriter::SetTextColor(ut::Color&)
// into the right place.
namespace nw4hbm {
namespace db {
// Dummy function
void dummy(ut::CharWriter* pCharWriter) {
ut::Color color;
pCharWriter->SetTextColor(color);
}
} // namespace db
} // namespace nw4r

View File

@ -0,0 +1,191 @@
#include "assert.h"
#include <revolution/os.h>
#include <revolution/base/PPCArch.h>
#include <revolution/vi.h>
#include "console.h"
#include "mapFile.h"
#include "directPrint.h"
#include "global.h"
namespace nw4hbm {
namespace db {
using namespace detail;
static OSAlarm sWarningAlarm;
static u32 sWarningTime;
static ConsoleHead* sAssertionConsole;
static bool sDispWarningAuto;
static void Assertion_Printf_(const char* fmt, ...) {
va_list vlist;
va_start(vlist, fmt);
if (sAssertionConsole) {
Console_VFPrintf(CONSOLE_OUTPUT_ALL, sAssertionConsole, fmt, vlist);
} else {
OSVReport(fmt, vlist);
}
va_end(vlist);
}
static bool ShowMapInfoSubroutine_(u32 address, u8 preCRFlag) {
u8 strBuf[260];
if (!MapFile_Exists()) {
return false;
}
if (address < 0x80000000 || address > 0x82FFFFFF) {
return false;
}
if (MapFile_QuerySymbol(address, strBuf, sizeof(strBuf))) {
Assertion_Printf_("%s\n", strBuf);
return true;
} else {
return false;
}
}
static void ShowStack_(u32 sp) NO_INLINE {
Assertion_Printf_("-------------------------------- TRACE\n");
Assertion_Printf_("Address: BackChain LR save\n");
u32* p = (u32*)sp;
for (u32 i = 0; i < 16; i++, p = (u32*)*p) {
if (p == NULL || p == (u32*)0xFFFFFFFF || !((u32)p & 0x80000000))
break;
Assertion_Printf_("%08X: %08X %08X ", p, p[0], p[1]);
if (!ShowMapInfoSubroutine_(p[1], false)) {
Assertion_Printf_("\n");
}
}
}
DECL_WEAK void VPanic(const char* file, int line, const char* fmt, std::va_list vlist) {
register u32 stackPointer;
asm {
lwz stackPointer, 0(r1)
}
OSDisableInterrupts();
VISetPreRetraceCallback(NULL);
VISetPostRetraceCallback(NULL);
if (sAssertionConsole) {
detail::DirectPrint_SetupFB(NULL);
}
ShowStack_(stackPointer);
if (sAssertionConsole != NULL) {
Console_Printf(sAssertionConsole, "%s:%d Panic:", file, line);
Console_VFPrintf(CONSOLE_OUTPUT_ALL, sAssertionConsole, fmt, vlist);
Console_Printf(sAssertionConsole, "\n");
Console_ShowLatestLine(sAssertionConsole);
Console_SetVisible(sAssertionConsole, true);
Console_DrawDirect(sAssertionConsole);
} else {
OSReport("%s:%d Panic:", file, line);
OSVReport(fmt, vlist);
OSReport("\n");
}
PPCHalt();
}
DECL_WEAK void detail::Panic(const char* file, int line, const char* fmt, ...) {
va_list vlist;
va_start(vlist, fmt);
VPanic(file, line, fmt, vlist);
}
static OSAlarm& GetWarningAlarm_();
static void WarningAlarmFunc_(OSAlarm* alarm, OSContext* context);
DECL_WEAK void VWarning(const char* file, int line, const char* fmt, std::va_list vlist) {
if (sAssertionConsole != NULL) {
Console_Printf(sAssertionConsole, "%s:%d Warning:", file, line);
Console_VFPrintf(CONSOLE_OUTPUT_ALL, sAssertionConsole, fmt, vlist);
Console_Printf(sAssertionConsole, "\n");
Console_ShowLatestLine(sAssertionConsole);
Console_SetVisible(sAssertionConsole, true);
} else {
OSReport("%s:%d Warning:", file, line);
OSVReport(fmt, vlist);
OSReport("\n");
}
}
DECL_WEAK void detail::Warning(const char* file, int line, const char* fmt, ...) {
OSAlarm& alarm = GetWarningAlarm_();
va_list vlist;
va_start(vlist, fmt);
VWarning(file, line, fmt, vlist);
va_end(vlist);
if (sWarningTime > 0) {
OSCancelAlarm(&sWarningAlarm);
OSSetAlarm(&sWarningAlarm, sWarningTime, WarningAlarmFunc_);
}
}
namespace detail {
void Log(const char* fmt, ...) {
va_list vlist;
}
} // namespace detail
ConsoleHead* Assertion_SetConsole(ConsoleHead* console) {
ConsoleHead* before = sAssertionConsole;
sAssertionConsole = console;
return before;
}
ConsoleHead* Assertion_GetConsole() {
return sAssertionConsole;
}
void Assertion_ShowConsole(u32 time) {
if (sAssertionConsole != NULL) {
OSAlarm& alarm = GetWarningAlarm_();
OSCancelAlarm(&alarm);
Console_SetVisible(sAssertionConsole, true);
if (time != 0) {
OSSetAlarm(&alarm, time, WarningAlarmFunc_);
}
}
}
void Assertion_HideConsole() {
// OSAlarm& alarm;
}
void Assertion_SetWarningTime(u32 time) {}
static OSAlarm& GetWarningAlarm_() {
static bool sInitializedAlarm;
if (!sInitializedAlarm) {
OSCreateAlarm(&sWarningAlarm);
sInitializedAlarm = true;
}
return sWarningAlarm;
}
static void WarningAlarmFunc_(OSAlarm* alarm, OSContext* context) {
Console_SetVisible(sAssertionConsole, false);
}
} // namespace db
} // namespace nw4r

View File

@ -0,0 +1,315 @@
#include <revolution/os.h>
#include "assert.h"
#include "console.h"
#include "directPrint.h"
namespace nw4hbm {
namespace db {
static OSMutex sMutex;
static u8 sStrBuf[1024];
static inline u8* GetTextPtr_(ConsoleHandle console, u16 line, u16 xPos) {
return console->textBuf + xPos + (console->width + 1) * line;
}
static inline u32 CodeWidth_(u8 const* p) {
return *p >= 0x81 ? sizeof(wchar_t) : sizeof(char);
}
static inline u32 GetTabSize_(ConsoleHandle console) {
s32 tab = (console->attr & 0xC) >> 2;
return static_cast<u32>(2 << tab);
}
static inline u8 const* SearchEndOfLine_(u8 const* str) {
while (*str != '\n' && *str != '\0') {
str++;
}
return str;
}
static inline u16 GetRingUsedLines_(ConsoleHandle console) {
NW4HBM_ASSERT_CHECK_NULL(112, console);
{
s32 lines = console->printTop - console->ringTop;
if (lines < 0) {
lines += console->height;
}
return static_cast<u16>(lines);
}
}
static inline u16 GetActiveLines_(ConsoleHandle console) {
u16 lines = GetRingUsedLines_(console);
if (console->printTopUsed) {
lines++;
}
return lines;
}
static void TerminateLine_(ConsoleHandle console) {
*GetTextPtr_(console, console->printTop, console->printXPos) = '\0';
}
static u8* NextLine_(ConsoleHandle console) {
*GetTextPtr_(console, console->printTop, console->printXPos) = '\0';
console->printXPos = 0;
console->printTop++;
console->printTopUsed = 0;
if (console->printTop == console->height && !(console->attr & 2)) {
console->printTop = 0;
}
if (console->printTop == console->ringTop) {
console->ringTopLineCnt++;
if (++console->ringTop == console->height) {
console->ringTop = 0;
}
}
return GetTextPtr_(console, console->printTop, 0);
}
static u8* PutTab_(ConsoleHandle console, u8* dstPtr) {
u32 tabWidth = GetTabSize_(console);
do {
*dstPtr++ = ' ';
console->printXPos++;
if (console->printXPos >= console->width) {
break;
}
} while (console->printXPos & (tabWidth - 1));
return dstPtr;
}
static u32 PutChar_(ConsoleHandle console, u8 const* str, u8* dstPtr) {
u32 codeWidth = CodeWidth_(str);
u32 cnt;
if (console->printXPos + codeWidth <= console->width == 0) {
return false;
}
console->printXPos += codeWidth;
for (cnt = codeWidth; cnt; cnt--) {
*dstPtr++ = *str++;
}
return codeWidth;
}
static void UnlockMutex_(OSMutex* mutex) {
OSUnlockMutex(mutex);
}
static bool TryLockMutex_(OSMutex* mutex) {
OSLockMutex(mutex);
return true;
}
static void DoDrawString_(ConsoleHandle console, u32 printLine, u8 const* str,
ut::TextWriterBase<char>* writer) {
if (writer) {
writer->Printf("%s\n", str);
} else {
s32 height = (s32)((u32)console->viewPosY + printLine * 10);
DirectPrint_DrawString(console->viewPosX, height, false, "%s\n", str);
}
}
static void DoDrawConsole_(ConsoleHandle console, ut::TextWriterBase<char>* writer) {
s32 viewOffset;
u16 line;
u16 printLines;
viewOffset = console->viewTopLine - console->ringTopLineCnt;
printLines = 0;
if (viewOffset < 0) {
viewOffset = 0;
} else if (viewOffset > GetActiveLines_(console)) {
return;
}
line = static_cast<u16>(console->ringTop + viewOffset);
if (line >= console->height) {
line -= console->height;
}
while (true) {
if (line == console->printTop && console->printTopUsed == 0) {
break;
}
DoDrawString_(console, printLines, GetTextPtr_(console, line, 0), writer);
printLines++;
if (line == console->printTop) {
break;
}
line++;
if (line == console->height) {
if (console->attr & 2) {
return;
}
line = 0;
}
if (printLines >= console->viewLines) {
return;
}
}
}
void Console_DrawDirect(ConsoleHandle console) {
NW4HBM_ASSERT_CHECK_NULL(621, console);
if (DirectPrint_IsActive() && console->isVisible) {
TryLockMutex_(&sMutex);
int width = console->width * 6 + 12, height = console->viewLines * 10 + 4;
DirectPrint_EraseXfb(console->viewPosX - 6, console->viewPosY - 3, width, height);
DoDrawConsole_(console, NULL);
DirectPrint_StoreCache();
UnlockMutex_(&sMutex);
}
}
void dummyString(ConsoleHandle pConsole) {
NW4HBM_ASSERT_CHECK_NULL(0, pConsole);
OSReport("illegal console handle");
u8* buffer;
NW4HBM_ASSERT_CHECK_NULL(0, buffer);
OSReport("NW4HBM:Alignment Error(0x%x)\nbuffer must be aligned to 4 bytes boundary.");
}
static void PrintToBuffer_(ConsoleHandle console, u8 const* str) {
u8* storePtr;
NW4HBM_ASSERT_CHECK_NULL(747, console);
NW4HBM_ASSERT_CHECK_NULL(748, str);
storePtr = GetTextPtr_(console, console->printTop, console->printXPos);
while (*str) {
if (console->attr & 2 && console->printTop == console->height) {
break;
}
while (*str) // ? just use continue? am i missing something?
{
bool newLineFlag = false;
if (*str == '\n') {
str++;
storePtr = NextLine_(console);
break;
}
if (*str == '\t') {
str++;
storePtr = PutTab_(console, storePtr);
console->printTopUsed = 1;
} else {
u32 bytes = PutChar_(console, str, storePtr);
if (bytes) {
console->printTopUsed = 1;
str += bytes;
storePtr += bytes;
} else {
newLineFlag = true;
}
}
if (console->printXPos >= console->width) {
newLineFlag = true;
}
if (newLineFlag) {
if (console->attr & 1) {
str = SearchEndOfLine_(str);
break;
}
if (*str == '\n') {
str++;
}
storePtr = NextLine_(console);
break;
}
}
}
}
static void Console_PrintString_(ConsoleOutputType type, ConsoleHandle console,
u8 const* str) {
NW4HBM_ASSERT_CHECK_NULL(843, console);
if (type & CONSOLE_OUTPUT_DISPLAY) {
OSReport("%s", str);
}
if (type & CONSOLE_OUTPUT_TERMINAL) {
PrintToBuffer_(console, str);
}
}
void Console_VFPrintf(ConsoleOutputType type, ConsoleHandle console, char const* format,
std::va_list vlist) {
NW4HBM_ASSERT_CHECK_NULL(872, console);
if (TryLockMutex_(&sMutex)) {
std::vsnprintf(reinterpret_cast<char*>(sStrBuf), sizeof(sStrBuf), format, vlist);
Console_PrintString_(type, console, sStrBuf);
UnlockMutex_(&sMutex);
}
}
void Console_Printf(ConsoleHandle console, char const* format, ...) {
std::va_list vlist;
va_start(vlist, format);
Console_VFPrintf(CONSOLE_OUTPUT_ALL, console, format, vlist);
va_end(vlist);
}
s32 Console_GetTotalLines(ConsoleHandle console) {
s32 count;
// this is not part of this function but it's required to generate the dtor
// (`nw4hbm::ut::Color::~Color()`) it was probably part of a function that got stripped
// by the linker
::nw4hbm::ut::Color unused;
NW4HBM_ASSERT_CHECK_NULL(1050, console);
TryLockMutex_(&sMutex);
count = GetActiveLines_(console) + console->ringTopLineCnt;
UnlockMutex_(&sMutex);
return count;
}
} // namespace db
} // namespace nw4hbm

View File

@ -0,0 +1,464 @@
#include <revolution/os.h>
#include <revolution/vi.h>
#include "assert.h"
#include "directPrint.h"
#include <string.h>
#define ROUND_UP(x, align) (((x) + (align)-1) & (-(align)))
#define ROUND_DOWN(x, align) ((x) & (~((align) - 1)))
typedef struct FrameBufferInfo {
/* 0x00 */ u8* frameMemory;
/* 0x04 */ u32 frameSize;
/* 0x08 */ u16 frameWidth;
/* 0x0A */ u16 frameHeight;
/* 0x0C */ u16 frameRow;
/* 0x0E */ u16 reserved;
} FrameBufferInfo;
typedef struct YUVColorInfo {
/* 0x00 */ GXColor colorRGBA;
/* 0x04 */ u16 colorY256;
/* 0x06 */ u16 colorU;
/* 0x08 */ u16 colorU2;
/* 0x0A */ u16 colorU4;
/* 0x0C */ u16 colorV;
/* 0x0E */ u16 colorV2;
/* 0x10 */ u16 colorV4;
/* 0x12 */ u16 reserved;
} YUVColorInfo;
namespace nw4hbm {
namespace db {
static void DrawStringToXfb_(int posh, int posv, char const* str, bool turnOver,
bool backErase);
static char const* DrawStringLineToXfb_(int posh, int posv, char const* str, int width);
static void DrawCharToXfb_(int posh, int posv, int code);
namespace detail {
static void WaitVIRetrace_();
static void* CreateFB_(GXRenderModeObj const* rmode);
} // namespace detail
static inline int StrLineWidth_(char const* str) {
int len = 0;
char c;
NW4HBM_ASSERT_CHECK_NULL(306, str);
while (true) {
c = *str++;
if (c == '\0' || c == '\n') {
return len;
}
if (c == '\t') {
len = (len + 4) & -4;
continue;
}
len++;
}
return len;
}
static const u8 sAsciiTable[128] = {
0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0xFD, 0xFE, 0x7A, 0x7A,
0x7A, 0x7A, 0x7A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x29, 0x64, 0x65, 0x66, 0x2B, 0x67,
0x68, 0x25, 0x26, 0x69, 0x2A, 0x6A, 0x27, 0x2C, 0x6B, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x24, 0x6C, 0x6D, 0x6E, 0x6F, 0x28, 0x70,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
0x71, 0x72, 0x73, 0x74, 0x75, 0xFF, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90,
0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x76, 0x77, 0x78, 0x79, 0x7A,
};
static const u32 sFontData[64] = {
0x70871C30, 0x8988A250, 0x88808290, 0x88830C90, 0x888402F8, 0x88882210, 0x71CF9C10,
0xF9CF9C70, 0x8208A288, 0xF200A288, 0x0BC11C78, 0x0A222208, 0x8A222208, 0x71C21C70,
0x23C738F8, 0x5228A480, 0x8A282280, 0x8BC822F0, 0xFA282280, 0x8A28A480, 0x8BC738F8,
0xF9C89C08, 0x82288808, 0x82088808, 0xF2EF8808, 0x82288888, 0x82288888, 0x81C89C70,
0x8A08A270, 0x920DA288, 0xA20AB288, 0xC20AAA88, 0xA208A688, 0x9208A288, 0x8BE8A270,
0xF1CF1CF8, 0x8A28A220, 0x8A28A020, 0xF22F1C20, 0x82AA0220, 0x82492220, 0x81A89C20,
0x8A28A288, 0x8A28A288, 0x8A289488, 0x8A2A8850, 0x894A9420, 0x894AA220, 0x70852220,
0xF8011000, 0x08020800, 0x10840400, 0x20040470, 0x40840400, 0x80020800, 0xF8011000,
0x70800000, 0x88822200, 0x08820400, 0x108F8800, 0x20821000, 0x00022200, 0x20800020,
0x00000000,
};
static const u32 sFontData2[77] = {
0x51421820, 0x53E7A420, 0x014A2C40, 0x01471000, 0x0142AA00, 0x03EAA400, 0x01471A78,
0x00000000, 0x50008010, 0x20010820, 0xF8020040, 0x20420820, 0x50441010, 0x00880000,
0x00070E00, 0x01088840, 0x78898820, 0x004A8810, 0x788A8810, 0x01098808, 0x00040E04,
0x70800620, 0x11400820, 0x12200820, 0x10001020, 0x10000820, 0x100F8820, 0x70000620,
0x60070000, 0x110F82A0, 0x12AA8AE0, 0x084F92A0, 0x100FBE1C, 0x10089008, 0x60070808,
0x00000000, 0x02000200, 0x7A078270, 0x8BC81E88, 0x8A2822F8, 0x9A282280, 0x6BC79E78,
0x30000000, 0x48080810, 0x41E80000, 0x422F1830, 0xFBE88810, 0x40288890, 0x43C89C60,
0x81000000, 0x81000000, 0x990F3C70, 0xA10AA288, 0xE10AA288, 0xA10AA288, 0x98CAA270,
0x00000000, 0x00000020, 0xF1EF1E20, 0x8A28A0F8, 0x8A281C20, 0xF1E80220, 0x80283C38,
0x00000000, 0x00000000, 0x8A28B688, 0x8A2A8888, 0x8A2A8878, 0x894A8808, 0x788536F0,
0x00000000, 0x00000000, 0xF8000000, 0x10000000, 0x20000000, 0x40000000, 0xF8000000,
};
static FrameBufferInfo sFrameBufferInfo;
static YUVColorInfo sFrameBufferColor;
static int sInitialized = false;
static inline int GetDotWidth_() {
return sFrameBufferInfo.frameWidth < 400 ? 1 : 2;
}
static inline int GetDotHeight_() {
return sFrameBufferInfo.frameHeight < 300 ? 1 : 2;
}
void DirectPrint_Init() {
if (!sInitialized) {
DirectPrint_ChangeXfb(NULL, 640, 480);
DirectPrint_SetColor(0xff, 0xff, 0xff);
sInitialized = true;
}
}
bool DirectPrint_IsActive() {
return sInitialized && sFrameBufferInfo.frameMemory;
}
void DirectPrint_EraseXfb(int posh, int posv, int sizeh, int sizev) {
int posEndH, posEndV;
if (sFrameBufferInfo.frameMemory == NULL) {
return;
}
if (GetDotWidth_() == 2) {
posh *= 2;
sizeh *= 2;
}
posEndH = posh + sizeh;
posh = posh >= 0 ? posh : 0;
posEndH = posEndH <= sFrameBufferInfo.frameWidth ? posEndH : sFrameBufferInfo.frameWidth;
sizeh = posEndH - posh;
if (GetDotHeight_() == 2) {
posv *= 2;
sizev *= 2;
}
posEndV = posv + sizev;
posv = posv >= 0 ? posv : 0;
posEndV = posEndV <= sFrameBufferInfo.frameHeight ? posEndV : sFrameBufferInfo.frameHeight;
sizev = posEndV - posv;
u16* pixel = reinterpret_cast<u16*>(sFrameBufferInfo.frameMemory) +
sFrameBufferInfo.frameRow * posv + posh;
for (int cntv = 0; cntv < sizev; cntv++) {
for (int cnth = 0; cnth < sizeh; cnth++) {
*pixel++ = 0x1080; // some sort of white or black?
}
pixel += sFrameBufferInfo.frameRow - sizeh;
}
}
void DirectPrint_ChangeXfb(void* framebuf, u16 width, u16 height) {
sFrameBufferInfo.frameMemory = static_cast<u8*>(framebuf);
sFrameBufferInfo.frameWidth = width;
sFrameBufferInfo.frameHeight = height;
sFrameBufferInfo.frameRow = ROUND_UP(static_cast<u16>(width), 16);
sFrameBufferInfo.frameSize =
sFrameBufferInfo.frameRow * sFrameBufferInfo.frameHeight * 2;
}
void DirectPrint_ChangeXfb(void* framebuf) {
sFrameBufferInfo.frameMemory = static_cast<u8*>(framebuf);
}
void DirectPrint_StoreCache(void) {
DCStoreRange(sFrameBufferInfo.frameMemory, sFrameBufferInfo.frameSize);
}
void DirectPrint_DrawString(int posh, int posv, bool turnOver, char const* format, ...) {
if (sFrameBufferInfo.frameMemory) {
std::va_list vargs;
va_start(vargs, format);
detail::DirectPrint_DrawStringToXfb(posh, posv, format, vargs, turnOver, false);
va_end(vargs);
}
}
// Intel IPP RGBToYCbCr algorithm, same as OSFatal.c::RGB2YUV
void DirectPrint_SetColor(u8 r, u8 g, u8 b) {
int y = (int)(0.257f * (int)r + 0.504f * (int)g + 0.098f * (int)b + 16.0f);
int u = (int)(-0.148f * (int)r - 0.291f * (int)g + 0.439f * (int)b + 128.0f);
int v = (int)(0.439f * (int)r - 0.368f * (int)g - 0.071f * (int)b + 128.0f);
sFrameBufferColor.colorRGBA.r = r;
sFrameBufferColor.colorRGBA.g = g;
sFrameBufferColor.colorRGBA.b = b;
sFrameBufferColor.colorRGBA.a = 0xff;
sFrameBufferColor.colorY256 = static_cast<u16>(y << 8);
sFrameBufferColor.colorU = static_cast<u16>(u);
sFrameBufferColor.colorU2 = static_cast<u16>(u / 2);
sFrameBufferColor.colorU4 = static_cast<u16>(u / 4);
sFrameBufferColor.colorV = static_cast<u16>(v);
sFrameBufferColor.colorV2 = static_cast<u16>(v / 2);
sFrameBufferColor.colorV4 = static_cast<u16>(v / 4);
}
void detail::DirectPrint_DrawStringToXfb(int posh, int posv, char const* format,
std::va_list vargs, bool turnOver,
bool backErase) {
char string[256];
NW4HBM_ASSERT(647, sFrameBufferInfo.frameMemory != NULL);
int length = std::vsnprintf(string, sizeof(string), format, vargs);
int posLeftStart = posh;
if (length > 0) {
DrawStringToXfb_(posh, posv, string, turnOver, backErase);
}
}
static void DrawStringToXfb_(int posh, int posv, char const* str, bool turnOver,
bool backErase) {
int basePosH = posh;
int width;
int frameWidth = sFrameBufferInfo.frameWidth / GetDotWidth_();
while (*str != '\0') {
int len;
if (backErase) {
len = StrLineWidth_(str);
DirectPrint_EraseXfb(posh - 6, posv - 3, (len + 2) * 6, 13);
}
width = (frameWidth - posh) / 6;
str = DrawStringLineToXfb_(posh, posv, str, width);
posv += 10;
if (*str == '\n') {
str++;
posh = basePosH;
continue;
}
if (*str == '\0') {
continue;
}
str++;
if (!turnOver) {
str = strchr(str, '\n');
if (str) {
str++;
posh = basePosH;
continue;
} else {
break;
}
}
posh = 0;
}
}
static char const* DrawStringLineToXfb_(int posh, int posv, char const* str, int width) {
char c;
int code;
int cnt = 0;
NW4HBM_ASSERT_CHECK_NULL(745, str);
NW4HBM_ASSERT(746, width > 0);
for (; (c = *str) != '\0'; str++) {
if (c == '\n' || c == '\0') { // another check against null character?
return str;
}
code = sAsciiTable[c % sizeof(sAsciiTable)];
if (code == 0xfd) {
int tab_size = 4 - (cnt & 3);
posh += tab_size * 6;
cnt += tab_size;
} else {
if (code != 0xff) {
DrawCharToXfb_(posh, posv, code);
}
posh += 6;
cnt++;
}
if (cnt >= width) {
if (str[1] == '\n') {
str++;
}
return str;
}
}
return str;
}
static void DrawCharToXfb_(int posh, int posv, int code) {
static u32 twiceBit[4] = {0, 3, 12, 15};
int ncode = code >= 100 ? code - 100 : code;
int fonth = ncode % 5 * 6;
int fontv = ncode / 5 * 7;
const u32* fontLine = code < 100 ? &sFontData[fontv] : &sFontData2[fontv];
int wH = GetDotWidth_();
int wV = GetDotHeight_();
u16* pixel = reinterpret_cast<u16*>(sFrameBufferInfo.frameMemory) +
sFrameBufferInfo.frameRow * posv * wV + posh * wH;
if (posv < 0 || posh < 0) {
return;
}
if (sFrameBufferInfo.frameWidth <= wH * (posh + 6) ||
sFrameBufferInfo.frameHeight <= wV * (posv + 7))
{
return;
}
for (int cntv = 0; cntv < 7; cntv++) {
u32 fontBits = *fontLine++ << fonth;
if (wH == 1) {
fontBits = (fontBits & 0xfc000000) >> 1;
} else {
fontBits =
(twiceBit[(fontBits >> 26) & 3] | twiceBit[(fontBits >> 28) & 3] << 4 |
twiceBit[(fontBits >> 30) & 3] << 8)
<< 19;
}
for (int cnth = 0; cnth < wH * 6;) {
u16 pixColor = (fontBits & (1u << 30) ? sFrameBufferColor.colorY256 : 0x00) |
((fontBits & (1u << 31) ? sFrameBufferColor.colorU4 : 0x20) +
(fontBits & (1u << 30) ? sFrameBufferColor.colorU2 : 0x40) +
(fontBits & (1u << 29) ? sFrameBufferColor.colorU4 : 0x20));
*pixel = pixColor;
if (wV > 1) {
pixel[sFrameBufferInfo.frameRow] = pixColor;
}
pixel++;
pixColor = (fontBits & (1u << 29) ? sFrameBufferColor.colorY256 : 0x00) |
((fontBits & (1u << 30) ? sFrameBufferColor.colorV4 : 0x20) +
(fontBits & (1u << 29) ? sFrameBufferColor.colorV2 : 0x40) +
(fontBits & (1u << 28) ? sFrameBufferColor.colorV4 : 0x20));
*pixel = pixColor;
if (wV > 1) {
pixel[sFrameBufferInfo.frameRow] = pixColor;
}
pixel++;
fontBits <<= 2;
cnth += 2;
}
pixel += sFrameBufferInfo.frameRow * wV - 6 * wH;
}
}
static void detail::WaitVIRetrace_(void) {
int intrStatus = OSEnableInterrupts(); /* int enabled; */
u32 preCnt = VIGetRetraceCount();
while (preCnt == VIGetRetraceCount()) { /* ... */
}
OSRestoreInterrupts(intrStatus);
}
static void* detail::CreateFB_(GXRenderModeObj const* rmode) {
u32 arenaHi = (u32)OSGetArenaHi();
u32 memSize = (u16)ROUND_UP((u16)rmode->fbWidth, 16) * rmode->xfbHeight * 2;
u32 frameBuf = ROUND_DOWN(arenaHi - memSize, 32);
VIConfigure(rmode);
VISetNextFrameBuffer(reinterpret_cast<void*>(frameBuf));
return reinterpret_cast<void*>(frameBuf);
}
void* detail::DirectPrint_SetupFB(GXRenderModeObj const* rmode) {
void* frameMemory;
DirectPrint_Init();
frameMemory = VIGetCurrentFrameBuffer();
if (!frameMemory) {
if (!rmode) {
switch (VIGetTvFormat()) {
case VI_TVMODE_NTSC_INT:
rmode = &GXNtsc480IntDf;
break;
case VI_TVMODE_NTSC_DS:
rmode = &GXPal528IntDf;
break;
case VI_TVMODE_PAL_DS:
rmode = &GXEurgb60Hz480IntDf;
break;
case VI_TVMODE_NTSC_PROG:
rmode = &GXMpal480IntDf;
break;
}
}
frameMemory = CreateFB_(rmode);
}
VISetBlack(false);
VIFlush();
WaitVIRetrace_();
if (rmode) {
DirectPrint_ChangeXfb(frameMemory, rmode->fbWidth, rmode->xfbHeight);
} else {
DirectPrint_ChangeXfb(frameMemory);
}
return frameMemory;
}
} // namespace db
} // namespace nw4hbm

View File

@ -0,0 +1,367 @@
#include <revolution/dvd.h>
#include <revolution/os.h>
#include "assert.h"
#include "mapFile.h"
#include "global.h"
typedef u8 GetCharFunc(u8 const* buf);
namespace nw4hbm {
namespace db {
static u8 GetCharOnMem_(const u8* buf);
static u8 GetCharOnDvd_(u8 const* buf);
static u8* SearchNextLine_(u8* buf, s32 lines);
static u8* SearchNextSection_(u8* buf);
static u8* SearchParam_(u8* lineTop, u32 argNum, u8 splitter);
static u32 XStrToU32_(u8 const* str);
static u32 CopySymbol_(u8 const* buf, u8* str, u32 strLenMax, u8 splitter);
static bool QuerySymbolToMapFile_(u8* buf, OSModuleInfo const* moduleInfo, u32 address,
u8* strBuf, u32 strBufSize);
static bool QuerySymbolToSingleMapFile_(MapFile* pMapFile, u32 address, u8* strBuf,
u32 strBufSize) NO_INLINE;
} // namespace db
} // namespace nw4hbm
namespace nw4hbm {
namespace db {
static u8 sMapBuf[0x200];
static s32 sMapBufOffset = -1;
static DVDFileInfo sFileInfo;
static u32 sFileLength;
static MapFile* sMapFileList;
static GetCharFunc* GetCharPtr_;
} // namespace db
} // namespace nw4hbm
namespace nw4hbm {
namespace db {
bool MapFile_Exists(void) {
return sMapFileList ? true : false;
}
static u8 GetCharOnMem_(u8 const* buf) {
return *buf;
}
static s32 GetSize(s32 offset, u32 length) {
if (offset + ARRAY_SIZE(sMapBuf) >= length) {
return OSRoundUp32B(length - offset);
}
return ARRAY_SIZE(sMapBuf);
}
static u8 GetCharOnDvd_(u8 const* buf) {
s32 address = (u32)buf & ~0x80000000;
s32 offset = address - sMapBufOffset;
if (address >= sFileLength) {
return 0;
}
if (sMapBufOffset < 0 || offset < 0 || ARRAY_SIZE(sMapBuf) <= offset) {
s32 len;
s32 size;
sMapBufOffset = OSRoundDown32B(address);
offset = address - sMapBufOffset;
size = GetSize(sMapBufOffset, sFileLength);
BOOL enabled = OSEnableInterrupts();
len = DVDReadAsyncPrio(&sFileInfo, sMapBuf, size, sMapBufOffset, NULL, 2);
while (DVDGetCommandBlockStatus(&sFileInfo.cb)) {}
OSRestoreInterrupts(enabled);
if (len <= 0) {
return 0;
}
}
return sMapBuf[offset];
}
void dummyString() {
u8* buffer;
NW4HBM_ASSERT_CHECK_NULL(0, buffer);
u8* mapDataBuf;
NW4HBM_ASSERT_CHECK_NULL(0, mapDataBuf);
MapFile* pMapFile;
NW4HBM_ASSERT_CHECK_NULL(0, pMapFile);
NW4HBM_ASSERT(0, sMapFileList->moduleInfo != NULL);
u8* filePath;
NW4HBM_ASSERT_CHECK_NULL(0, filePath);
NW4HBM_ASSERT(0, pMapFile->fileEntry >= 0);
}
static u8* SearchNextLine_(u8* buf, s32 lines) {
u8 c;
NW4HBM_ASSERT_CHECK_NULL(361, GetCharPtr_);
if (buf == NULL) {
return NULL;
}
for (; (c = (*GetCharPtr_)(buf)) != '\0'; buf++) {
if (c == '\n') {
if (--lines <= 0) {
return buf + 1;
}
}
}
return NULL;
}
static u8* SearchNextSection_(u8* buf) {
NW4HBM_ASSERT_CHECK_NULL(397, GetCharPtr_);
do {
buf = SearchNextLine_(buf, 1);
if (!buf) {
return NULL;
}
} while ((*GetCharPtr_)(buf) != '.');
return buf;
}
static u8* SearchParam_(u8* lineTop, u32 argNum, u8 splitter) {
int inArg = 0;
u8* buf = lineTop;
NW4HBM_ASSERT_CHECK_NULL(432, GetCharPtr_);
if (buf == NULL) {
return NULL;
}
while (true) {
u8 c = (*GetCharPtr_)(buf);
if (c == '\0' || c == '\n') {
return 0;
}
if (inArg) {
if (c == splitter) {
inArg = 0;
}
} else if (c != splitter) {
if (!argNum--) {
return buf;
}
inArg = 1;
}
buf++;
}
return 0;
}
static u32 XStrToU32_(u8 const* str) {
u32 val = 0;
NW4HBM_ASSERT_CHECK_NULL(486, str);
NW4HBM_ASSERT_CHECK_NULL(487, GetCharPtr_);
while (true) {
u32 num;
u8 c;
c = (*GetCharPtr_)(str);
if ('0' <= c && c <= '9') {
num = static_cast<u32>(c - '0');
} else if ('a' <= c && c <= 'z') {
num = static_cast<u32>(c - ('a' - 10)); // ?
} else if ('A' <= c && c <= 'Z') {
num = static_cast<u32>(c - ('A' - 10)); // What's the - 10 for
} else {
return val;
}
if (val >= 0x10000000) {
return 0;
}
val = num + (val << 4);
str++;
}
return 0;
}
static u32 CopySymbol_(const u8* buf, u8* str, u32 strLenMax, u8 splitter) {
u32 cnt = 0;
NW4HBM_ASSERT_CHECK_NULL(544, buf);
NW4HBM_ASSERT_CHECK_NULL(545, str);
NW4HBM_ASSERT_CHECK_NULL(546, GetCharPtr_);
while (true) {
u8 c = (*GetCharPtr_)(buf++);
if (c == splitter || c == '\0' || c == '\n') {
*str = '\0';
return cnt;
}
*str = c;
str++;
cnt++;
if (cnt >= strLenMax - 1) {
*str = '\0';
return cnt;
}
}
return 0;
}
static bool QuerySymbolToMapFile_(u8* buf, OSModuleInfo const* moduleInfo, u32 address,
u8* strBuf, u32 strBufSize) {
OSSectionInfo* sectionInfo = NULL;
u32 sectionCnt;
NW4HBM_ASSERT_CHECK_NULL(602, strBuf);
NW4HBM_ASSERT(603, strBufSize > 0);
if (moduleInfo) {
sectionInfo = reinterpret_cast<OSSectionInfo*>(moduleInfo->sectionInfoOffset);
sectionCnt = moduleInfo->numSections;
}
do {
u32 offset = 0;
buf = SearchNextSection_(buf);
buf = SearchNextLine_(buf, 3);
if (sectionInfo) {
offset = sectionInfo->offset;
if (address < offset) {
goto get_next_section_info;
}
if (address >= offset + sectionInfo->size) {
goto get_next_section_info;
}
}
while (true) {
u8* param;
u32 startAddr;
u32 size;
buf = SearchNextLine_(buf, 1);
if (!buf) {
return false;
}
param = SearchParam_(buf, 1, ' ');
if (!param) {
break;
}
size = XStrToU32_(param);
param = SearchParam_(buf, 2, ' ');
if (!param) {
break;
}
startAddr = XStrToU32_(param);
if (!startAddr) {
continue;
}
startAddr = startAddr + offset;
if (address < startAddr || startAddr + size <= address) {
continue;
}
param = SearchParam_(buf, 5, ' ');
if (!param) {
*strBuf = '\0';
return true;
}
if ((*GetCharPtr_)(param) == '.') {
continue;
}
CopySymbol_(param, strBuf, strBufSize, ' ');
return true;
}
get_next_section_info:
if (sectionInfo) {
if (!--sectionCnt) {
return false;
}
sectionInfo++;
}
} while (true);
return false;
}
static bool QuerySymbolToSingleMapFile_(MapFile* pMapFile, u32 address, u8* strBuf,
u32 strBufSize) {
NW4HBM_ASSERT_CHECK_NULL(723, pMapFile);
NW4HBM_ASSERT_CHECK_NULL(724, strBuf);
if (pMapFile->mapBuf) {
GetCharPtr_ = &GetCharOnMem_;
return QuerySymbolToMapFile_(pMapFile->mapBuf, pMapFile->moduleInfo, address,
strBuf, strBufSize);
}
if (pMapFile->fileEntry >= 0) {
bool ret;
if (DVDFastOpen(pMapFile->fileEntry, &sFileInfo)) {
sFileLength = sFileInfo.length;
GetCharPtr_ = &GetCharOnDvd_;
ret = QuerySymbolToMapFile_((u8*)(0x80000000), pMapFile->moduleInfo, address, strBuf, strBufSize);
DVDClose(&sFileInfo);
return ret;
}
}
*strBuf = '\0';
return false;
}
bool MapFile_QuerySymbol(u32 address, u8* strBuf, u32 strBufSize) {
MapFile* pMap;
for (pMap = sMapFileList; pMap; pMap = pMap->next) {
if (QuerySymbolToSingleMapFile_(pMap, address, strBuf, strBufSize)) {
return true;
}
}
return false;
}
} // namespace db
} // namespace nw4hbm

View File

@ -0,0 +1,23 @@
#ifndef NW4R_DB_DIRECTPRINT_H
#define NW4R_DB_DIRECTPRINT_H
#include <revolution/gx.h>
namespace nw4hbm {
namespace db {
void DirectPrint_Init();
bool DirectPrint_IsActive();
void DirectPrint_EraseXfb(int posh, int posv, int sizeh, int sizev);
void DirectPrint_ChangeXfb(void* framebuf, u16 width, u16 height);
void DirectPrint_StoreCache();
void DirectPrint_DrawString(int posh, int posv, bool turnOver, const char* format, ...);
void DirectPrint_SetColor(u8 r, u8 g, u8 b);
namespace detail {
void DirectPrint_DrawStringToXfb(int posh, int posv, const char* format, va_list vargs, bool turnOver, bool backErase);
void* DirectPrint_SetupFB(const GXRenderModeObj* rmode);
}
} // namespace db
} // namespace nw4r
#endif

View File

@ -0,0 +1,20 @@
#ifndef NW4R_DB_MAPFILE_H
#define NW4R_DB_MAPFILE_H
#include <revolution/os.h>
namespace nw4hbm {
namespace db {
struct MapFile {
/* 0x00 */ u8* mapBuf;
/* 0x04 */ OSModuleInfo* moduleInfo;
/* 0x08 */ s32 fileEntry;
/* 0x0C */ MapFile* next;
}; // size = 0x10
bool MapFile_Exists();
bool MapFile_QuerySymbol(u32 address, u8* strBuf, u32 strBufSize);
} // namespace db
} // namespace nw4r
#endif

View File

@ -0,0 +1,209 @@
#ifndef NW4HBM_LYT_ANIMATION_H
#define NW4HBM_LYT_ANIMATION_H
#include "lyt_types.h"
#include "resourceAccessor.h"
#include "resources.h"
#define TexMtxMax 10
#define IndTexMtxMax 3
namespace nw4hbm {
namespace lyt {
class Pane;
class Material;
enum {
/* 0 */ ANIMTARGET_PANE_TRANSX = 0,
/* 1 */ ANIMTARGET_PANE_TRANSY,
/* 2 */ ANIMTARGET_PANE_TRANSZ,
/* 3 */ ANIMTARGET_PANE_ROTX,
/* 4 */ ANIMTARGET_PANE_ROTY,
/* 5 */ ANIMTARGET_PANE_ROTZ,
/* 6 */ ANIMTARGET_PANE_SCALEX,
/* 7 */ ANIMTARGET_PANE_SCALEY,
/* 8 */ ANIMTARGET_PANE_SIZEX,
/* 9 */ ANIMTARGET_PANE_SIZEY,
/* 10 */ ANIMTARGET_PANE_MAX,
/* 16 */ ANIMTARGET_PANE_COLOR_ALPHA = 16,
/* 17 */ ANIMTARGET_PANE_COLOR_MAX,
};
enum {
/* 0 */ ANIMTARGET_VERTEXCOLOR_LT_RED = 0,
/* 1 */ ANIMTARGET_VERTEXCOLOR_LT_GREEN,
/* 2 */ ANIMTARGET_VERTEXCOLOR_LT_BLUE,
/* 3 */ ANIMTARGET_VERTEXCOLOR_LT_ALPHA,
/* 4 */ ANIMTARGET_VERTEXCOLOR_RT_RED,
/* 5 */ ANIMTARGET_VERTEXCOLOR_RT_GREEN,
/* 6 */ ANIMTARGET_VERTEXCOLOR_RT_BLUE,
/* 7 */ ANIMTARGET_VERTEXCOLOR_RT_ALPHA,
/* 8 */ ANIMTARGET_VERTEXCOLOR_LB_RED,
/* 9 */ ANIMTARGET_VERTEXCOLOR_LB_GREEN,
/* 10 */ ANIMTARGET_VERTEXCOLOR_LB_BLUE,
/* 11 */ ANIMTARGET_VERTEXCOLOR_LB_ALPHA,
/* 12 */ ANIMTARGET_VERTEXCOLOR_RB_RED,
/* 13 */ ANIMTARGET_VERTEXCOLOR_RB_GREEN,
/* 14 */ ANIMTARGET_VERTEXCOLOR_RB_BLUE,
/* 15 */ ANIMTARGET_VERTEXCOLOR_RB_ALPHA,
/* 16 */ ANIMTARGET_VERTEXCOLOR_MAX
};
enum {
/* 0 */ ANIMTARGET_MATCOLOR_MATR = 0,
/* 1 */ ANIMTARGET_MATCOLOR_MATG,
/* 2 */ ANIMTARGET_MATCOLOR_MATB,
/* 3 */ ANIMTARGET_MATCOLOR_MATA,
/* 4 */ ANIMTARGET_MATCOLOR_TEV0R,
/* 5 */ ANIMTARGET_MATCOLOR_TEV0G,
/* 6 */ ANIMTARGET_MATCOLOR_TEV0B,
/* 7 */ ANIMTARGET_MATCOLOR_TEV0A,
/* 8 */ ANIMTARGET_MATCOLOR_TEV1R,
/* 9 */ ANIMTARGET_MATCOLOR_TEV1G,
/* 10 */ ANIMTARGET_MATCOLOR_TEV1B,
/* 11 */ ANIMTARGET_MATCOLOR_TEV1A,
/* 12 */ ANIMTARGET_MATCOLOR_TEV2R,
/* 13 */ ANIMTARGET_MATCOLOR_TEV2G,
/* 14 */ ANIMTARGET_MATCOLOR_TEV2B,
/* 15 */ ANIMTARGET_MATCOLOR_TEV2A,
/* 16 */ ANIMTARGET_MATCOLOR_TEVK0R,
/* 17 */ ANIMTARGET_MATCOLOR_TEVK0G,
/* 18 */ ANIMTARGET_MATCOLOR_TEVK0B,
/* 19 */ ANIMTARGET_MATCOLOR_TEVK0A,
/* 20 */ ANIMTARGET_MATCOLOR_TEVK1R,
/* 21 */ ANIMTARGET_MATCOLOR_TEVK1G,
/* 22 */ ANIMTARGET_MATCOLOR_TEVK1B,
/* 23 */ ANIMTARGET_MATCOLOR_TEVK1A,
/* 24 */ ANIMTARGET_MATCOLOR_TEVK2R,
/* 25 */ ANIMTARGET_MATCOLOR_TEVK2G,
/* 26 */ ANIMTARGET_MATCOLOR_TEVK2B,
/* 27 */ ANIMTARGET_MATCOLOR_TEVK2A,
/* 28 */ ANIMTARGET_MATCOLOR_TEVK3R,
/* 29 */ ANIMTARGET_MATCOLOR_TEVK3G,
/* 30 */ ANIMTARGET_MATCOLOR_TEVK3B,
/* 31 */ ANIMTARGET_MATCOLOR_TEVK3A,
/* 32 */ ANIMTARGET_MATCOLOR_MAX
};
enum {
/* 0 */ ANIMTARGET_TEXSRT_TRANSX = 0,
/* 1 */ ANIMTARGET_TEXSRT_TRANSY,
/* 2 */ ANIMTARGET_TEXSRT_ROT,
/* 3 */ ANIMTARGET_TEXSRT_SCALEX,
/* 4 */ ANIMTARGET_TEXSRT_SCALEY,
/* 5 */ ANIMTARGET_TEXSRT_MAX
};
enum {
/* 0 */ ANIMTARGET_TEXPATTURN_IMAGE = 0,
/* 1 */ ANIMTARGET_TEXPATTURN_MAX
};
enum {
/* 0 */ ANIMCURVE_NONE = 0,
/* 1 */ ANIMCURVE_STEP,
/* 2 */ ANIMCURVE_HERMITE,
/* 3 */ ANIMCURVE_MAX
};
class AnimTransform {
public:
AnimTransform();
/* 0x08 */ virtual ~AnimTransform();
/* 0x0C */ virtual void SetResource(const res::AnimationBlock* pRes,
ResourceAccessor* pResAccessor) = 0;
/* 0x10 */ virtual void Bind(Pane* pane, bool bRecursive) = 0;
/* 0x14 */ virtual void Bind(Material* pMaterial) = 0;
/* 0x18 */ virtual void Animate(u32 idx, Pane* pane) = 0;
/* 0x1C */ virtual void Animate(u32 idx, Material* pMaterial) = 0;
f32 GetFrameMax() const { return GetFrameSize(); }
u16 GetFrameSize() const;
void SetFrame(f32 frame) { mFrame = frame; }
bool IsLoopData() const;
/* 0x00 (vtable) */
/* 0x04 */ ut::LinkListNode mLink;
protected:
/* 0x0C */ const res::AnimationBlock* mpRes;
/* 0x10 */ f32 mFrame;
}; // size = 0x14
typedef ut::LinkList<AnimTransform, offsetof(AnimTransform, mLink)> AnimTransformList;
class AnimationLink {
public:
AnimationLink() : mLink(), mbDisable(false) { Reset(); }
~AnimationLink() {}
AnimTransform* GetAnimTransform() const { return mAnimTrans; }
u16 GetIndex() const { return mIdx; }
bool IsEnable() const { return !mbDisable; }
void SetEnable(bool bEnable) { mbDisable = !bEnable; }
void Reset() { SetAnimTransform(NULL, 0); }
void SetAnimTransform(AnimTransform* animTrans, u16 idx) {
mAnimTrans = animTrans;
mIdx = idx;
}
/* 0x00 */ ut::LinkListNode mLink;
private:
/* 0x08 */ AnimTransform* mAnimTrans;
/* 0x0C */ u16 mIdx;
/* 0x0E */ bool mbDisable;
}; // size = 0x10
typedef ut::LinkList<AnimationLink, offsetof(AnimationLink, mLink)> AnimationLinkList;
class AnimTransformBasic : public AnimTransform {
public:
AnimTransformBasic();
/* 0x08 */ virtual ~AnimTransformBasic();
/* 0x0C */ virtual void SetResource(const res::AnimationBlock* pRes,
ResourceAccessor* pResAccessor);
/* 0x10 */ virtual void Bind(Pane* pane, bool bRecursive);
/* 0x14 */ virtual void Bind(Material* pMaterial);
/* 0x18 */ virtual void Animate(u32 idx, Pane* pane);
/* 0x1C */ virtual void Animate(u32 idx, Material* pMaterial);
private:
/* 0x00 (base) */
/* 0x14 */ void** mpFileResAry;
/* 0x18 */ AnimationLink* mAnimLinkAry;
/* 0x1C */ u16 mAnimLinkNum;
}; // size = 0x20
namespace detail {
AnimationLink* FindAnimationLink(AnimationLinkList* animList, AnimTransform* animTrans);
}
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,98 @@
#ifndef NW4HBM_LYT_ARC_RESOURCE_ACCESSOR_H
#define NW4HBM_LYT_ARC_RESOURCE_ACCESSOR_H
#include "revolution/types.h"
#include "revolution/arc.h"
#include "../ut/Font.h"
#include "../ut/LinkList.h"
#include "resourceAccessor.h"
namespace nw4hbm {
namespace lyt {
static const int RESOURCE_NAME_MAX = 128;
class FontRefLink {
public:
FontRefLink();
void Set(const char* name, ut::Font* pFont);
const char* GetFontName() const { return mFontName; }
ut::Font* GetFont() const { return mpFont; }
/* 0x00 */ ut::LinkListNode mLink;
protected:
/* 0x08 */ char mFontName[RESOURCE_NAME_MAX];
/* 0x88 */ ut::Font* mpFont;
};
typedef ut::LinkList<FontRefLink, offsetof(FontRefLink, mLink)> FontRefLinkList;
class ArcResourceLink {
public:
ArcResourceLink() {}
bool Set(void* archiveStart, const char* resRootDirectory);
char* GetResRootDir() { return mResRootDir; }
ARCHandle* GetArcHandle() { return &mArcHandle; }
/* 0x00 */ ut::LinkListNode mLink;
protected:
/* 0x08 */ ARCHandle mArcHandle;
/* 0x24 */ char mResRootDir[RESOURCE_NAME_MAX];
};
typedef ut::LinkList<ArcResourceLink, offsetof(ArcResourceLink, mLink)> ArcResourceLinkList;
class ArcResourceAccessor : public ResourceAccessor {
public:
ArcResourceAccessor();
/* 0x08 */ virtual ~ArcResourceAccessor() {}
/* 0x0C */ virtual void* GetResource(u32 resType, const char* name, u32* pSize = NULL);
/* 0x10 */ virtual ut::Font* GetFont(const char* name);
bool Attach(void* archiveStart, const char* resourceRootDirectory);
bool IsAttached(void) { return this->mArcBuf != NULL; }
private:
/* 0x00 (base) */
/* 0x04 */ ARCHandle mArcHandle;
/* 0x20 */ void* mArcBuf;
/* 0x24 */ FontRefLinkList mFontList;
/* 0x30 */ char mResRootDir[RESOURCE_NAME_MAX];
};
class MultiArcResourceAccessor : public ResourceAccessor {
public:
MultiArcResourceAccessor();
/* 0x08 */ virtual ~MultiArcResourceAccessor();
/* 0x0C */ virtual void* GetResource(u32 resType, const char* name, u32* pSize = NULL);
/* 0x10 */ virtual ut::Font* GetFont(const char* name);
void Attach(ArcResourceLink* pLink);
void DetachAll() { reinterpret_cast<ut::detail::LinkListImpl*>(&mArcList)->Clear(); }
void RegistFont(FontRefLink* pLink);
protected:
/* 0x00 (base) */
/* 0x04 */ ArcResourceLinkList mArcList;
/* 0x10 */ FontRefLinkList mFontList;
};
namespace detail {
ut::Font* FindFont(FontRefLinkList* pFontRefList, const char* name);
}
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,21 @@
#ifndef NW4HBM_LYT_BOUNDING_H
#define NW4HBM_LYT_BOUNDING_H
#include "pane.h"
namespace nw4hbm {
namespace lyt {
class Bounding : public Pane {
public:
Bounding(const res::Bounding* pBlock, const ResBlockSet& resBlockSet);
/* 0x08 */ virtual ~Bounding();
/* 0x0C */ NW4HBM_UT_RUNTIME_TYPEINFO;
/* 0x18 */ virtual void DrawSelf(const DrawInfo& drawInfo);
};
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,108 @@
#ifndef NW4HBM_LYT_COMMON_H
#define NW4HBM_LYT_COMMON_H
#include "revolution/tpl.h"
#include "revolution/types.h"
#include "../ut/Color.h"
#include "animation.h"
#include "resources.h"
#include "../db/assert.h"
namespace nw4hbm {
namespace lyt {
namespace detail {
typedef math::VEC2 TexCoords[4];
class TexCoordAry {
public:
TexCoordAry();
u8 GetSize() const { return mNum; }
const TexCoords* GetArray() const { return mpData; }
void SetSize(u8 num);
bool IsEmpty() const { return mCap == 0; }
void Reserve(u8 num);
void Free();
void Copy(const void* pResTexCoord, u8 texCoordNum);
void SetCoord(u32 idx, const math::VEC2* vec);
void GetCoord(u32 idx, math::VEC2* vec) const;
private:
/* 0x00 */ u8 mCap;
/* 0x01 */ u8 mNum;
/* 0x04 */ TexCoords* mpData;
};
bool EqualsPaneName(const char* name1, const char* name2);
bool EqualsMaterialName(const char* name1, const char* name2);
bool TestFileHeader(const res::BinaryFileHeader& fileHeader);
bool TestFileHeader(const res::BinaryFileHeader& fileHeader, u32 testSig);
bool IsModulateVertexColor(ut::Color* vtxColors, u8 glbAlpha);
ut::Color MultipleAlpha(const ut::Color col, u8 alpha);
void MultipleAlpha(ut::Color* dst, const ut::Color* src, u8 alpha);
void SetVertexFormat(bool bModulate, u8 texCoordNum);
void DrawQuad(const math::VEC2& basePt, const Size& size, u8 texCoordNum,
const TexCoords* texCoords, const ut::Color* vtxColors);
void DrawQuad(const math::VEC2& basePt, const Size& size, u8 texCoordNum,
const TexCoords* texCoords, const ut::Color* vtxColors, u8 alpha);
void DrawLine(const math::VEC2& pos, const Size& size, ut::Color color);
void InitGXTexObjFromTPL(GXTexObj* to, TPLPalette* pal, u32 id);
inline s32 GetSignatureInt(const char* sig) {
return *reinterpret_cast<const s32*>(sig);
}
inline const char* GetStrTableStr(const void* pStrTable, int index) {
const u32* offsets = static_cast<const u32*>(pStrTable);
const char* stringPool = static_cast<const char*>(pStrTable);
return &stringPool[offsets[index]];
}
inline u8 GetVtxColorElement(const ut::Color* cols, u32 idx) {
NW4HBM_ASSERT(199, idx < ANIMTARGET_VERTEXCOLOR_MAX);
return reinterpret_cast<const u8*>(cols + idx / 4)[idx % 4];
}
inline void SetVtxColorElement(ut::Color* cols, u32 idx, u8 value) {
NW4HBM_ASSERT(212, idx < ANIMTARGET_VERTEXCOLOR_MAX);
reinterpret_cast<u8*>(cols + idx / 4)[idx % 4] = value;
}
inline u8 GetHorizontalPosition(u8 var) {
return var % HORIZONTALPOSITION_MAX;
}
inline u8 GetVerticalPosition(u8 var) {
return var / VERTICALPOSITION_MAX;
}
inline void SetHorizontalPosition(u8* pVar, u8 newVal) {
*pVar = GetVerticalPosition(*pVar) * HORIZONTALPOSITION_MAX + newVal;
}
inline void SetVerticalPosition(u8* pVar, u8 newVal) {
*pVar = newVal * VERTICALPOSITION_MAX + GetHorizontalPosition(*pVar);
}
} // namespace detail
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,67 @@
#ifndef NW4HBM_LYT_DRAW_INFO_H
#define NW4HBM_LYT_DRAW_INFO_H
#include <revolution/gx.h>
#include "../math/types.h"
#include "../ut/Rect.h"
namespace nw4hbm {
namespace lyt {
class DrawInfo {
public:
DrawInfo();
/* 0x08 */ virtual ~DrawInfo();
void SetViewRect(const ut::Rect& rect) { mViewRect = rect; }
const math::MTX34& GetViewMtx() const { return mViewMtx; }
void SetViewMtx(const math::MTX34& value) { mViewMtx = value; }
const math::VEC2& GetLocationAdjustScale() const { return mLocationAdjustScale; }
void SetLocationAdjustScale(const math::VEC2& scale) { mLocationAdjustScale = scale; }
bool IsMultipleViewMtxOnDraw() const { return mFlag.mulViewDraw; }
void SetMultipleViewMtxOnDraw(bool bEnable) { mFlag.mulViewDraw = bEnable; }
bool IsInfluencedAlpha() const { return mFlag.influencedAlpha; }
void SetInfluencedAlpha(bool bEnable) { mFlag.influencedAlpha = bEnable; }
bool IsLocationAdjust() const { return mFlag.locationAdjust; }
void SetLocationAdjust(bool bEnable) { mFlag.locationAdjust = bEnable; }
bool IsInvisiblePaneCalculateMtx() const { return mFlag.invisiblePaneCalculateMtx; }
void SetInvisiblePaneCalculateMtx(bool bEnable) {
mFlag.invisiblePaneCalculateMtx = bEnable;
}
bool IsDebugDrawMode() const { return mFlag.debugDrawMode; }
void SetDebugDrawMode(bool bEnable) { mFlag.debugDrawMode = bEnable; }
bool IsYAxisUp() const { return mViewRect.bottom - mViewRect.top < 0.0f; }
f32 GetGlobalAlpha() const { return mGlobalAlpha; }
void SetGlobalAlpha(f32 alpha) { mGlobalAlpha = alpha; }
protected:
/* 0x00 (vtable) */
/* 0x04 */ math::MTX34 mViewMtx;
/* 0x34 */ ut::Rect mViewRect;
/* 0x44 */ math::VEC2 mLocationAdjustScale;
/* 0x4C */ f32 mGlobalAlpha;
/* 0x50 */ struct {
u8 mulViewDraw : 1; // 10000000
u8 influencedAlpha : 1; // 01000000
u8 locationAdjust : 1; // 00100000
u8 invisiblePaneCalculateMtx : 1; // 00010000
u8 debugDrawMode : 1; // 00001000
} mFlag;
};
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,65 @@
#ifndef NW4HBM_LYT_GROUP_H
#define NW4HBM_LYT_GROUP_H
#include <revolution/types.h>
#include "pane.h"
#include "../ut/LinkList.h"
namespace nw4hbm {
namespace lyt {
namespace detail {
typedef struct PaneLink {
ut::LinkListNode mLink;
/* 0x08 */ Pane* mTarget;
} PaneLink;
} // namespace detail
typedef ut::LinkList<detail::PaneLink, offsetof(detail::PaneLink, mLink)> PaneLinkList;
class Group {
public:
Group();
Group(const res::Group* pResGroup, Pane* pRootPane);
/* 0x08 */ virtual ~Group();
const char* GetName() const { return mName; }
bool IsUserAllocated() const { return mbUserAllocated; }
PaneLinkList& GetPaneList() { return mPaneLinkList; };
void Init();
void AppendPane(Pane* pane);
/* 0x00 (vtable) */
/* 0x04 */ ut::LinkListNode mLink;
protected:
/* 0x0C */ PaneLinkList mPaneLinkList;
/* 0x18 */ char mName[16];
/* 0x29 */ bool mbUserAllocated;
/* 0x2A */ u8 mPadding[2];
};
typedef ut::LinkList<Group, offsetof(Group, mLink)> GroupList;
class GroupContainer {
public:
GroupContainer() {}
~GroupContainer();
GroupList& GetGroupList() { return mGroupList; }
void AppendGroup(Group* pGroup);
Group* FindGroupByName(const char* findName);
protected:
/* 0x00 */ GroupList mGroupList;
};
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,68 @@
#ifndef NW4HBM_LYT_LAYOUT_H
#define NW4HBM_LYT_LAYOUT_H
#include <revolution/mem.h>
#include <revolution/types.h>
#include "animation.h"
#include "drawInfo.h"
#include "group.h"
#include "lyt_types.h"
#include "resourceAccessor.h"
#include "../ut/LinkList.h"
#include "../ut/TagProcessorBase.h"
#include "../ut/WideTagProcessor.h"
#include "macros.h"
namespace nw4hbm {
namespace lyt {
class Layout {
public:
Layout();
/* 0x08 */ virtual ~Layout();
/* 0x0C */ virtual bool Build(const void* lytResBuf, ResourceAccessor* pResAcsr);
/* 0x10 */ virtual AnimTransform* CreateAnimTransform(const void* anmResBuf,
ResourceAccessor* pResAcsr);
/* 0x14 */ virtual void BindAnimation(AnimTransform* animTrans);
/* 0x18 */ virtual void UnbindAnimation(AnimTransform* animTrans);
/* 0x1C */ virtual void UnbindAllAnimation();
/* 0x20 */ virtual void SetAnimationEnable(AnimTransform* animTrans,
bool bEnable = true);
/* 0x24 */ virtual void CalculateMtx(const DrawInfo& drawInfo);
/* 0x28 */ virtual void Draw(const DrawInfo& drawInfo);
/* 0x2C */ virtual void Animate(u32 option = 0);
/* 0x30 */ virtual void SetTagProcessor(ut::WideTagProcessor* pTagProcessor) NO_INLINE;
const ut::Rect GetLayoutRect() const;
Pane* GetRootPane() const { return mpRootPane; }
GroupContainer* GetGroupContainer() const { return mpGroupContainer; }
static MEMAllocator* GetAllocator() { return mspAllocator; }
static void SetAllocator(MEMAllocator* allocator) { mspAllocator = allocator; }
static void* AllocMemory(u32 size) { return MEMAllocFromAllocator(mspAllocator, size); }
static void FreeMemory(void* ptr) { MEMFreeToAllocator(mspAllocator, ptr); }
static Pane* BuildPaneObj(s32 kind, const void* dataPtr,
const ResBlockSet& resBlockSet) NO_INLINE;
private:
/* 0x00 (vtable) */
/* 0x04 */ AnimTransformList mAnimTransList;
/* 0x10 */ Pane* mpRootPane;
/* 0x14 */ GroupContainer* mpGroupContainer;
/* 0x18 */ Size mLayoutSize;
/* 0x20 */ u8 mOriginType;
static MEMAllocator* mspAllocator;
};
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,466 @@
#include "animation.h"
#include "common.h"
#include "layout.h"
#include "pane.h"
#include "new.h"
#include <cstring.h>
namespace {
// pretend this is nw4hbm::lyt
using namespace nw4hbm;
using namespace nw4hbm::lyt;
inline bool RIsSame(const f32 a, const f32 b, const f32 tolerance) {
f32 c = a - b;
return -tolerance < c && c < tolerance;
}
u16 GetStepCurveValue(f32 frame, const res::StepKey* keyArray, u32 keySize);
f32 GetHermiteCurveValue(f32 frame, const res::HermiteKey* keyArray, u32 keySize);
void AnimatePainSRT(Pane* pPane, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame);
void AnimateVisibility(Pane* pPane, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame);
void AnimateVertexColor(Pane* pPane, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame);
void AnimateMaterialColor(Material* pMaterial, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame);
void AnimateTextureSRT(Material* pMaterial, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame);
void AnimateTexturePattern(Material* pMaterial, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame, void** tpls);
void AnimateIndTexSRT(Material* pMaterial, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame);
} // namespace
namespace {
u16 GetStepCurveValue(f32 frame, const res::StepKey* keyArray, u32 keySize) {
if (keySize == 1 || frame <= keyArray[0].frame) {
return keyArray[0].value;
}
if (frame >= keyArray[keySize - 1].frame) {
return keyArray[keySize - 1].value;
}
int ikeyL = 0;
int ikeyR = keySize - 1;
while (ikeyL != ikeyR - 1 && ikeyL != ikeyR) {
int ikeyCenter = (ikeyL + ikeyR) / 2;
const res::StepKey& centerKey = keyArray[ikeyCenter];
if (frame < centerKey.frame) {
ikeyR = ikeyCenter;
} else {
ikeyL = ikeyCenter;
}
}
if (RIsSame(frame, keyArray[ikeyR].frame, 0.001f)) {
return keyArray[ikeyR].value;
} else {
return keyArray[ikeyL].value;
}
}
f32 GetHermiteCurveValue(f32 frame, const res::HermiteKey* keyArray, u32 keySize) {
if (keySize == 1 || frame <= keyArray[0].frame) {
return keyArray[0].value;
}
if (frame >= keyArray[keySize - 1].frame) {
return keyArray[keySize - 1].value;
}
int ikeyL = 0;
int ikeyR = keySize - 1;
while (ikeyL != ikeyR - 1 && ikeyL != ikeyR) {
int ikeyCenter = (ikeyL + ikeyR) / 2;
if (frame <= keyArray[ikeyCenter].frame) {
ikeyR = ikeyCenter;
} else {
ikeyL = ikeyCenter;
}
}
const res::HermiteKey& key0 = keyArray[ikeyL];
const res::HermiteKey& key1 = keyArray[ikeyR];
if (RIsSame(frame, key1.frame, 0.001f)) {
if (ikeyR < keySize - 1 && keyArray[ikeyR + 1].frame == key1.frame) {
return keyArray[ikeyR + 1].value;
} else {
return key1.value;
}
}
f32 t1 = frame - key0.frame;
f32 t2 = 1.0f / (key1.frame - key0.frame);
f32 v0 = key0.value;
f32 v1 = key1.value;
f32 s0 = key0.slope;
f32 s1 = key1.slope;
f32 t1t1t2 = t1 * t1 * t2;
f32 t1t1t2t2 = t1t1t2 * t2;
f32 t1t1t1t2t2 = t1 * t1t1t2t2;
f32 t1t1t1t2t2t2 = t1t1t1t2t2 * t2;
// Does anyone know what this means? Because I don't
// clang-format off
return v0 * (( 2.0f * t1t1t1t2t2t2) - (3.0f * t1t1t2t2) + 1.0f)
+ v1 * ((-2.0f * t1t1t1t2t2t2) + (3.0f * t1t1t2t2) )
+ s0 * (( t1t1t1t2t2 ) - (2.0f * t1t1t2 ) + t1 )
+ s1 * (( t1t1t1t2t2 ) - ( t1t1t2 ) );
// clang-format on
}
void AnimatePainSRT(Pane* pPane, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame) {
for (int i = 0; i < pAnimInfo->num; i++) {
const res::AnimationTarget* pAnimTarget =
detail::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
NW4HBM_ASSERT(197, pAnimTarget->target < ANIMTARGET_PANE_MAX);
NW4HBM_ASSERT(198, pAnimTarget->curveType == ANIMCURVE_HERMITE);
const res::HermiteKey* keys =
detail::ConvertOffsToPtr<res::HermiteKey>(pAnimTarget, pAnimTarget->keysOffset);
pPane->SetSRTElement(pAnimTarget->target,
GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum));
}
}
void AnimateVisibility(Pane* pPane, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame) {
for (int i = 0; i < pAnimInfo->num; i++) {
const res::AnimationTarget* pAnimTarget =
detail::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
NW4HBM_ASSERT(217, pAnimTarget->target < ANIMTARGET_PANE_MAX);
NW4HBM_ASSERT(218, pAnimTarget->curveType == ANIMCURVE_STEP);
const res::StepKey* keys =
detail::ConvertOffsToPtr<res::StepKey>(pAnimTarget, pAnimTarget->keysOffset);
pPane->SetVisible(GetStepCurveValue(frame, keys, pAnimTarget->keyNum) != 0);
}
}
void AnimateVertexColor(Pane* pPane, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame) {
for (int i = 0; i < pAnimInfo->num; i++) {
const res::AnimationTarget* pAnimTarget =
detail::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
NW4HBM_ASSERT(237, pAnimTarget->target < ANIMTARGET_PANE_COLOR_MAX);
NW4HBM_ASSERT(238, pAnimTarget->curveType == ANIMCURVE_HERMITE);
const res::HermiteKey* keys =
detail::ConvertOffsToPtr<res::HermiteKey>(pAnimTarget, pAnimTarget->keysOffset);
f32 value = GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum);
value += 0.5f;
u8 u8Val;
OSf32tou8(&value, &u8Val);
// What
pPane->SetColorElement(pAnimTarget->target, *static_cast<u8*>(&u8Val));
}
}
inline void AnimateMaterialColor(Material* pMaterial, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame) {
for (int i = 0; i < pAnimInfo->num; i++) {
const res::AnimationTarget* pAnimTarget =
detail::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
NW4HBM_ASSERT(262, pAnimTarget->target < ANIMTARGET_MATCOLOR_MAX);
NW4HBM_ASSERT(263, pAnimTarget->curveType == ANIMCURVE_HERMITE);
const res::HermiteKey* keys =
detail::ConvertOffsToPtr<res::HermiteKey>(pAnimTarget, pAnimTarget->keysOffset);
f32 value = GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum);
value += 0.5f;
s16 s16Val;
OSf32tos16(&value, &s16Val);
s16Val = ut::Min<s16>(ut::Max<s16>(s16Val, -1024), 1023);
pMaterial->SetColorElement(pAnimTarget->target, s16Val);
}
}
void AnimateTextureSRT(Material* pMaterial, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame) {
for (int i = 0; i < pAnimInfo->num; i++) {
const res::AnimationTarget* pAnimTarget =
detail::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
NW4HBM_ASSERT(287, pAnimTarget->id < TexMtxMax);
if (pAnimTarget->id < pMaterial->GetTexSRTCap()) {
NW4HBM_ASSERT(290, pAnimTarget->target < ANIMTARGET_TEXSRT_MAX);
NW4HBM_ASSERT(291, pAnimTarget->curveType == ANIMCURVE_HERMITE);
const res::HermiteKey* keys =
detail::ConvertOffsToPtr<res::HermiteKey>(pAnimTarget, pAnimTarget->keysOffset);
pMaterial->SetTexSRTElement(pAnimTarget->id, pAnimTarget->target,
GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum));
}
}
}
void AnimateTexturePattern(Material* pMaterial, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame, void** tpls) {
for (int j = 0; j < pAnimInfo->num; j++) {
const res::AnimationTarget* pAnimTarget =
detail::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[j]);
NW4HBM_ASSERT(311, pAnimTarget->id < GX_MAX_TEXMAP);
if (pAnimTarget->id < pMaterial->GetTextureNum()) {
NW4HBM_ASSERT(314, pAnimTarget->curveType == ANIMCURVE_STEP);
if (!pAnimTarget->target) {
const res::StepKey* keys = detail::ConvertOffsToPtr<res::StepKey>(
pAnimTarget, pAnimTarget->keysOffset);
u16 fileIdx = GetStepCurveValue(frame, keys, pAnimTarget->keyNum);
pMaterial->SetTextureNoWrap(pAnimTarget->id,
static_cast<TPLPalette*>(tpls[fileIdx]));
}
}
}
}
void AnimateIndTexSRT(Material* pMaterial, const res::AnimationInfo* pAnimInfo,
const u32* animTargetOffsets, f32 frame) {
for (int i = 0; i < pAnimInfo->num; i++) {
const res::AnimationTarget* pAnimTarget =
detail::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
NW4HBM_ASSERT(337, pAnimTarget->id < IndTexMtxMax);
if (pAnimTarget->id < pMaterial->GetIndTexSRTCap()) {
NW4HBM_ASSERT(340, pAnimTarget->target < ANIMTARGET_TEXSRT_MAX);
NW4HBM_ASSERT(341, pAnimTarget->curveType == ANIMCURVE_HERMITE);
const res::HermiteKey* keys =
detail::ConvertOffsToPtr<res::HermiteKey>(pAnimTarget, pAnimTarget->keysOffset);
pMaterial->SetIndTexSRTElement(
pAnimTarget->id, pAnimTarget->target,
GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum));
}
}
}
} // unnamed namespace
namespace nw4hbm {
namespace lyt {
AnimTransform::AnimTransform() : mLink(), mpRes(NULL), mFrame(0.0f) {}
AnimTransform::~AnimTransform() {}
u16 AnimTransform::GetFrameSize() const {
return mpRes->frameSize;
}
AnimTransformBasic::AnimTransformBasic()
: mpFileResAry(NULL), mAnimLinkAry(NULL), mAnimLinkNum(0) {}
AnimTransformBasic::~AnimTransformBasic() {
if (mAnimLinkAry) {
Layout::FreeMemory(mAnimLinkAry);
}
if (mpFileResAry) {
Layout::FreeMemory(mpFileResAry);
}
}
void AnimTransformBasic::SetResource(const res::AnimationBlock* pRes,
ResourceAccessor* pResAccessor) {
NW4HBM_ASSERT(422, mpFileResAry == 0);
NW4HBM_ASSERT(423, mAnimLinkAry == 0);
mpRes = pRes;
mpFileResAry = NULL;
if (pRes->fileNum) {
mpFileResAry =
static_cast<void**>(Layout::AllocMemory(sizeof(*mpFileResAry) * pRes->fileNum));
if (mpFileResAry) {
const u32* fileNameOffsets =
detail::ConvertOffsToPtr<u32>(mpRes, sizeof(*mpRes));
for (int i = 0; i < mpRes->fileNum; i++) {
mpFileResAry[i] = pResAccessor->GetResource(
'timg', detail::GetStrTableStr(fileNameOffsets, i), 0);
}
}
}
mAnimLinkAry = static_cast<AnimationLink*>(
Layout::AllocMemory(sizeof(*mAnimLinkAry) * pRes->animContNum));
if (mAnimLinkAry) {
mAnimLinkNum = pRes->animContNum;
std::memset(mAnimLinkAry, 0, sizeof(*mAnimLinkAry) * pRes->animContNum);
for (u16 i = 0; i < pRes->animContNum; i++) {
new (&mAnimLinkAry[i]) AnimationLink();
}
}
}
void AnimTransformBasic::Bind(Pane* pPane, bool bRecursive) {
const u32* animContOffsets =
detail::ConvertOffsToPtr<u32>(mpRes, mpRes->animContOffsetsOffset);
for (u16 i = 0; i < mpRes->animContNum; i++) {
const res::AnimationContent* pAnimCont =
detail::ConvertOffsToPtr<res::AnimationContent>(mpRes, animContOffsets[i]);
if (pAnimCont->type == res::AnimationContent::ACType_Pane) {
Pane* pFindPane = pPane->FindPaneByName(pAnimCont->name, bRecursive);
if (pFindPane) {
mAnimLinkAry[i].SetAnimTransform(this, i);
pFindPane->AddAnimationLink(&mAnimLinkAry[i]);
}
} else {
Material* pFindMat = pPane->FindMaterialByName(pAnimCont->name, bRecursive);
if (pFindMat) {
mAnimLinkAry[i].SetAnimTransform(this, i);
pFindMat->AddAnimationLink(&mAnimLinkAry[i]);
}
}
}
}
void AnimTransformBasic::Bind(Material* pMaterial) {
const u32* animContOffsets =
detail::ConvertOffsToPtr<u32>(mpRes, mpRes->animContOffsetsOffset);
for (u16 i = 0; i < mpRes->animContNum; i++) {
const res::AnimationContent* pAnimCont =
detail::ConvertOffsToPtr<res::AnimationContent>(mpRes, animContOffsets[i]);
if (pAnimCont->type != res::AnimationContent::ACType_Material) {
continue;
}
if (detail::EqualsMaterialName(pMaterial->GetName(), pAnimCont->name)) {
mAnimLinkAry[i].SetAnimTransform(this, i);
pMaterial->AddAnimationLink(&mAnimLinkAry[i]);
}
}
}
void AnimTransformBasic::Animate(u32 idx, Pane* pPane) {
u32 animContOffsets =
detail::ConvertOffsToPtr<u32>(mpRes, mpRes->animContOffsetsOffset)[idx];
const res::AnimationContent* pAnimCont =
detail::ConvertOffsToPtr<res::AnimationContent>(mpRes, animContOffsets);
const u32* animInfoOffsets =
detail::ConvertOffsToPtr<u32>(pAnimCont, sizeof(*pAnimCont));
for (int i = 0; i < pAnimCont->num; i++) {
const res::AnimationInfo* pAnimInfo =
detail::ConvertOffsToPtr<res::AnimationInfo>(pAnimCont, animInfoOffsets[i]);
const u32* animTargetOffsets =
detail::ConvertOffsToPtr<u32>(pAnimInfo, sizeof(*pAnimInfo));
switch (pAnimInfo->kind) {
case res::AnimationInfo::ANIM_INFO_PANE_PAIN_SRT:
AnimatePainSRT(pPane, pAnimInfo, animTargetOffsets, mFrame);
break;
case res::AnimationInfo::ANIM_INFO_PANE_VISIBILITY:
AnimateVisibility(pPane, pAnimInfo, animTargetOffsets, mFrame);
break;
case res::AnimationInfo::ANIM_INFO_PANE_VERTEX_COLOR:
AnimateVertexColor(pPane, pAnimInfo, animTargetOffsets, mFrame);
break;
}
}
}
void AnimTransformBasic::Animate(u32 idx, Material* pMaterial) {
u32 animContOffsets =
detail::ConvertOffsToPtr<u32>(mpRes, mpRes->animContOffsetsOffset)[idx];
const res::AnimationContent* pAnimCont =
detail::ConvertOffsToPtr<res::AnimationContent>(mpRes, animContOffsets);
const u32* animInfoOffsets =
detail::ConvertOffsToPtr<u32>(pAnimCont, sizeof(*pAnimCont));
for (int i = 0; i < pAnimCont->num; i++) {
const res::AnimationInfo* pAnimInfo =
detail::ConvertOffsToPtr<res::AnimationInfo>(pAnimCont, animInfoOffsets[i]);
const u32* animTargetOffsets =
detail::ConvertOffsToPtr<u32>(pAnimInfo, sizeof(*pAnimInfo));
switch (pAnimInfo->kind) {
case res::AnimationInfo::ANIM_INFO_MATERIAL_COLOR:
AnimateMaterialColor(pMaterial, pAnimInfo, animTargetOffsets, mFrame);
break;
case res::AnimationInfo::ANIM_INFO_MATERIAL_TEXTURE_SRT:
AnimateTextureSRT(pMaterial, pAnimInfo, animTargetOffsets, mFrame);
break;
case res::AnimationInfo::ANIM_INFO_MATERIAL_TEXTURE_PATTERN:
if (mpFileResAry) {
AnimateTexturePattern(pMaterial, pAnimInfo, animTargetOffsets, mFrame,
mpFileResAry);
}
break;
case res::AnimationInfo::ANIM_INFO_MATERIAL_IND_TEX_SRT:
AnimateIndTexSRT(pMaterial, pAnimInfo, animTargetOffsets, mFrame);
break;
}
}
}
AnimationLink* detail::FindAnimationLink(AnimationLinkList* pAnimList,
AnimTransform* pAnimTrans) {
NW4HBM_ASSERT_CHECK_NULL(559, pAnimList);
NW4HBM_ASSERT_CHECK_NULL(560, pAnimTrans);
for (AnimationLinkList::Iterator it = pAnimList->GetBeginIter();
it != pAnimList->GetEndIter(); it++)
{
if (pAnimTrans == it->GetAnimTransform()) {
return &(*it);
}
}
return NULL;
}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,197 @@
#include "arcResourceAccessor.h"
#include <revolution/arc.h>
#include "string.h"
namespace {
s32 FindNameResource(ARCHandle* pArcHandle, const char* resName) NO_INLINE {
s32 entryNum = -1;
ARCDir dir;
BOOL bSuccess = ARCOpenDir(pArcHandle, ".", &dir);
NW4HBM_ASSERT(48, bSuccess);
ARCDirEntry dirEntry;
while (ARCReadDir(&dir, &dirEntry)) {
if (dirEntry.isDir != 0) {
bSuccess = ARCChangeDir(pArcHandle, dirEntry.name);
NW4HBM_ASSERT(57, bSuccess);
entryNum = FindNameResource(pArcHandle, resName);
bSuccess = ARCChangeDir(pArcHandle, "..");
NW4HBM_ASSERT(60, bSuccess);
if (entryNum != -1) {
break;
}
} else if (stricmp(resName, dirEntry.name) == 0) {
entryNum = dirEntry.entryNum;
break;
}
}
bSuccess = ARCCloseDir(&dir);
NW4HBM_ASSERT(77, bSuccess);
return entryNum;
}
void* GetResourceSub(ARCHandle* pArcHandle, const char* resRootDir, u32 resType,
const char* name, u32* pSize) {
s32 entryNum = -1;
if (ARCConvertPathToEntrynum(pArcHandle, resRootDir) != -1 &&
ARCChangeDir(pArcHandle, resRootDir))
{
if (!resType) {
entryNum = FindNameResource(pArcHandle, name);
} else {
char resTypeStr[5];
resTypeStr[0] = resType >> 24;
resTypeStr[1] = resType >> 16;
resTypeStr[2] = resType >> 8;
resTypeStr[3] = resType;
resTypeStr[4] = '\0';
if (ARCConvertPathToEntrynum(pArcHandle, resTypeStr) != -1 &&
ARCChangeDir(pArcHandle, resTypeStr))
{
entryNum = ARCConvertPathToEntrynum(pArcHandle, name);
BOOL bSuccess = ARCChangeDir(pArcHandle, "..");
NW4HBM_ASSERT(117, bSuccess);
}
}
BOOL bSuccess = ARCChangeDir(pArcHandle, "..");
NW4HBM_ASSERT(123, bSuccess);
}
if (entryNum != -1) {
ARCFileInfo arcFileInfo;
BOOL bSuccess = ARCFastOpen(pArcHandle, entryNum, &arcFileInfo);
NW4HBM_ASSERT(131, bSuccess);
void* resPtr = ARCGetStartAddrInMem(&arcFileInfo);
if (pSize) {
*pSize = ARCGetLength(&arcFileInfo);
}
ARCClose(&arcFileInfo);
return resPtr;
}
return NULL;
}
} // namespace
namespace nw4hbm {
namespace lyt {
ut::Font* detail::FindFont(FontRefLinkList* pFontRefList, const char* name) {
for (FontRefLinkList::Iterator it = pFontRefList->GetBeginIter();
it != pFontRefList->GetEndIter(); it++)
{
if (strcmp(name, it->GetFontName()) == 0) {
return it->GetFont();
}
}
return NULL;
}
FontRefLink::FontRefLink() : mpFont(NULL) {}
void FontRefLink::Set(const char* name, ut::Font* pFont) {
strcpy(mFontName, name);
mpFont = pFont;
}
ArcResourceAccessor::ArcResourceAccessor() : mArcBuf(NULL) {}
void dummyString() {
OSReport("NW4HBM:Failed assertion std::strlen(name) < FONTNAMEBUF_MAX");
}
bool ArcResourceAccessor::Attach(void* archiveStart, const char* resourceRootDirectory) {
// clang-format off
NW4HBM_ASSERT(220, ! IsAttached());
NW4HBM_ASSERT_CHECK_NULL(221, archiveStart);
NW4HBM_ASSERT_CHECK_NULL(222, resourceRootDirectory);
// clang-format on
BOOL bSuccess = ARCInitHandle(archiveStart, &mArcHandle);
if (!bSuccess) {
return false;
}
mArcBuf = archiveStart;
strncpy(mResRootDir, resourceRootDirectory, ARRAY_SIZE(mResRootDir) - 1);
mResRootDir[ARRAY_SIZE(mResRootDir) - 1] = '\0';
return true;
}
void dummyString2() {
OSReport("NW4HBM:Failed assertion IsAttached()");
OSReport("NW4HBM:Pointer must not be NULL (pLink)");
}
void* ArcResourceAccessor::GetResource(u32 resType, const char* name, u32* pSize) {
return GetResourceSub(&mArcHandle, mResRootDir, resType, name, pSize);
}
bool ArcResourceLink::Set(void* archiveStart, const char* resRootDirectory) {
BOOL bSuccess = ARCInitHandle(archiveStart, &mArcHandle);
if (!bSuccess) {
return false;
}
strncpy(mResRootDir, resRootDirectory, ARRAY_SIZE(mResRootDir) - 1);
mResRootDir[ARRAY_SIZE(mResRootDir) - 1] = '\0';
return true;
}
ut::Font* ArcResourceAccessor::GetFont(const char* name) {
return detail::FindFont(&mFontList, name);
}
MultiArcResourceAccessor::MultiArcResourceAccessor() {}
MultiArcResourceAccessor::~MultiArcResourceAccessor() {
DetachAll();
}
void MultiArcResourceAccessor::Attach(ArcResourceLink* pLink) {
mArcList.PushBack(pLink);
}
void* MultiArcResourceAccessor::GetResource(u32 resType, const char* name, u32* pSize) {
for (ArcResourceLinkList::Iterator it = mArcList.GetBeginIter();
it != mArcList.GetEndIter(); it++)
{
ARCHandle* pArcHandle = it->GetArcHandle();
if (void* resPtr =
GetResourceSub(pArcHandle, it->GetResRootDir(), resType, name, pSize))
{
return resPtr;
}
}
return NULL;
}
void MultiArcResourceAccessor::RegistFont(FontRefLink* pLink) {
mFontList.PushBack(pLink);
}
ut::Font* MultiArcResourceAccessor::GetFont(const char* name) {
return detail::FindFont(&mFontList, name);
}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,24 @@
#include "bounding.h"
#include "common.h"
#include "drawInfo.h"
#include "pane.h"
namespace nw4hbm {
namespace lyt {
NW4HBM_UT_GET_DERIVED_RUNTIME_TYPEINFO(Bounding, Pane);
Bounding::Bounding(const res::Bounding* pBlock, const ResBlockSet&) : Pane(pBlock) {}
Bounding::~Bounding() {}
void Bounding::DrawSelf(const DrawInfo& drawInfo) {
if (drawInfo.IsDebugDrawMode()) {
LoadMtx(drawInfo);
detail::DrawLine(GetVtxPos(), mSize, ut::Color(0x00ff00ff));
}
}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,279 @@
#include "common.h"
#include "layout.h"
#include <cstring.h>
namespace nw4hbm {
namespace lyt {
namespace detail {
// sizeof(Pane::mName) == 16
bool EqualsPaneName(const char* name1, const char* name2) {
return std::strncmp(name1, name2, 16) == 0;
}
// sizeof(Material::mName) == 20
bool EqualsMaterialName(const char* name1, const char* name2) {
return std::strncmp(name1, name2, 20) == 0;
}
// U+FEFF * BYTE ORDER MARK
bool TestFileHeader(const res::BinaryFileHeader& fileHeader) {
return fileHeader.byteOrder == 0xFEFF && fileHeader.version == 8;
}
bool TestFileHeader(const res::BinaryFileHeader& fileHeader, u32 testSig) {
return static_cast<u32>(GetSignatureInt(fileHeader.signature)) == testSig &&
TestFileHeader(fileHeader);
}
TexCoordAry::TexCoordAry() : mCap(0), mNum(0), mpData(NULL) {}
void TexCoordAry::Free() {
if (mpData) {
Layout::FreeMemory(mpData);
mpData = NULL;
mCap = 0;
mNum = 0;
}
}
void TexCoordAry::Reserve(u8 num) {
NW4HBM_ASSERT(93, num <= GX_MAX_TEXMAP);
if (mCap < num) {
Free();
mpData = static_cast<TexCoords*>(Layout::AllocMemory(sizeof(*mpData) * num));
if (mpData) {
mCap = num;
}
}
}
void TexCoordAry::SetSize(u8 num) {
if (!mpData) {
return;
}
if (num > mCap) {
return;
}
// clang-format off
static TexCoords texCoords =
{
math::VEC2(0.0f, 0.0f),
math::VEC2(1.0f, 0.0f),
math::VEC2(0.0f, 1.0f),
math::VEC2(1.0f, 1.0f)
};
// clang-format on
for (int j = mNum; j < num; j++) {
for (int i = 0; i < (int)ARRAY_SIZE(mpData[j]); i++) {
mpData[j][i] = texCoords[i];
}
}
mNum = num;
}
void TexCoordAry::Copy(const void* pResTexCoord, u8 texCoordNum) {
NW4HBM_ASSERT(161, texCoordNum <= mCap);
mNum = ut::Max(mNum, texCoordNum);
const TexCoords* src = static_cast<const TexCoords*>(pResTexCoord);
for (int j = 0; j < texCoordNum; j++) {
for (int i = 0; i < (int)ARRAY_SIZE(mpData[j]); i++) {
mpData[j][i] = src[j][i];
}
}
}
bool IsModulateVertexColor(ut::Color* vtxColors, u8 glbAlpha) {
if (glbAlpha != 0xff) {
return true;
}
if (vtxColors) {
if (vtxColors[0] != 0xffffffff || vtxColors[1] != 0xffffffff ||
vtxColors[2] != 0xffffffff || vtxColors[3] != 0xffffffff)
{
return true;
}
}
return false;
}
ut::Color MultipleAlpha(const ut::Color col, u8 alpha) {
ut::Color ret = col;
if (alpha != 0xff) {
ret.a = col.a * alpha / 255;
}
return ret;
}
void MultipleAlpha(ut::Color* dst, const ut::Color* src, u8 alpha) {
for (int i = 0; i < 4; i++) {
dst[i] = MultipleAlpha(src[i], alpha);
}
}
void SetVertexFormat(bool bModulate, u8 texCoordNum) {
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
if (bModulate) {
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
}
for (int i = 0; i < texCoordNum; i++) {
GXSetVtxDesc(static_cast<GXAttr>(GX_VA_TEX0 + i), GX_DIRECT);
}
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_F32, 0);
if (bModulate) {
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
}
for (int i = 0; i < texCoordNum; i++) {
GXSetVtxAttrFmt(GX_VTXFMT0, static_cast<GXAttr>(GX_VA_TEX0 + i), GX_CLR_RGBA,
GX_F32, 0);
}
}
static void __deadstrip1();
static void __deadstrip1() {
// Force instantiation of GXEnd here on debug build
GXEnd();
}
void DrawQuad(const math::VEC2& basePt, const Size& size, u8 texCoordNum,
const TexCoords* texCoords, const ut::Color* vtxColors) {
// start at top left, go clockwise
// clang-format off
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
GXPosition2f32(basePt.x, basePt.y);
if (vtxColors)
GXColor1u32(vtxColors[0]);
for (int i = 0; i < texCoordNum; i++)
GXTexCoord2f32(texCoords[i][0].x, texCoords[i][0].y);
GXPosition2f32(basePt.x + size.width, basePt.y);
if (vtxColors)
GXColor1u32(vtxColors[1]);
for (int i = 0; i < texCoordNum; i++)
GXTexCoord2f32(texCoords[i][1].x, texCoords[i][1].y);
GXPosition2f32(basePt.x + size.width, basePt.y + size.height);
if (vtxColors)
GXColor1u32(vtxColors[3]);
for (int i = 0; i < texCoordNum; i++)
GXTexCoord2f32(texCoords[i][3].x, texCoords[i][3].y);
GXPosition2f32(basePt.x, basePt.y + size.height);
if (vtxColors)
GXColor1u32(vtxColors[2]);
for (int i = 0; i < texCoordNum; i++)
GXTexCoord2f32(texCoords[i][2].x, texCoords[i][2].y);
GXEnd();
// clang-format on
}
void DrawQuad(const math::VEC2& basePt, const Size& size, u8 texCoordNum,
const TexCoords* texCoords, const ut::Color* vtxColors, u8 alpha) {
ut::Color wkVtxColors[4];
if (vtxColors) {
MultipleAlpha(wkVtxColors, vtxColors, alpha);
}
DrawQuad(basePt, size, texCoordNum, texCoords, vtxColors ? wkVtxColors : NULL);
}
void DrawLine(const math::VEC2& pos, const Size& size, ut::Color color) {
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0);
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE,
GX_AF_NONE);
GXSetChanMatColor(GX_COLOR0A0, color);
GXSetNumTexGens(0);
GXSetNumTevStages(1);
GXSetNumIndStages(0);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GXSetTevOp(GX_TEVSTAGE0, GX_BLEND);
GXSetTevDirect(GX_TEVSTAGE0);
GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE,
GX_CH_ALPHA);
GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
GXSetLineWidth(6, GX_TO_ZERO);
// start at top left, go clockwise
// clang-format off
GXBegin(GX_LINESTRIP, GX_VTXFMT0, 5);
GXPosition2f32(pos.x , pos.y );
GXPosition2f32(pos.x + size.width, pos.y );
GXPosition2f32(pos.x + size.width, pos.y + size.height);
GXPosition2f32(pos.x , pos.y + size.height);
GXPosition2f32(pos.x , pos.y );
GXEnd();
// clang-format on
}
void InitGXTexObjFromTPL(GXTexObj* to, TPLPalette* pal, u32 id) {
// Is there some sort of macro for this
if (pal->descriptorArray < (TPLDescriptor*)0x80000000) { // ?
TPLBind(pal);
}
TPLDescriptor* tdp = TPLGet(pal, id);
GXBool mipMap = tdp->textureHeader->minLOD != tdp->textureHeader->maxLOD ? GX_TRUE : GX_FALSE;
if (tdp->CLUTHeader) {
// NOTE: explicit recast of mipMap necessary for debug
GXInitTexObjCI(
to, tdp->textureHeader->data, tdp->textureHeader->width, tdp->textureHeader->height,
static_cast<GXCITexFmt>(tdp->textureHeader->format), tdp->textureHeader->wrapS,
tdp->textureHeader->wrapT, static_cast<GXBool>(mipMap), 0);
GXInitTexObjUserData(to, tdp->CLUTHeader);
} else {
// NOTE: explicit recast of mipMap necessary for debug
GXInitTexObj(
to, tdp->textureHeader->data, tdp->textureHeader->width, tdp->textureHeader->height,
static_cast<GXTexFmt>(tdp->textureHeader->format), tdp->textureHeader->wrapS,
tdp->textureHeader->wrapT, static_cast<GXBool>(mipMap));
}
GXInitTexObjLOD(to, tdp->textureHeader->minFilter, tdp->textureHeader->magFilter,
tdp->textureHeader->minLOD, tdp->textureHeader->maxLOD,
tdp->textureHeader->LODBias, false, tdp->textureHeader->edgeLODEnable,
GX_ANISO_1);
}
} // namespace detail
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,17 @@
#include "drawInfo.h"
#include <cstring.h>
namespace nw4hbm {
namespace lyt {
DrawInfo::DrawInfo() : mLocationAdjustScale(1.0f, 1.0f), mGlobalAlpha(1.0f) {
std::memset(&mFlag, 0, sizeof(mFlag));
math::MTX34Identity(&mViewMtx);
}
DrawInfo::~DrawInfo() {}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,86 @@
#include "group.h"
#include "common.h"
#include "layout.h"
#include <cstring.h>
#include <new.h>
namespace nw4hbm {
namespace lyt {
Group::Group() {}
Group::Group(const res::Group* pResGroup, Pane* pRootPane) {
Init();
std::memcpy(mName, pResGroup->name, sizeof(mName));
const char* paneName = detail::ConvertOffsToPtr<char>(pResGroup, sizeof(*pResGroup));
for (int i = 0; i < pResGroup->paneNum; i++) {
Pane* pFindPane =
pRootPane->FindPaneByName(paneName + (int)sizeof(pResGroup)->name * i, true);
if (pFindPane) {
AppendPane(pFindPane);
}
}
}
void Group::Init() {
mbUserAllocated = false;
}
Group::~Group() {
for (PaneLinkList::Iterator it = mPaneLinkList.GetBeginIter();
it != mPaneLinkList.GetEndIter();)
{
PaneLinkList::Iterator currIt = it++;
mPaneLinkList.Erase(currIt);
Layout::FreeMemory(&*currIt);
}
}
void Group::AppendPane(Pane* pPane) {
if (void* pMem = Layout::AllocMemory(sizeof(detail::PaneLink))) {
detail::PaneLink* pPaneLink = new (pMem) detail::PaneLink();
pPaneLink->mTarget = pPane;
mPaneLinkList.PushBack(pPaneLink);
}
}
GroupContainer::~GroupContainer() {
for (GroupList::Iterator it = mGroupList.GetBeginIter(); it != mGroupList.GetEndIter();)
{
GroupList::Iterator currIt = it++;
mGroupList.Erase(currIt);
if (!currIt->IsUserAllocated()) {
currIt->~Group();
Layout::FreeMemory(&*currIt);
}
}
}
void GroupContainer::AppendGroup(Group* pGroup) {
mGroupList.PushBack(pGroup);
}
Group* GroupContainer::FindGroupByName(const char* findName) {
for (GroupList::Iterator it = mGroupList.GetBeginIter(); it != mGroupList.GetEndIter();
it++)
{
if (detail::EqualsPaneName(it->GetName(), findName)) {
return &(*it);
}
}
return NULL;
}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,368 @@
#include "layout.h"
#include "bounding.h"
#include "picture.h"
#include "textBox.h"
#include "window.h"
#include <new.h>
#define CONVERT_OFFSET_TO_PTR(type_, ptr_, offset_) \
reinterpret_cast<type_*>(reinterpret_cast<u32>(ptr_) + offset_)
namespace {
// pretend this is nw4hbm::lyt
using namespace nw4hbm;
using namespace nw4hbm::lyt;
void SetTagProcessorImpl(Pane* pPane, ut::TagProcessorBase<wchar_t>* pTagProcesssor);
// wait until these guys hear about c++11
template <class T>
T* CreateObject() {
void* pMem = Layout::AllocMemory(sizeof(T));
if (pMem) {
return new (pMem) T();
} else {
NW4R_DB_WARNING(47, false, "can't alloc memory.");
return NULL;
}
}
template <class T, typename Param1>
T* CreateObject(Param1 p1) {
void* pMem = Layout::AllocMemory(sizeof(T));
if (pMem) {
return new (pMem) T(p1);
} else {
return NULL;
}
}
template <class T, typename Param1, typename Param2>
T* CreateObject(Param1 p1, Param2 p2) {
void* pMem = Layout::AllocMemory(sizeof(T));
if (pMem) {
return new (pMem) T(p1, p2);
} else {
return NULL;
}
}
} // unnamed namespace
namespace nw4hbm {
namespace lyt {
MEMAllocator* Layout::mspAllocator;
} // namespace lyt
} // namespace nw4hbm
namespace {
void SetTagProcessorImpl(Pane* pPane, ut::TagProcessorBase<wchar_t>* pTagProcessor) {
if (TextBox* pTextBox = ut::DynamicCast<TextBox*>(pPane)) {
pTextBox->SetTagProcessor(pTagProcessor);
}
for (PaneList::Iterator it = pPane->GetChildList().GetBeginIter();
it != pPane->GetChildList().GetEndIter(); ++it)
{
SetTagProcessorImpl(&(*it), pTagProcessor);
}
}
} // anonymous namespace
namespace nw4hbm {
namespace lyt {
Layout::Layout()
: mpRootPane(NULL), mpGroupContainer(NULL), mLayoutSize(0.0f, 0.0f), mOriginType(0) {}
Layout::~Layout() {
if (mpGroupContainer) {
mpGroupContainer->~GroupContainer();
FreeMemory(mpGroupContainer);
}
if (mpRootPane && !mpRootPane->IsUserAllocated()) {
mpRootPane->~Pane();
FreeMemory(mpRootPane);
}
for (AnimTransformList::Iterator it = mAnimTransList.GetBeginIter();
it != mAnimTransList.GetEndIter();)
{
AnimTransformList::Iterator currIt = it++;
mAnimTransList.Erase(currIt);
currIt->~AnimTransform();
FreeMemory(&*currIt);
}
}
bool Layout::Build(const void* lytResBuf, ResourceAccessor* pResAcsr) {
NW4HBM_ASSERT_CHECK_NULL(171, mspAllocator);
NW4HBM_ASSERT_CHECK_NULL(172, lytResBuf);
const res::BinaryFileHeader* fileHead =
static_cast<const res::BinaryFileHeader*>(lytResBuf);
if (!detail::TestFileHeader(*fileHead, res::FILE_HEADER_SIGNATURE_LAYOUT)) {
return false;
}
if (fileHead->version != 8) {
NW4R_DB_ASSERTMSG(187, false, "Version check faild ('%d.%d' must be '%d.%d').",
(fileHead->version >> 8) & 0xFF, fileHead->version & 0xFF, 0, 8);
}
ResBlockSet resBlockSet = {};
resBlockSet.pResAccessor = pResAcsr;
Pane* pParentPane = NULL;
Pane* pLastPane = NULL;
bool bReadRootGroup = false;
int groupNestLevel = 0;
void* dataPtr = CONVERT_OFFSET_TO_PTR(void, lytResBuf, fileHead->headerSize);
for (int i = 0; i < fileHead->dataBlocks; i++) {
res::DataBlockHeader* pDataBlockHead = static_cast<res::DataBlockHeader*>(dataPtr);
switch (detail::GetSignatureInt(pDataBlockHead->kind)) {
case 'lyt1': {
res::Layout* pResLyt = static_cast<res::Layout*>(dataPtr);
mOriginType = pResLyt->originType != 0; // ?
mLayoutSize = pResLyt->layoutSize;
}
break;
case 'txl1':
resBlockSet.pTextureList = static_cast<res::TextureList*>(dataPtr);
break;
case 'fnl1':
resBlockSet.pFontList = static_cast<res::FontList*>(dataPtr);
break;
case 'mat1':
resBlockSet.pMaterialList = static_cast<res::MaterialList*>(dataPtr);
break;
case 'pan1':
case 'bnd1':
case 'pic1':
case 'txt1':
case 'wnd1':
if (Pane* pPane = BuildPaneObj(detail::GetSignatureInt(pDataBlockHead->kind),
dataPtr, resBlockSet))
{
if (!mpRootPane) {
mpRootPane = pPane;
}
if (pParentPane) {
pParentPane->AppendChild(pPane);
}
pLastPane = pPane;
}
break;
case 'pas1': // pane start?
NW4HBM_ASSERT_CHECK_NULL(249, pLastPane);
pParentPane = pLastPane;
break;
case 'pae1': // pane end?
pLastPane = pParentPane;
pParentPane = pLastPane->GetParent();
break;
case 'grp1':
if (!bReadRootGroup) {
bReadRootGroup = true;
mpGroupContainer = CreateObject<GroupContainer>();
} else if (mpGroupContainer && groupNestLevel == 1) {
if (Group* pGroup = CreateObject<Group>(
reinterpret_cast<const res::Group*>(pDataBlockHead), mpRootPane))
{
mpGroupContainer->AppendGroup(pGroup);
}
}
break;
case 'grs1': // group start?
groupNestLevel++;
break;
case 'gre1': // group end?
groupNestLevel--;
break;
}
dataPtr = CONVERT_OFFSET_TO_PTR(void, dataPtr, pDataBlockHead->size);
}
return true;
}
AnimTransform* Layout::CreateAnimTransform(const void* anmResBuf,
ResourceAccessor* pResAcsr) {
NW4HBM_ASSERT_CHECK_NULL(295, mspAllocator);
NW4HBM_ASSERT_CHECK_NULL(296, anmResBuf);
const res::BinaryFileHeader* pFileHead =
static_cast<const res::BinaryFileHeader*>(anmResBuf);
if (!detail::TestFileHeader(*pFileHead)) {
return NULL;
}
if (pFileHead->version != 8) {
NW4R_DB_ASSERTMSG(311, false, "Version check faild ('%d.%d' must be '%d.%d').",
(pFileHead->version >> 8) & 0xFF, pFileHead->version & 0xFF, 0,
8);
}
const res::AnimationBlock* pInfoBlock = NULL;
const res::DataBlockHeader* pDataBlockHead =
detail::ConvertOffsToPtr<res::DataBlockHeader>(pFileHead, pFileHead->headerSize);
AnimTransform* ret = NULL;
for (int i = 0; i < pFileHead->dataBlocks; i++) {
switch (detail::GetSignatureInt(pDataBlockHead->kind)) {
case 'pai1': // painting? idk
NW4HBM_ASSERT(321, ret == 0);
switch (detail::GetSignatureInt(pFileHead->signature)) {
case 'RLAN':
case res::AnimationInfo::ANIM_INFO_PANE_PAIN_SRT:
case res::AnimationInfo::ANIM_INFO_PANE_VISIBILITY:
case res::AnimationInfo::ANIM_INFO_PANE_VERTEX_COLOR:
case res::AnimationInfo::ANIM_INFO_MATERIAL_COLOR:
case res::AnimationInfo::ANIM_INFO_MATERIAL_TEXTURE_SRT:
case res::AnimationInfo::ANIM_INFO_MATERIAL_TEXTURE_PATTERN:
if (AnimTransformBasic* pAnimTrans = CreateObject<AnimTransformBasic>()) {
pInfoBlock =
reinterpret_cast<const res::AnimationBlock*>(pDataBlockHead);
pAnimTrans->SetResource(pInfoBlock, pResAcsr);
ret = pAnimTrans;
}
}
if (ret) {
mAnimTransList.PushBack(ret);
}
}
pDataBlockHead = detail::ConvertOffsToPtr<res::DataBlockHeader>(
pDataBlockHead, pDataBlockHead->size);
}
return ret;
}
void Layout::BindAnimation(AnimTransform* pAnimTrans) {
if (mpRootPane) {
mpRootPane->BindAnimation(pAnimTrans, true);
}
}
void Layout::UnbindAnimation(AnimTransform* pAnimTrans) {
if (mpRootPane) {
mpRootPane->UnbindAnimation(pAnimTrans, true);
}
}
void Layout::UnbindAllAnimation() {
UnbindAnimation(NULL);
}
void Layout::SetAnimationEnable(AnimTransform* pAnimTrans, bool bEnable) {
if (mpRootPane) {
mpRootPane->SetAnimationEnable(pAnimTrans, bEnable, true);
}
}
void Layout::CalculateMtx(const DrawInfo& drawInfo) {
if (mpRootPane) {
mpRootPane->CalculateMtx(drawInfo);
}
}
void Layout::Draw(const DrawInfo& drawInfo) {
if (mpRootPane) {
mpRootPane->Draw(drawInfo);
}
}
void Layout::Animate(u32 option) {
if (mpRootPane) {
mpRootPane->Animate(option);
}
}
const ut::Rect Layout::GetLayoutRect() const {
if (mOriginType == 1) {
return ut::Rect(-mLayoutSize.width / 2.0f, mLayoutSize.height / 2.0f,
mLayoutSize.width / 2.0f, -mLayoutSize.height / 2.0f);
} else {
return ut::Rect(0.0f, 0.0f, mLayoutSize.width, mLayoutSize.height);
}
}
void Layout::SetTagProcessor(ut::TagProcessorBase<wchar_t>* pTagProcessor) {
SetTagProcessorImpl(mpRootPane, pTagProcessor);
}
Pane* Layout::BuildPaneObj(s32 kind, const void* dataPtr, const ResBlockSet& resBlockSet) {
switch (kind) {
case res::OBJECT_SIGNATURE_PANE: {
const res::Pane* pResPane = static_cast<const res::Pane*>(dataPtr);
return CreateObject<Pane>(pResPane);
}
case res::OBJECT_SIGNATURE_PICTURE: {
const res::Picture* pResPic = static_cast<const res::Picture*>(dataPtr);
return CreateObject<Picture>(pResPic, resBlockSet);
}
case res::OBJECT_SIGNATURE_TEXT_BOX: {
// block?
const res::TextBox* pBlock = static_cast<const res::TextBox*>(dataPtr);
return CreateObject<TextBox>(pBlock, resBlockSet);
}
case res::OBJECT_SIGNATURE_WINDOW: {
// block?
const res::Window* pBlock = static_cast<const res::Window*>(dataPtr);
return CreateObject<Window>(pBlock, resBlockSet);
}
case res::OBJECT_SIGNATURE_BOUNDING: {
const res::Bounding* pResBounding = static_cast<const res::Bounding*>(dataPtr);
return CreateObject<Bounding>(pResBounding, resBlockSet);
}
default:
NW4R_DB_ASSERTMSG(503, false, "unknown data type");
return NULL;
}
}
} // namespace lyt
} // namespace nw4hbm

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,495 @@
#include "pane.h"
#include "common.h"
#include "layout.h"
#include <cstring.h>
namespace {
// pretend this is nw4hbm::lyt
using namespace nw4hbm;
using namespace nw4hbm::lyt;
void ReverseYAxis(math::MTX34* pMtx);
} // unnamed namespace
namespace nw4hbm {
namespace lyt {
NW4HBM_UT_GET_RUNTIME_TYPEINFO(Pane);
}
} // namespace nw4hbm
namespace {
void ReverseYAxis(math::MTX34* pMtx) {
pMtx->m[0][1] = -pMtx->m[0][1];
pMtx->m[1][1] = -pMtx->m[1][1];
pMtx->m[2][1] = -pMtx->m[2][1];
}
} // unnamed namespace
namespace nw4hbm {
namespace lyt {
Pane::Pane() {
Init();
mBasePosition = 4;
memset(mName, 0, sizeof(mName));
memset(mUserData, 0, sizeof(mUserData));
mTranslate = math::VEC3(0.0f, 0.0f, 0.0f);
mRotate = math::VEC3(0.0f, 0.0f, 0.0f);
mScale = math::VEC2(1.0f, 1.0f);
mSize = Size(0.0f, 0.0f);
mAlpha = ut::Color(255);
mGlbAlpha = mAlpha;
mFlag = 0;
SetVisible(true);
}
Pane::Pane(const res::Pane* pBlock) {
Init();
mBasePosition = pBlock->basePosition;
SetName(pBlock->name);
SetUserData(pBlock->userData);
mTranslate = pBlock->translate;
mRotate = pBlock->rotate;
mScale = pBlock->scale;
mSize = pBlock->size;
mAlpha = pBlock->alpha;
mGlbAlpha = mAlpha;
mFlag = pBlock->flag;
}
void Pane::Init() {
mpParent = NULL;
mpMaterial = NULL;
mbUserAllocated = false;
}
Pane::~Pane() {
for (PaneList::Iterator it = mChildList.GetBeginIter(); it != mChildList.GetEndIter();)
{
PaneList::Iterator currIt = it++;
mChildList.Erase(currIt);
if (!currIt->IsUserAllocated()) {
currIt->~Pane();
Layout::FreeMemory(&*currIt);
}
}
UnbindAnimationSelf(NULL);
if (mpMaterial && !mpMaterial->IsUserAllocated()) {
mpMaterial->~Material();
Layout::FreeMemory(mpMaterial);
}
}
void Pane::SetName(const char* name) {
std::strncpy(mName, name, sizeof(mName));
}
void Pane::SetUserData(const char* userData) {
std::strncpy(mUserData, userData, sizeof(mUserData));
}
void Pane::AppendChild(Pane* pChild) {
InsertChild(mChildList.GetEndIter(), pChild);
}
// it requires a type that wasn't used before to generate the string and avoid having it
// stripped
/* typedef nw4hbm::ut::LinkList<void**, 0> DummyLinkList;
DECOMP_FORCE_CLASS_METHOD(DummyLinkList, GetNodeFromPointer(NULL));
typedef nw4hbm::ut::LinkList<void***, 0> DummyLinkList2;
DECOMP_FORCE_CLASS_METHOD(DummyLinkList2, GetNodeFromPointer(NULL)); */
void Pane::InsertChild(PaneList::Iterator next, Pane* pChild) {
NW4HBM_ASSERT_CHECK_NULL(253, pChild);
NW4HBM_ASSERT(254, pChild->mpParent == 0);
mChildList.Insert(next, pChild);
pChild->mpParent = this;
}
void dummyString() {
OSReport("NW4HBM:Pointer must not be NULL (pNext)");
OSReport("NW4HBM:Failed assertion pNext->mpParent == this");
OSReport("NW4HBM:Failed assertion pChild->mpParent == this");
}
#pragma ppc_iro_level 0
const ut::Rect Pane::GetPaneRect(const DrawInfo& drawInfo) const {
ut::Rect ret;
math::VEC2 basePt = GetVtxPos();
ret.left = basePt.x;
ret.top = basePt.y;
ret.right = ret.left + mSize.width;
ret.bottom = ret.top + mSize.height;
if (drawInfo.IsYAxisUp()) {
ret.top = -ret.top;
ret.bottom = -ret.bottom;
}
return ret;
}
#pragma ppc_iro_level reset
ut::Color Pane::GetVtxColor(u32) const {
return ut::Color(0xFFFFFFFF);
}
void Pane::SetVtxColor(u32, ut::Color) { /* ... */ }
u8 Pane::GetColorElement(u32 idx) const {
NW4HBM_ASSERT(319, idx < ANIMTARGET_PANE_COLOR_MAX);
switch (idx) {
case 16:
return mAlpha;
default:
return GetVtxColorElement(idx);
}
}
// it requires a type that wasn't used before to generate the string and avoid having it
// stripped
/* typedef nw4hbm::ut::LinkList<void****, 0> DummyLinkList3;
DECOMP_FORCE_CLASS_METHOD(DummyLinkList3, GetNodeFromPointer(NULL)); */
void Pane::SetColorElement(u32 idx, u8 value) {
NW4HBM_ASSERT(334, idx < ANIMTARGET_PANE_COLOR_MAX);
switch (idx) {
case 16:
mAlpha = value;
break;
default:
SetVtxColorElement(idx, value);
break;
}
}
u8 Pane::GetVtxColorElement(u32) const {
return 0xff;
}
void Pane::SetVtxColorElement(u32, u8) { /* ... */ }
Pane* Pane::FindPaneByName(const char* findName, bool bRecursive) {
if (detail::EqualsPaneName(mName, findName)) {
return this;
}
if (bRecursive) {
for (PaneList::Iterator it = mChildList.GetBeginIter();
it != mChildList.GetEndIter(); it++)
{
if (Pane* pane = it->FindPaneByName(findName, true)) {
return pane;
}
}
}
return NULL;
}
Material* Pane::FindMaterialByName(const char* findName, bool bRecursive) {
if (mpMaterial && detail::EqualsMaterialName(mpMaterial->GetName(), findName)) {
return mpMaterial;
}
if (bRecursive) {
for (PaneList::Iterator it = mChildList.GetBeginIter();
it != mChildList.GetEndIter(); it++)
{
if (Material* pMaterial = it->FindMaterialByName(findName, true)) {
return pMaterial;
}
}
}
return NULL;
}
void Pane::CalculateMtx(const DrawInfo& drawInfo) {
// this doesnt even get referenced, an entirely new constant is generated lol
const f32 invAlpha = 1.0f / 255.0f;
if (!detail::TestBit(mFlag, 0) && !drawInfo.IsInvisiblePaneCalculateMtx()) {
return;
}
{
math::MTX34 mtx1;
math::MTX34 mtx2;
math::MTX34 rotateMtx;
{
math::VEC2 scale(mScale);
if (drawInfo.IsLocationAdjust() && detail::TestBit(mFlag, 2)) {
scale.x *= drawInfo.GetLocationAdjustScale().x;
scale.y *= drawInfo.GetLocationAdjustScale().y;
}
PSMTXScale(mtx2, scale.x, scale.y, 1.0f);
}
PSMTXRotRad(rotateMtx, 'x', DEG_TO_RAD(mRotate.x));
PSMTXConcat(rotateMtx, mtx2, mtx1);
PSMTXRotRad(rotateMtx, 'y', DEG_TO_RAD(mRotate.y));
PSMTXConcat(rotateMtx, mtx1, mtx2);
PSMTXRotRad(rotateMtx, 'z', DEG_TO_RAD(mRotate.z));
PSMTXConcat(rotateMtx, mtx2, mtx1);
PSMTXTransApply(mtx1, mMtx, mTranslate.x, mTranslate.y, mTranslate.z);
}
if (mpParent) {
math::MTX34Mult(&mGlbMtx, &mpParent->mGlbMtx, &mMtx);
} else if (drawInfo.IsMultipleViewMtxOnDraw()) {
mGlbMtx = mMtx;
} else {
math::MTX34Mult(&mGlbMtx, &drawInfo.GetViewMtx(), &mMtx);
}
if (drawInfo.IsInfluencedAlpha() && mpParent) {
mGlbAlpha = mAlpha * drawInfo.GetGlobalAlpha();
} else {
mGlbAlpha = mAlpha;
}
// cr = const ref?
f32 crGlobalAlpha = drawInfo.GetGlobalAlpha();
bool bCrInfluenced = drawInfo.IsInfluencedAlpha();
bool bModDrawInfo = detail::TestBit(mFlag, 1) && mAlpha != 0xff;
if (bModDrawInfo) {
// mt = mutable, probably
DrawInfo& mtDrawInfo = const_cast<DrawInfo&>(drawInfo);
mtDrawInfo.SetGlobalAlpha(crGlobalAlpha * mAlpha * invAlpha);
mtDrawInfo.SetInfluencedAlpha(true);
}
CalculateMtxChild(drawInfo);
// restore changed values if applicable
if (bModDrawInfo) {
DrawInfo& mtDrawInfo = const_cast<DrawInfo&>(drawInfo);
mtDrawInfo.SetGlobalAlpha(crGlobalAlpha);
mtDrawInfo.SetInfluencedAlpha(bCrInfluenced);
}
}
void Pane::CalculateMtxChild(const DrawInfo& drawInfo) {
for (PaneList::Iterator it = mChildList.GetBeginIter(); it != mChildList.GetEndIter();
it++)
{
it->CalculateMtx(drawInfo);
}
}
void Pane::Draw(const DrawInfo& drawInfo) {
if (detail::TestBit(mFlag, 0)) {
DrawSelf(drawInfo);
for (PaneList::Iterator it = mChildList.GetBeginIter();
it != mChildList.GetEndIter(); it++)
{
it->Draw(drawInfo);
}
}
}
void Pane::DrawSelf(const DrawInfo& drawInfo) {
if (mpParent && drawInfo.IsDebugDrawMode()) {
LoadMtx(drawInfo);
detail::DrawLine(GetVtxPos(), mSize, 0x00ff00ff); // green
}
}
void Pane::Animate(u32 option) {
AnimateSelf(option);
if (detail::TestBit(mFlag, 0) || !(option & 1)) {
for (PaneList::Iterator it = mChildList.GetBeginIter();
it != mChildList.GetEndIter(); it++)
{
it->Animate(option);
}
}
}
void Pane::AnimateSelf(u32 option) {
for (AnimationLinkList::Iterator it = mAnimList.GetBeginIter();
it != mAnimList.GetEndIter(); it++)
{
if (it->IsEnable()) {
AnimTransform* animTrans = it->GetAnimTransform();
animTrans->Animate(it->GetIndex(), this);
}
}
if ((detail::TestBit(mFlag, 0) || !(option & 1)) && mpMaterial) {
mpMaterial->Animate();
}
}
void Pane::BindAnimation(AnimTransform* pAnimTrans, bool bRecursive) {
NW4HBM_ASSERT_CHECK_NULL(596, pAnimTrans);
pAnimTrans->Bind(this, bRecursive);
}
void Pane::UnbindAnimation(AnimTransform* pAnimTrans, bool bRecursive) {
UnbindAnimationSelf(pAnimTrans);
if (bRecursive) {
for (PaneList::Iterator it = mChildList.GetBeginIter();
it != mChildList.GetEndIter(); it++)
{
it->UnbindAnimation(pAnimTrans, bRecursive);
}
}
}
void Pane::UnbindAllAnimation(bool bRecursive) {
UnbindAnimation(NULL, bRecursive);
}
void Pane::UnbindAnimationSelf(AnimTransform* pAnimTrans) {
if (mpMaterial) {
mpMaterial->UnbindAnimation(pAnimTrans);
}
for (AnimationLinkList::Iterator it = mAnimList.GetBeginIter();
it != mAnimList.GetEndIter();)
{
AnimationLinkList::Iterator currIt = it++;
if (pAnimTrans == NULL || currIt->GetAnimTransform() == pAnimTrans) {
mAnimList.Erase(currIt);
currIt->Reset();
}
}
}
void Pane::AddAnimationLink(AnimationLink* pAnimationLink) {
NW4HBM_ASSERT_CHECK_NULL(649, pAnimationLink);
mAnimList.PushBack(pAnimationLink);
}
AnimationLink* Pane::FindAnimationLink(AnimTransform* pAnimTrans) {
if (AnimationLink* ret = detail::FindAnimationLink(&mAnimList, pAnimTrans)) {
return ret;
}
if (mpMaterial) {
if (AnimationLink* ret = mpMaterial->FindAnimationLink(pAnimTrans)) {
return ret;
}
}
return NULL;
}
void Pane::SetAnimationEnable(AnimTransform* pAnimTrans, bool bEnable, bool bRecursive) {
if (AnimationLink* pAnimLink = detail::FindAnimationLink(&mAnimList, pAnimTrans)) {
pAnimLink->SetEnable(bEnable);
}
if (mpMaterial) {
mpMaterial->SetAnimationEnable(pAnimTrans, bEnable);
}
if (bRecursive) {
for (PaneList::Iterator it = mChildList.GetBeginIter();
it != mChildList.GetEndIter(); it++)
{
it->SetAnimationEnable(pAnimTrans, bEnable, bRecursive);
}
}
}
void Pane::LoadMtx(const DrawInfo& drawInfo) {
math::MTX34 mtx;
MtxPtr mtxPtr = NULL;
if (drawInfo.IsMultipleViewMtxOnDraw()) {
math::MTX34Mult(&mtx, &drawInfo.GetViewMtx(), &mGlbMtx);
if (drawInfo.IsYAxisUp()) {
ReverseYAxis(&mtx);
}
mtxPtr = mtx;
} else if (drawInfo.IsYAxisUp()) {
math::MTX34Copy(&mtx, &mGlbMtx);
ReverseYAxis(&mtx);
mtxPtr = mtx;
} else {
mtxPtr = mGlbMtx;
}
GXLoadPosMtxImm(mtxPtr, 0);
GXSetCurrentMtx(0);
}
math::VEC2 Pane::GetVtxPos() const {
math::VEC2 basePt(0.0f, 0.0f);
switch (mBasePosition % 3) {
default:
case 0:
basePt.x = 0.0f;
break;
case 1:
basePt.x = -mSize.width / 2.0f;
break;
case 2:
basePt.x = -mSize.width;
break;
}
switch (mBasePosition / 3) {
default:
case 0:
basePt.y = 0.0f;
break;
case 1:
basePt.y = -mSize.height / 2.0f;
break;
case 2:
basePt.y = -mSize.height;
break;
}
return basePt;
}
Material* Pane::GetMaterial() const {
return mpMaterial;
}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,130 @@
#include "picture.h"
#include "layout.h"
#include "new.h"
namespace nw4hbm {
namespace lyt {
NW4HBM_UT_GET_DERIVED_RUNTIME_TYPEINFO(Picture, Pane);
Picture::Picture(const res::Picture* pResPic, const ResBlockSet& resBlockSet)
: Pane(pResPic) {
u8 texCoordNum = ut::Min<u8>(pResPic->texCoordNum, 8);
Init(texCoordNum);
for (int i = 0; i < (int)ARRAY_SIZE(mVtxColors); i++) {
mVtxColors[i] = pResPic->vtxCols[i];
}
if (texCoordNum && !mTexCoordAry.IsEmpty()) {
mTexCoordAry.Copy(&pResPic[1], texCoordNum);
}
if (Material* pMemMaterial =
static_cast<Material*>(Layout::AllocMemory(sizeof(*pMemMaterial))))
{
NW4HBM_ASSERT_CHECK_NULL(149, resBlockSet.pMaterialList);
const u32* matOffsTbl =
detail::ConvertOffsToPtr<u32>(resBlockSet.pMaterialList, 0xc);
const res::Material* pResMaterial = detail::ConvertOffsToPtr<res::Material>(
resBlockSet.pMaterialList, matOffsTbl[pResPic->materialIdx]);
mpMaterial = new (pMemMaterial) Material(pResMaterial, resBlockSet);
}
}
void Picture::Init(u8 texNum) {
if (texNum) {
ReserveTexCoord(texNum);
}
}
Picture::~Picture() {
if (mpMaterial && !mpMaterial->IsUserAllocated()) {
mpMaterial->~Material();
Layout::FreeMemory(mpMaterial);
mpMaterial = NULL;
}
mTexCoordAry.Free();
}
void Picture::Append(TPLPalette* pTplRes) {
GXTexObj texObj;
detail::InitGXTexObjFromTPL(&texObj, pTplRes, 0);
Append(texObj);
}
void Picture::Append(const GXTexObj& texObj) {
if (mpMaterial->GetTextureNum() >= mpMaterial->GetTextureCap() ||
mpMaterial->GetTextureNum() >= mpMaterial->GetTexCoordGenCap())
{
NW4R_DB_WARNING(
192, false,
"mpMaterial->GetTextureNum(%d) is large. mpMaterial->GetTextureCap(%d), "
"mpMaterial->GetTexCoordGenCap(%d)\n",
mpMaterial->GetTextureNum(), mpMaterial->GetTextureCap(),
mpMaterial->GetTexCoordGenCap());
return;
}
u8 texIdx = mpMaterial->GetTextureNum();
mpMaterial->SetTextureNum(texIdx + 1);
mpMaterial->SetTexture(texIdx, texObj);
mpMaterial->SetTexCoordGenNum(mpMaterial->GetTextureNum());
mpMaterial->SetTexCoordGen(texIdx, TexCoordGen());
SetTexCoordNum(mpMaterial->GetTextureNum());
if (mSize == Size(0.0f, 0.0f) && mpMaterial->GetTextureNum() == 1) {
mSize = detail::GetTextureSize(mpMaterial, 0);
}
}
void Picture::ReserveTexCoord(u8 num) {
mTexCoordAry.Reserve(num);
}
void Picture::SetTexCoordNum(u8 num) {
mTexCoordAry.SetSize(num);
}
ut::Color Picture::GetVtxColor(u32 idx) const {
NW4HBM_ASSERT(251, idx < VERTEXCOLOR_MAX);
return mVtxColors[idx];
}
void Picture::SetVtxColor(u32 idx, ut::Color value) {
NW4HBM_ASSERT(262, idx < VERTEXCOLOR_MAX);
mVtxColors[idx] = value;
}
u8 Picture::GetVtxColorElement(u32 idx) const {
return detail::GetVtxColorElement(mVtxColors, idx);
}
void Picture::SetVtxColorElement(u32 idx, u8 value) {
detail::SetVtxColorElement(mVtxColors, idx, value);
}
void Picture::DrawSelf(const DrawInfo& drawInfo) {
if (!mpMaterial) {
return;
}
LoadMtx(drawInfo);
bool bUseVtxCol = mpMaterial->SetupGX(
detail::IsModulateVertexColor(mVtxColors, mGlbAlpha), mGlbAlpha);
nw4hbm::lyt::detail::SetVertexFormat(bUseVtxCol, mTexCoordAry.GetSize());
detail::DrawQuad(GetVtxPos(), mSize, mTexCoordAry.GetSize(), mTexCoordAry.GetArray(),
bUseVtxCol ? mVtxColors : NULL, mGlbAlpha);
}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,15 @@
#include "resourceAccessor.h"
namespace nw4hbm {
namespace lyt {
ResourceAccessor::~ResourceAccessor() {}
ResourceAccessor::ResourceAccessor() {}
ut::Font* ResourceAccessor::GetFont(const char*) {
return NULL;
}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,558 @@
#include "../ut/CharStrmReader.h"
#include "../ut/Font.h"
#include "../ut/ResFont.h"
#include "common.h"
#include "layout.h"
#include "material.h"
#include "pane.h"
#include "textBox.h"
#include "new.h"
namespace nw4hbm {
namespace lyt {
NW4HBM_UT_GET_DERIVED_RUNTIME_TYPEINFO(TextBox, Pane);
}
} // namespace nw4hbm
namespace {
using namespace nw4hbm;
u8 ClampColor(s16 colVal);
ut::Color GetColor(const GXColorS10& src) {
GXColor dst;
dst.r = ClampColor(src.r);
dst.g = ClampColor(src.g);
dst.b = ClampColor(src.b);
dst.a = ClampColor(src.a);
return dst;
}
u8 ClampColor(s16 value) {
return value < 0 ? 0 : (value > 255 ? 255 : value);
}
template <typename T>
int CalcLineRectImpl(ut::Rect* pRect, ut::TextWriterBase<T>* pTextWriter, const T* str,
int length, f32 maxWidth, bool* pbOver) {
NW4HBM_ASSERT_VALID_PTR(71, pTextWriter);
NW4HBM_ASSERT_VALID_PTR(72, pRect);
NW4HBM_ASSERT_VALID_PTR(73, str);
NW4R_ASSERT_MIN(74, length, 0);
ut::PrintContext<T> context = {pTextWriter, str, 0.0f, 0.0f, 0};
const ut::Font* font = pTextWriter->GetFont();
f32 x = 0.0f;
bool bCharSpace = false;
NW4HBM_ASSERT_VALID_PTR(83, font);
ut::CharStrmReader reader = font->GetCharStrmReader();
const T* prStrPos = static_cast<const T*>(reader.GetCurrentPos());
pRect->left = 0.0f;
pRect->right = 0.0f;
pRect->top = ut::Min(0.0f, pTextWriter->GetLineHeight());
pRect->bottom = ut::Max(0.0f, pTextWriter->GetLineHeight());
*pbOver = false;
reader.Set(str);
ut::Rect prMaxRect = *pRect;
for (u16 code = reader.Next();
static_cast<const T*>(reader.GetCurrentPos()) - str <= length;
prStrPos = static_cast<const T*>(reader.GetCurrentPos()), code = reader.Next(),
prMaxRect = *pRect)
{
if ((int)code < L' ') {
ut::Operation operation;
ut::Rect rect(x, 0.0f, 0.0f, 0.0f);
context.str = static_cast<const T*>(reader.GetCurrentPos());
context.flags = 0;
context.flags |= bCharSpace ? 0 : 1;
pTextWriter->SetCursorX(x);
operation = pTextWriter->GetTagProcessor().CalcRect(&rect, code, &context);
NW4HBM_ASSERT_VALID_PTR(123, context.str);
reader.Set(context.str);
pRect->left = ut::Min(pRect->left, rect.left);
pRect->top = ut::Min(pRect->top, rect.top);
pRect->right = ut::Max(pRect->right, rect.right);
pRect->bottom = ut::Max(pRect->bottom, rect.bottom);
x = pTextWriter->GetCursorX();
if (pRect->GetWidth() > maxWidth) {
*pbOver = true;
break;
}
if (operation == ut::OPERATION_END_DRAW) {
return length;
} else if (operation == ut::OPERATION_NO_CHAR_SPACE) {
bCharSpace = false;
} else if (operation == ut::OPERATION_CHAR_SPACE) {
bCharSpace = true;
} else if (operation == ut::OPERATION_NEXT_LINE) {
goto end_draw;
}
} else {
if (bCharSpace) {
x += pTextWriter->GetCharSpace();
}
bCharSpace = true;
if (pTextWriter->IsWidthFixed()) {
x += pTextWriter->GetFixedWidth();
} else {
x += pTextWriter->GetFont()->GetCharWidth(code) * pTextWriter->GetScaleH();
}
pRect->left = ut::Min(pRect->left, x);
pRect->right = ut::Max(pRect->right, x);
if (pRect->GetWidth() > maxWidth) {
*pbOver = true;
goto end_draw;
}
}
}
end_draw:
if (*pbOver && prStrPos) {
*pRect = prMaxRect;
return prStrPos - str;
} else {
return static_cast<const T*>(reader.GetCurrentPos()) - str;
}
}
template <typename T>
void CalcStringRectImpl(ut::Rect* pRect, ut::TextWriterBase<T>* pTextWriter, const T* str,
int length, f32 maxWidth) {
NW4HBM_ASSERT_VALID_PTR(218, pTextWriter);
NW4HBM_ASSERT_VALID_PTR(219, pRect);
NW4HBM_ASSERT_VALID_PTR(220, str);
NW4R_ASSERT_MIN(221, length, 0);
int remain = length;
const T* pos = str;
pRect->left = 0.0f;
pRect->right = 0.0f;
pRect->top = 0.0f;
pRect->bottom = 0.0f;
pTextWriter->SetCursor(0.0f, 0.0f);
do {
ut::Rect rect;
bool bOver;
int read = CalcLineRectImpl(&rect, pTextWriter, pos, remain, maxWidth, &bOver);
if (bOver) {
CalcLineRectImpl(&rect, pTextWriter, L"\n", 1, maxWidth, &bOver);
}
pos += read;
remain -= read;
pRect->left = ut::Min(pRect->left, rect.left);
pRect->top = ut::Min(pRect->top, rect.top);
pRect->right = ut::Max(pRect->right, rect.right);
pRect->bottom = ut::Max(pRect->bottom, rect.bottom);
} while (remain > 0);
}
template <typename T>
int CalcLineStrNum(f32* pWidth, ut::TextWriterBase<T>* pTextWriter, const T* str, int length,
f32 maxWidth, bool* pbOver) {
NW4HBM_ASSERT_VALID_PTR(275, pTextWriter);
NW4HBM_ASSERT_VALID_PTR(276, str);
NW4R_ASSERT_MIN(277, length, 0);
ut::Rect rect;
ut::TextWriterBase<T> myCopy = *pTextWriter;
myCopy.SetCursor(0.0f, 0.0f);
int ret = CalcLineRectImpl(&rect, &myCopy, str, length, maxWidth, pbOver);
*pWidth = rect.GetWidth();
return ret;
}
template <typename T>
void CalcStringRect(ut::Rect* pRect, ut::TextWriterBase<T>* pTextWriter, const T* str,
int length, f32 maxWidth) {
NW4HBM_ASSERT_VALID_PTR(311, pTextWriter);
NW4HBM_ASSERT_VALID_PTR(312, pRect);
NW4HBM_ASSERT_VALID_PTR(313, str);
NW4R_ASSERT_MIN(314, length, 0);
ut::TextWriterBase<T> myCopy = *pTextWriter;
CalcStringRectImpl(pRect, &myCopy, str, length, maxWidth);
}
} // namespace
namespace nw4hbm {
namespace lyt {
TextBox::TextBox(u16 allocStrLen, const wchar_t* str, const ut::Font* pFont) : Pane() {
Init(allocStrLen);
SetString(str);
SetFont(pFont);
}
TextBox::TextBox(const res::TextBox* pBlock, const ResBlockSet& resBlockSet)
: Pane(pBlock) {
u16 allocStrBufLen = pBlock->textBufBytes / sizeof(wchar_t);
if (allocStrBufLen) {
allocStrBufLen = allocStrBufLen - 1;
}
Init(allocStrBufLen);
if (pBlock->textStrBytes >= 2 && mTextBuf != NULL) {
const wchar_t* pBlockText =
detail::ConvertOffsToPtr<wchar_t>(pBlock, pBlock->textStrOffset);
const u16 resStrLen = pBlock->textStrBytes / sizeof(wchar_t) - 1;
SetString(pBlockText, 0, resStrLen);
}
for (int i = 0; i < (int)ARRAY_SIZE(mTextColors); i++) {
mTextColors[i] = pBlock->textCols[i];
}
mFontSize = pBlock->fontSize;
mTextPosition = pBlock->textPosition;
mCharSpace = pBlock->charSpace;
mLineSpace = pBlock->lineSpace;
NW4HBM_ASSERT_CHECK_NULL(395, resBlockSet.pFontList);
NW4HBM_ASSERT(396, pBlock->fontIdx < resBlockSet.pFontList->fontNum);
const res::Font* fonts = detail::ConvertOffsToPtr<res::Font>(
resBlockSet.pFontList, sizeof(*resBlockSet.pFontList));
const char* fontName =
detail::ConvertOffsToPtr<char>(fonts, fonts[pBlock->fontIdx].nameStrOffset);
if (ut::Font* pFont = resBlockSet.pResAccessor->GetFont(fontName)) {
mpFont = pFont;
} else if (void* fontRes =
resBlockSet.pResAccessor->GetResource('font', fontName, NULL))
{
if (void* pMemFont = Layout::AllocMemory(sizeof(ut::ResFont))) {
ut::ResFont* pResFont = new (pMemFont) ut::ResFont();
bool bSuccess = pResFont->SetResource(fontRes);
if (!bSuccess) {
NW4R_DB_ASSERTMSG(410, false, "Fail to load ResFont.");
}
mpFont = pResFont;
mTextBoxFlag.allocFont = true;
}
}
if (void* pMemMaterial = Layout::AllocMemory(sizeof(Material))) {
NW4HBM_ASSERT_CHECK_NULL(420, resBlockSet.pMaterialList);
const u32* matOffsTbl = detail::ConvertOffsToPtr<u32>(
resBlockSet.pMaterialList, sizeof(*resBlockSet.pMaterialList));
const res::Material* pResMaterial = detail::ConvertOffsToPtr<res::Material>(
resBlockSet.pMaterialList, matOffsTbl[pBlock->materialIdx]);
mpMaterial = new (pMemMaterial) Material(pResMaterial, resBlockSet);
}
}
void TextBox::Init(u16 allocStrLen) {
mTextBuf = NULL;
mTextBufBytes = 0;
mTextLen = 0;
mpFont = NULL;
mFontSize = Size(0.0f, 0.0f);
SetTextPositionH(HORIZONTALPOSITION_CENTER);
SetTextPositionV(VERTICALPOSITION_CENTER);
mLineSpace = 0.0f;
mCharSpace = 0.0f;
mpTagProcessor = NULL;
memset(&mTextBoxFlag, 0, sizeof(mTextBoxFlag));
if (allocStrLen != 0) {
AllocStringBuffer(allocStrLen);
}
}
TextBox::~TextBox() {
SetFont(NULL);
if (mpMaterial != NULL && !mpMaterial->IsUserAllocated()) {
mpMaterial->~Material();
Layout::FreeMemory(mpMaterial);
mpMaterial = NULL;
}
FreeStringBuffer();
}
ut::Color TextBox::GetVtxColor(u32 idx) const {
NW4HBM_ASSERT(467, idx < VERTEXCOLOR_MAX);
return GetTextColor(idx / 2);
}
void TextBox::SetVtxColor(u32 idx, ut::Color value) {
NW4HBM_ASSERT(478, idx < VERTEXCOLOR_MAX);
SetTextColor(idx / 2, value);
}
u8 TextBox::GetVtxColorElement(u32 idx) const {
NW4HBM_ASSERT(486, idx < ANIMTARGET_VERTEXCOLOR_MAX);
return reinterpret_cast<const u8*>(mTextColors + idx / 8)[idx % 4];
}
void TextBox::SetVtxColorElement(u32 idx, u8 value) {
NW4HBM_ASSERT(494, idx < ANIMTARGET_VERTEXCOLOR_MAX);
reinterpret_cast<u8*>(mTextColors + idx / 8)[idx % 4] = value;
}
const ut::Rect TextBox::GetTextDrawRect(const DrawInfo& drawInfo) const {
ut::WideTextWriter writer;
writer.SetFont(*mpFont);
writer.SetFontSize(mFontSize.width, mFontSize.height);
writer.SetLineSpace(mLineSpace);
writer.SetCharSpace(mCharSpace);
if (mpTagProcessor) {
writer.SetTagProcessor(mpTagProcessor);
}
ut::Rect rect = GetTextDrawRect(&writer);
if (drawInfo.IsYAxisUp()) {
rect.top = -rect.top;
rect.bottom = -rect.bottom;
}
return rect;
}
void TextBox::DrawSelf(const DrawInfo& drawInfo) {
if (mTextBuf == NULL || mpFont == NULL || mpMaterial == NULL) {
return;
}
LoadMtx(drawInfo);
ut::WideTextWriter writer;
writer.SetFont(*mpFont);
writer.SetFontSize(mFontSize.width, mFontSize.height);
writer.SetLineSpace(mLineSpace);
writer.SetCharSpace(mCharSpace);
ut::Color topCol = detail::MultipleAlpha(mTextColors[TEXTCOLOR_TOP], mGlbAlpha);
ut::Color btmCol = detail::MultipleAlpha(mTextColors[TEXTCOLOR_BOTTOM], mGlbAlpha);
writer.SetGradationMode(topCol != btmCol ? ut::CharWriter::GRADMODE_V :
ut::CharWriter::GRADMODE_NONE);
writer.SetTextColor(topCol, btmCol);
ut::Color minCol = GetColor(mpMaterial->GetTevColor(TEVCOLOR_REG0));
ut::Color maxCol = GetColor(mpMaterial->GetTevColor(TEVCOLOR_REG1));
writer.SetColorMapping(minCol, maxCol);
if (mpTagProcessor) {
writer.SetTagProcessor(mpTagProcessor);
}
writer.SetupGX();
ut::Rect textRect = GetTextDrawRect(&writer);
f32 hMag = GetTextMagH();
wchar_t* strPos = mTextBuf;
f32 textWidth = textRect.GetWidth();
writer.SetCursor(textRect.left, textRect.top);
for (int remain = mTextLen; remain > 0;) {
f32 lineWidth;
bool bOver;
int lineStrNum =
CalcLineStrNum(&lineWidth, &writer, strPos, remain, mSize.width, &bOver);
f32 textPosX = hMag * (textWidth - lineWidth);
writer.SetCursorX(textRect.left + textPosX);
writer.Print(strPos, lineStrNum);
if (bOver) {
writer.Print(L"\n");
}
strPos += lineStrNum;
remain -= lineStrNum;
}
}
u16 TextBox::GetStringBufferLength() const {
if (mTextBufBytes == 0) {
return 0;
} else {
NW4HBM_ASSERT(605, mTextBufBytes >= sizeof(wchar_t));
}
return mTextBufBytes / sizeof(wchar_t) - 1;
}
void TextBox::AllocStringBuffer(u16 minLen) {
if (minLen == 0) {
return;
}
u16 allocBytes = sizeof(wchar_t) * (minLen + 1);
if (allocBytes <= mTextBufBytes) {
return;
}
FreeStringBuffer();
mTextBuf = static_cast<wchar_t*>(Layout::AllocMemory(allocBytes));
if (mTextBuf != NULL) {
mTextBufBytes = allocBytes;
}
}
void TextBox::FreeStringBuffer() {
if (mTextBuf != NULL) {
Layout::FreeMemory(mTextBuf);
mTextBuf = NULL;
mTextBufBytes = 0;
}
}
u16 TextBox::SetString(const wchar_t* str, u16 dstIdx) {
return SetString(str, dstIdx, std::wcslen(str));
}
u16 TextBox::SetString(const wchar_t* str, u16 dstIdx, u16 strLen) {
if (mTextBuf == NULL) {
NW4R_DB_WARNING(708, false, "mTextBuf is NULL.\n");
return 0;
}
u16 bufLen = GetStringBufferLength();
if (dstIdx >= bufLen) {
NW4R_DB_WARNING(716, false, "dstIdx is out of range.\n");
return 0;
}
const u16 cpLen = ut::Min<u16>(strLen, bufLen - dstIdx);
if (cpLen < strLen) {
NW4R_DB_WARNING(721, false, "%d character(s) droped.\n", strLen - cpLen);
}
std::memcpy(&mTextBuf[dstIdx], str, sizeof(wchar_t) * cpLen);
mTextLen = dstIdx + cpLen;
mTextBuf[mTextLen] = L'\0';
return cpLen;
}
const ut::Font* TextBox::GetFont() const {
return mpFont;
}
void TextBox::SetFont(const ut::Font* pFont) {
if (mTextBoxFlag.allocFont) {
NW4HBM_ASSERT_CHECK_NULL(775, mpFont);
mpFont->~Font();
Layout::FreeMemory(const_cast<ut::Font*>(mpFont));
mTextBoxFlag.allocFont = false;
}
mpFont = pFont;
if (mpFont) {
SetFontSize(Size(mpFont->GetWidth(), mpFont->GetHeight()));
} else {
SetFontSize(Size(0.0f, 0.0f));
}
}
const ut::Rect TextBox::GetTextDrawRect(ut::WideTextWriter* pWriter) const {
ut::Rect textRect;
pWriter->SetCursor(0.0f, 0.0f);
CalcStringRect(&textRect, pWriter, mTextBuf, mTextLen, mSize.width);
math::VEC2 basePt = Pane::GetVtxPos();
textRect.MoveTo(basePt.x + (mSize.width - textRect.GetWidth()) * GetTextMagH(),
basePt.y + (mSize.height - textRect.GetHeight()) * GetTextMagV());
return textRect;
}
f32 TextBox::GetTextMagH() const {
f32 hMag = 0.0f;
switch (GetTextPositionH()) {
default:
case HORIZONTALPOSITION_LEFT: {
hMag = 0.0f;
break;
}
case HORIZONTALPOSITION_CENTER: {
hMag = 0.5f;
break;
}
case HORIZONTALPOSITION_RIGHT: {
hMag = 1.0f;
break;
}
}
return hMag;
}
f32 TextBox::GetTextMagV() const {
f32 vMag = 0.0f;
switch (GetTextPositionV()) {
default:
case HORIZONTALPOSITION_LEFT: {
vMag = 0.0f;
break;
}
case HORIZONTALPOSITION_CENTER: {
vMag = 0.5f;
break;
}
case HORIZONTALPOSITION_RIGHT: {
vMag = 1.0f;
break;
}
}
return vMag;
}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,449 @@
#ifndef NW4HBM_LYT_TYPES_H
#define NW4HBM_LYT_TYPES_H
#include "revolution/types.h"
#include <revolution/gx.h>
#include "../math/types.h"
#include "../ut/LinkList.h"
namespace nw4hbm {
namespace lyt {
static const u32 RESOURCE_TYPE_ANIMATION = 'anim';
static const u32 RESOURCE_TYPE_LAYOUT = 'blyt';
static const u32 RESOURCE_TYPE_FONT = 'font';
static const u32 RESOURCE_TYPE_TEXTURE = 'timg';
enum {
VERTEXCOLOR_LT = 0,
VERTEXCOLOR_RT,
VERTEXCOLOR_LB,
VERTEXCOLOR_RB,
VERTEXCOLOR_MAX
};
enum {
TEVCOLOR_REG0 = 0,
TEVCOLOR_REG1,
TEVCOLOR_REG2,
TEVCOLOR_MAX
};
enum {
HORIZONTALPOSITION_LEFT = 0,
HORIZONTALPOSITION_CENTER,
HORIZONTALPOSITION_RIGHT,
HORIZONTALPOSITION_MAX
};
enum {
VERTICALPOSITION_TOP = 0,
VERTICALPOSITION_CENTER,
VERTICALPOSITION_BOTTOM,
VERTICALPOSITION_MAX
};
enum {
ORIGINTYPE_TOPLEFT = 0,
ORIGINTYPE_CENTER,
ORIGINTYPE_MAX
};
enum {
TEXTCOLOR_TOP = 0,
TEXTCOLOR_BOTTOM,
TEXTCOLOR_MAX
};
enum {
WINDOWFRAME_LT = 0,
WINDOWFRAME_RT,
WINDOWFRAME_LB,
WINDOWFRAME_RB,
WINDOWFRAME_L,
WINDOWFRAME_R,
WINDOWFRAME_T,
WINDOWFRAME_B,
WINDOWFRAME_MAX
};
enum {
TEXTUREFLIP_NONE,
TEXTUREFLIP_H,
TEXTUREFLIP_V,
TEXTUREFLIP_90,
TEXTUREFLIP_180,
TEXTUREFLIP_270,
TEXTUREFLIP_MAX
};
enum {
FLIPINDEX_X,
FLIPINDEX_Y,
FLIPINDEX_MAX
};
namespace detail {
template <typename T>
const T* ConvertOffsToPtr(const void* baseAddress, unsigned offset) {
return reinterpret_cast<const T*>(reinterpret_cast<unsigned>(baseAddress) + offset);
}
template <typename T>
T* ConvertOffsToPtr(void* baseAddress, unsigned offset) {
return reinterpret_cast<T*>(reinterpret_cast<unsigned>(baseAddress) + offset);
}
template <typename T>
inline void SetBit(T* pBits, int pos, bool val) {
const T mask = (T)(~(1 << pos));
*pBits &= mask;
*pBits |= (val ? 1 : 0) << pos;
}
template <typename T>
inline bool TestBit(T bits, int pos) {
const T mask = (T)(1 << pos);
return 0 != (bits & mask);
}
template <typename T>
T GetBits(T bits, int pos, int len) {
T mask = static_cast<T>(~(-1 << len));
return static_cast<T>((bits >> pos) & mask);
}
} // namespace detail
typedef struct Size {
Size() : width(), height() {}
Size(f32 aWidth, f32 aHeight) : width(aWidth), height(aHeight) {}
Size(const Size& other) : width(other.width), height(other.height) {}
friend bool operator==(const Size& a, const Size& b) {
return a.width == b.width && a.height == b.height;
}
/* 0x00 */ f32 width;
/* 0x04 */ f32 height;
} Size; // size = 0x08
typedef struct TexSRT {
/* 0x00 */ math::VEC2 translate;
/* 0x08 */ f32 rotate;
/* 0x0C */ math::VEC2 scale;
} TexSRT;
class TexCoordGen {
public:
TexCoordGen() : reserve(0) { Set(GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); }
u32 GetTexMtx() const { return texMtx; }
GXTexGenType GetTexGenType() const { return static_cast<GXTexGenType>(texGenType); }
GXTexGenSrc GetTexGenSrc() const { return static_cast<GXTexGenSrc>(texGenSrc); }
void Set(GXTexGenType aTexGenType, GXTexGenSrc aTexGenSrc, u32 aTexMtx) {
texGenType = aTexGenType;
texGenSrc = aTexGenSrc;
texMtx = aTexMtx;
}
private:
/* 0x00 */ u8 texGenType;
/* 0x01 */ u8 texGenSrc;
/* 0x02 */ u8 texMtx;
/* 0x03 */ u8 reserve;
};
class IndirectStage {
public:
IndirectStage() { Set(GX_TEXCOORD0, GX_TEXMAP0, GX_ITS_1, GX_ITS_1); }
GXTexCoordID GetTexCoordGen() const { return static_cast<GXTexCoordID>(texCoordGen); }
GXTexMapID GetTexMap() const { return static_cast<GXTexMapID>(texMap); }
GXIndTexScale GetScaleS() const { return static_cast<GXIndTexScale>(scaleS); }
GXIndTexScale GetScaleT() const { return static_cast<GXIndTexScale>(scaleT); }
void Set(GXTexCoordID aTexCoordGen, GXTexMapID aTexMap, GXIndTexScale aScaleS,
GXIndTexScale aScaleT) {
texCoordGen = aTexCoordGen;
texMap = aTexMap;
scaleS = aScaleS;
scaleT = aScaleT;
}
private:
/* 0x00 */ u8 texCoordGen;
/* 0x01 */ u8 texMap;
/* 0x02 */ u8 scaleS;
/* 0x03 */ u8 scaleT;
};
class TevSwapMode {
public:
GXTevColorChan GetR() const { return static_cast<GXTevColorChan>((swap) & 0x03); }
GXTevColorChan GetG() const { return static_cast<GXTevColorChan>((swap >> 2) & 0x03); }
GXTevColorChan GetB() const { return static_cast<GXTevColorChan>((swap >> 4) & 0x03); }
GXTevColorChan GetA() const { return static_cast<GXTevColorChan>((swap >> 6) & 0x03); }
void Set(GXTevColorChan r, GXTevColorChan g, GXTevColorChan b, GXTevColorChan a) {
swap = r | g << 2 | b << 4 | a << 6;
}
private:
/* 0x00 */ u8 swap;
};
class TevStageInOp {
public:
u8 GetA() const { return ab & 0x0F; }
u8 GetB() const { return (ab >> 4) & 0x0F; }
u8 GetC() const { return cd & 0x0F; }
u8 GetD() const { return (cd >> 4) & 0x0F; }
u8 GetScale() const { return (op >> 6) & 0x03; }
u8 GetBias() const { return (op >> 4) & 0x03; }
u8 GetOp() const { return op & 0x0F; }
u8 GetKSel() const { return (cl >> 3) & 0x1F; }
u8 GetOutReg() const { return (cl >> 1) & 0x03; }
bool IsClamp() const { return static_cast<bool>(cl & 0x01); }
void SetIn(u8 a, u8 b, u8 c, u8 d) {
ab = a | b << 4;
cd = c | d << 4;
}
void SetOp(u8 aOp, u8 bias, u8 scale, bool clamp, u8 outReg, u8 kSel) {
op = aOp | bias << 4 | scale << 6;
cl = (clamp ? 1 : 0) | outReg << 1 | kSel << 3;
}
private:
/* 0x00 */ u8 ab;
/* 0x01 */ u8 cd;
/* 0x02 */ u8 op;
/* 0x03 */ u8 cl;
};
class TevStage {
public:
TevStage() {
SetOrder(GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEV_SWAP0, GX_TEV_SWAP0);
SetColorIn(GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
SetAlphaIn(GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA);
SetColorOp(GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV,
GX_TEV_KCSEL_K0);
SetAlphaOp(GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV,
GX_TEV_KASEL_K0_R);
SetIndirect(GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF,
GX_ITW_OFF, false, false, GX_ITBA_OFF);
}
GXTexCoordID GetTexCoordGen() const { return static_cast<GXTexCoordID>(texCoordGen); }
GXChannelID GetColorChan() const { return static_cast<GXChannelID>(colChan); }
GXTexMapID GetTexMap() const {
return static_cast<GXTexMapID>((swapSel & 1) << 8 | texMap);
}
GXTevSwapSel GetTexSwapSel() const {
return static_cast<GXTevSwapSel>((swapSel >> 3) & 0x03);
}
GXTevSwapSel GetRasSwapSel() const {
return static_cast<GXTevSwapSel>((swapSel >> 1) & 0x03);
}
GXTevColorArg GetColorInA() const { return static_cast<GXTevColorArg>(colIn.GetA()); }
GXTevColorArg GetColorInB() const { return static_cast<GXTevColorArg>(colIn.GetB()); }
GXTevColorArg GetColorInC() const { return static_cast<GXTevColorArg>(colIn.GetC()); }
GXTevColorArg GetColorInD() const { return static_cast<GXTevColorArg>(colIn.GetD()); }
GXTevOp GetColorOp() const { return static_cast<GXTevOp>(colIn.GetOp()); }
GXTevBias GetColorBias() const { return static_cast<GXTevBias>(colIn.GetBias()); }
GXTevScale GetColorScale() const { return static_cast<GXTevScale>(colIn.GetScale()); }
bool IsColorClamp() const { return colIn.IsClamp(); }
GXTevRegID GetColorOutReg() const { return static_cast<GXTevRegID>(colIn.GetOutReg()); }
GXTevKColorSel GetKColorSel() const {
return static_cast<GXTevKColorSel>(colIn.GetKSel());
}
GXTevAlphaArg GetAlphaInA() const { return static_cast<GXTevAlphaArg>(alpIn.GetA()); }
GXTevAlphaArg GetAlphaInB() const { return static_cast<GXTevAlphaArg>(alpIn.GetB()); }
GXTevAlphaArg GetAlphaInC() const { return static_cast<GXTevAlphaArg>(alpIn.GetC()); }
GXTevAlphaArg GetAlphaInD() const { return static_cast<GXTevAlphaArg>(alpIn.GetD()); }
GXTevOp GetAlphaOp() const { return static_cast<GXTevOp>(alpIn.GetOp()); }
GXTevBias GetAlphaBias() const { return static_cast<GXTevBias>(alpIn.GetBias()); }
GXTevScale GetAlphaScale() const { return static_cast<GXTevScale>(alpIn.GetScale()); }
bool IsAlphaClamp() const { return alpIn.IsClamp(); }
GXTevRegID GetAlphaOutReg() const { return static_cast<GXTevRegID>(alpIn.GetOutReg()); }
GXTevKAlphaSel GetKAlphaSel() const {
return static_cast<GXTevKAlphaSel>(alpIn.GetKSel());
}
GXIndTexStageID GetIndStage() const { return static_cast<GXIndTexStageID>(indStage); }
GXIndTexMtxID GetIndMtxSel() const {
return static_cast<GXIndTexMtxID>((indBiMt >> 3) & 0x0F);
}
GXIndTexBiasSel GetIndBiasSel() const {
return static_cast<GXIndTexBiasSel>(indBiMt & 0x07);
}
GXIndTexWrap GetIndWrapS() const { return static_cast<GXIndTexWrap>(indWrap & 0x07); }
GXIndTexWrap GetIndWrapT() const {
return static_cast<GXIndTexWrap>((indWrap >> 3) & 0x07);
}
GXIndTexAlphaSel GetIndAlphaSel() const {
return static_cast<GXIndTexAlphaSel>((indFoAdUtAl >> 4) & 0x03);
}
bool IsIndUtcLod() const { return static_cast<bool>((indFoAdUtAl >> 3) & 0x01); }
bool IsIndAddPrev() const { return static_cast<bool>((indFoAdUtAl >> 2) & 0x01); }
GXIndTexFormat GetIndFormat() const {
return static_cast<GXIndTexFormat>(indFoAdUtAl & 0x03);
}
void SetOrder(GXTexCoordID aTexCoordGen, GXTexMapID aTexMap, GXChannelID aColChan,
GXTevSwapSel rasSel, GXTevSwapSel texSel) {
texCoordGen = aTexCoordGen;
colChan = aColChan;
texMap = aTexMap;
swapSel = aTexMap >> 8 | rasSel << 1 | texSel << 3;
}
void SetColorIn(GXTevColorArg a, GXTevColorArg b, GXTevColorArg c, GXTevColorArg d) {
colIn.SetIn(a, b, c, d);
}
void SetColorOp(GXTevOp op, GXTevBias bias, GXTevScale scale, bool clamp,
GXTevRegID outReg, GXTevKColorSel kSel) {
colIn.SetOp(op, bias, scale, clamp, outReg, kSel);
}
void SetAlphaIn(GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c, GXTevAlphaArg d) {
alpIn.SetIn(a, b, c, d);
}
void SetAlphaOp(GXTevOp op, GXTevBias bias, GXTevScale scale, bool clamp,
GXTevRegID outReg, GXTevKAlphaSel kSel) {
alpIn.SetOp(op, bias, scale, clamp, outReg, kSel);
}
void SetIndirect(GXIndTexStageID stage, GXIndTexFormat format, GXIndTexBiasSel biasSel,
GXIndTexMtxID mtxSel, GXIndTexWrap wrapS, GXIndTexWrap wrapT,
bool addPrev, bool utcLod, GXIndTexAlphaSel alphaSel) {
indStage = stage;
indBiMt = biasSel | mtxSel << 3;
indWrap = wrapS | wrapT << 3;
indFoAdUtAl =
format | (addPrev ? 1 : 0) << 2 | (utcLod ? 1 : 0) << 3 | alphaSel << 4;
}
private:
/* 0x00 */ u8 texCoordGen;
/* 0x01 */ u8 colChan;
/* 0x02 */ u8 texMap;
/* 0x03 */ u8 swapSel;
/* 0x04 */ TevStageInOp colIn;
/* 0x08 */ TevStageInOp alpIn;
/* 0x0C */ u8 indStage;
/* 0x0D */ u8 indBiMt;
/* 0x0E */ u8 indWrap;
/* 0x0F */ u8 indFoAdUtAl;
};
class ChanCtrl {
public:
ChanCtrl() : reserve1(0), reserve2(0) { Set(GX_SRC_VTX, GX_SRC_VTX); }
GXColorSrc GetColorSrc() const { return static_cast<GXColorSrc>(matSrcCol); }
GXColorSrc GetAlphaSrc() const { return static_cast<GXColorSrc>(matSrcAlp); }
void Set(GXColorSrc colSrc, GXColorSrc alpSrc) {
matSrcCol = colSrc;
matSrcAlp = alpSrc;
}
private:
/* 0x00 */ u8 matSrcCol;
/* 0x01 */ u8 matSrcAlp;
/* 0x02 */ u8 reserve1;
/* 0x03 */ u8 reserve2;
};
class AlphaCompare {
public:
AlphaCompare() { Set(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); }
GXCompare GetComp0() const { return static_cast<GXCompare>(comp & 0x0F); }
GXCompare GetComp1() const { return static_cast<GXCompare>((comp >> 4) & 0x0F); }
GXAlphaOp GetOp() const { return static_cast<GXAlphaOp>(op); }
u8 GetRef0() const { return ref0; }
u8 GetRef1() const { return ref1; }
void Set(GXCompare aComp0, u8 aRef0, GXAlphaOp aOp, GXCompare aComp1, u8 aRef1) {
comp = aComp0 | aComp1 << 4;
op = aOp;
ref0 = aRef0;
ref1 = aRef1;
}
private:
/* 0x00 */ u8 comp;
/* 0x01 */ u8 op;
/* 0x02 */ u8 ref0;
/* 0x03 */ u8 ref1;
};
class BlendMode {
public:
BlendMode() { Set(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET); }
GXBlendMode GetType() const { return static_cast<GXBlendMode>(type); }
GXBlendFactor GetSrcFactor() const { return static_cast<GXBlendFactor>(srcFactor); }
GXBlendFactor GetDstFactor() const { return static_cast<GXBlendFactor>(dstFactor); }
GXLogicOp GetOp() const { return static_cast<GXLogicOp>(op); }
void Set(GXBlendMode aType, GXBlendFactor aSrcFactor, GXBlendFactor aDstFactor,
GXLogicOp aOp) {
type = aType;
srcFactor = aSrcFactor;
dstFactor = aDstFactor;
op = aOp;
}
private:
/* 0x00 */ u8 type;
/* 0x01 */ u8 srcFactor;
/* 0x02 */ u8 dstFactor;
/* 0x03 */ u8 op;
};
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,568 @@
#include "window.h"
#include "layout.h"
#include "new.h"
struct TextureFlipInfo {
/* 0x00 */ u8 coords[4][2];
/* 0x08 */ u8 idx[2];
}; // size = 0x0A
namespace {
// pretend this is nw4hbm::lyt
using namespace nw4hbm;
using namespace nw4hbm::lyt;
// NOTE the misspelling of GetTextureFlipInfo
TextureFlipInfo& GetTexutreFlipInfo(u8 textureFlip);
void GetLTFrameSize(math::VEC2* pPt, Size* pSize, const math::VEC2& basePt, const Size& winSize,
const WindowFrameSize& frameSize);
void GetLTTexCoord(math::VEC2* texCds, const Size& polSize, const Size& texSize,
u8 textureFlip);
void GetRTFrameSize(math::VEC2* pPt, Size* pSize, const math::VEC2& basePt, const Size& winSize,
const WindowFrameSize& frameSize);
void GetRTTexCoord(math::VEC2* texCds, const Size& polSize, const Size& texSize,
u8 textureFlip);
void GetLBFrameSize(math::VEC2* pPt, Size* pSize, const math::VEC2& basePt, const Size& winSize,
const WindowFrameSize& frameSize);
void GetLBTexCoord(math::VEC2* texCds, const Size& polSize, const Size& texSize,
u8 textureFlip);
void GetRBFrameSize(math::VEC2* pPt, Size* pSize, const math::VEC2& basePt, const Size& winSize,
const WindowFrameSize& frameSize);
void GetRBTexCoord(math::VEC2* texCds, const Size& polSize, const Size& texSize,
u8 textureFlip);
} // unnamed namespace
namespace nw4hbm {
namespace lyt {
NW4HBM_UT_GET_DERIVED_RUNTIME_TYPEINFO(Window, Pane);
} // namespace lyt
} // namespace nw4hbm
//! TODO clean up
namespace {
TextureFlipInfo& GetTexutreFlipInfo(u8 textureFlip) {
// clang-format off
static TextureFlipInfo flipInfos[] = // 0 1 2 3
{ // in order of LT RT LB RB
{{{0, 0}, {1, 0}, {0, 1}, {1, 1}}, {0, 1}}, // 0 1 2 3 no flip
{{{1, 0}, {0, 0}, {1, 1}, {0, 1}}, {0, 1}}, // 1 0 3 2 horizontal flip
{{{0, 1}, {1, 1}, {0, 0}, {1, 0}}, {0, 1}}, // 2 3 0 1 vertical flip
{{{0, 1}, {0, 0}, {1, 1}, {1, 0}}, {1, 0}}, // 2 0 3 1, index flip cw 90 deg
{{{1, 1}, {0, 1}, {1, 0}, {0, 0}}, {0, 1}}, // 3 2 1 0 cw 180 deg
{{{1, 0}, {1, 1}, {0, 0}, {0, 1}}, {1, 0}} // 1 3 0 2, index flip cw 270 deg (ccw 90 deg)
};
// clang-format on
NW4HBM_ASSERT(50, textureFlip < TEXTUREFLIP_MAX);
return flipInfos[textureFlip];
}
void GetLTFrameSize(math::VEC2* pPt, Size* pSize, const math::VEC2& basePt, const Size& winSize,
const WindowFrameSize& frameSize) {
*pPt = basePt;
pSize->width = winSize.width - frameSize.r;
pSize->height = frameSize.t;
}
void GetLTTexCoord(math::VEC2* texCds, const Size& polSize, const Size& texSize,
u8 textureFlip) {
TextureFlipInfo& flipInfo = GetTexutreFlipInfo(textureFlip);
int ix = flipInfo.idx[FLIPINDEX_X];
int iy = flipInfo.idx[FLIPINDEX_Y];
const math::VEC2 tSz(texSize.width, texSize.height);
texCds[VERTEXCOLOR_LT][ix] = texCds[VERTEXCOLOR_LB][ix] =
flipInfo.coords[VERTEXCOLOR_LT][ix];
texCds[VERTEXCOLOR_LT][iy] = texCds[VERTEXCOLOR_RT][iy] =
flipInfo.coords[VERTEXCOLOR_LT][iy];
texCds[VERTEXCOLOR_RB][ix] = texCds[VERTEXCOLOR_RT][ix] =
flipInfo.coords[VERTEXCOLOR_LT][ix] +
polSize.width /
((flipInfo.coords[VERTEXCOLOR_RT][ix] - flipInfo.coords[VERTEXCOLOR_LT][ix]) *
tSz[ix]);
texCds[VERTEXCOLOR_RB][iy] = texCds[VERTEXCOLOR_LB][iy] =
flipInfo.coords[VERTEXCOLOR_LT][iy] +
polSize.height /
((flipInfo.coords[VERTEXCOLOR_LB][iy] - flipInfo.coords[VERTEXCOLOR_LT][iy]) *
tSz[iy]);
}
void GetRTFrameSize(math::VEC2* pPt, Size* pSize, const math::VEC2& basePt, const Size& winSize,
const WindowFrameSize& frameSize) {
*pPt = math::VEC2(basePt.x + winSize.width - frameSize.r, basePt.y);
pSize->width = frameSize.r;
pSize->height = winSize.height - frameSize.b;
}
void GetRTTexCoord(math::VEC2* texCds, const Size& polSize, const Size& texSize,
u8 textureFlip) {
TextureFlipInfo& flipInfo = GetTexutreFlipInfo(textureFlip);
int ix = flipInfo.idx[FLIPINDEX_X];
int iy = flipInfo.idx[FLIPINDEX_Y];
const math::VEC2 tSz(texSize.width, texSize.height);
texCds[VERTEXCOLOR_RT][ix] = texCds[VERTEXCOLOR_RB][ix] =
flipInfo.coords[VERTEXCOLOR_RT][ix];
texCds[VERTEXCOLOR_RT][iy] = texCds[VERTEXCOLOR_LT][iy] =
flipInfo.coords[VERTEXCOLOR_RT][iy];
texCds[VERTEXCOLOR_LB][ix] = texCds[VERTEXCOLOR_LT][ix] =
flipInfo.coords[VERTEXCOLOR_RT][ix] +
polSize.width /
((flipInfo.coords[VERTEXCOLOR_LT][ix] - flipInfo.coords[VERTEXCOLOR_RT][ix]) *
tSz[ix]);
texCds[VERTEXCOLOR_LB][iy] = texCds[VERTEXCOLOR_RB][iy] =
flipInfo.coords[VERTEXCOLOR_RT][iy] +
polSize.height /
((flipInfo.coords[VERTEXCOLOR_RB][iy] - flipInfo.coords[VERTEXCOLOR_RT][iy]) *
tSz[iy]);
}
void GetLBFrameSize(math::VEC2* pPt, Size* pSize, const math::VEC2& basePt, const Size& winSize,
const WindowFrameSize& frameSize) {
*pPt = math::VEC2(basePt.x, basePt.y + frameSize.t);
pSize->width = frameSize.l;
pSize->height = winSize.height - frameSize.t;
}
void GetLBTexCoord(math::VEC2* texCds, const Size& polSize, const Size& texSize,
u8 textureFlip) {
TextureFlipInfo& flipInfo = GetTexutreFlipInfo(textureFlip);
int ix = flipInfo.idx[FLIPINDEX_X];
int iy = flipInfo.idx[FLIPINDEX_Y];
const math::VEC2 tSz(texSize.width, texSize.height);
texCds[VERTEXCOLOR_LB][ix] = texCds[VERTEXCOLOR_LT][ix] =
flipInfo.coords[VERTEXCOLOR_LB][ix];
texCds[VERTEXCOLOR_LB][iy] = texCds[VERTEXCOLOR_RB][iy] =
flipInfo.coords[VERTEXCOLOR_LB][iy];
texCds[VERTEXCOLOR_RT][ix] = texCds[VERTEXCOLOR_RB][ix] =
flipInfo.coords[VERTEXCOLOR_LB][ix] +
polSize.width /
((flipInfo.coords[VERTEXCOLOR_RB][ix] - flipInfo.coords[VERTEXCOLOR_LB][ix]) *
tSz[ix]);
texCds[VERTEXCOLOR_RT][iy] = texCds[VERTEXCOLOR_LT][iy] =
flipInfo.coords[VERTEXCOLOR_LB][iy] +
polSize.height /
((flipInfo.coords[VERTEXCOLOR_LT][iy] - flipInfo.coords[VERTEXCOLOR_LB][iy]) *
tSz[iy]);
}
void GetRBFrameSize(math::VEC2* pPt, Size* pSize, const math::VEC2& basePt, const Size& winSize,
const WindowFrameSize& frameSize) {
*pPt = math::VEC2(basePt.x + frameSize.l, basePt.y + winSize.height - frameSize.b);
pSize->width = winSize.width - frameSize.l;
pSize->height = frameSize.b;
}
void GetRBTexCoord(math::VEC2* texCds, const Size& polSize, const Size& texSize,
u8 textureFlip) {
TextureFlipInfo& flipInfo = GetTexutreFlipInfo(textureFlip);
int ix = flipInfo.idx[FLIPINDEX_X];
int iy = flipInfo.idx[FLIPINDEX_Y];
const math::VEC2 tSz(texSize.width, texSize.height);
texCds[VERTEXCOLOR_RB][ix] = texCds[VERTEXCOLOR_RT][ix] =
flipInfo.coords[VERTEXCOLOR_RB][ix];
texCds[VERTEXCOLOR_RB][iy] = texCds[VERTEXCOLOR_LB][iy] =
flipInfo.coords[VERTEXCOLOR_RB][iy];
texCds[VERTEXCOLOR_LT][ix] = texCds[VERTEXCOLOR_LB][ix] =
flipInfo.coords[VERTEXCOLOR_RB][ix] +
polSize.width /
((flipInfo.coords[VERTEXCOLOR_LB][ix] - flipInfo.coords[VERTEXCOLOR_RB][ix]) *
tSz[ix]);
texCds[VERTEXCOLOR_LT][iy] = texCds[VERTEXCOLOR_RT][iy] =
flipInfo.coords[VERTEXCOLOR_RB][iy] +
polSize.height /
((flipInfo.coords[VERTEXCOLOR_RT][iy] - flipInfo.coords[VERTEXCOLOR_RB][iy]) *
tSz[iy]);
}
} // unnamed namespace
namespace nw4hbm {
namespace lyt {
Window::Window(const res::Window* pBlock, const ResBlockSet& resBlockSet) : Pane(pBlock) {
mContentInflation = pBlock->inflation;
NW4HBM_ASSERT_CHECK_NULL(193, resBlockSet.pMaterialList);
const u32* const matOffsTbl = detail::ConvertOffsToPtr<u32>(
resBlockSet.pMaterialList, sizeof(*resBlockSet.pMaterialList));
const res::WindowContent* pResContent =
detail::ConvertOffsToPtr<res::WindowContent>(pBlock, pBlock->contentOffset);
for (int i = 0; i < (int)ARRAY_SIZE(mContent.vtxColors); i++) {
mContent.vtxColors[i] = pResContent->vtxCols[i];
}
if (pResContent->texCoordNum) {
u8 texCoordNum = ut::Min<u8>(pResContent->texCoordNum, 8);
mContent.texCoordAry.Reserve(texCoordNum);
if (!mContent.texCoordAry.IsEmpty()) {
mContent.texCoordAry.Copy(&pResContent[1], texCoordNum);
}
}
if (void* pMemMaterial = Layout::AllocMemory(sizeof(Material))) {
const res::Material* pResMaterial = detail::ConvertOffsToPtr<res::Material>(
resBlockSet.pMaterialList, matOffsTbl[pResContent->materialIdx]);
mpMaterial = new (pMemMaterial) Material(pResMaterial, resBlockSet);
}
mFrameNum = 0;
mFrames = NULL;
if (pBlock->frameNum) {
if ((mFrames = static_cast<Frame*>(
Layout::AllocMemory(sizeof(*mFrames) * pBlock->frameNum))))
{
mFrameNum = pBlock->frameNum;
const u32* frameOffsetTable =
detail::ConvertOffsToPtr<u32>(pBlock, pBlock->frameOffsetTableOffset);
for (int i = 0; i < mFrameNum; i++) {
const res::WindowFrame* pResWindowFrame =
detail::ConvertOffsToPtr<res::WindowFrame>(pBlock, frameOffsetTable[i]);
mFrames[i].textureFlip = pResWindowFrame->textureFlip;
mFrames[i].pMaterial = NULL;
if (void* pMemMaterial = Layout::AllocMemory(sizeof(Material))) {
const res::Material* pResMaterial =
detail::ConvertOffsToPtr<res::Material>(
resBlockSet.pMaterialList,
matOffsTbl[pResWindowFrame->materialIdx]);
mFrames[i].pMaterial =
new (pMemMaterial) Material(pResMaterial, resBlockSet);
}
}
}
}
}
Window::~Window() {
if (mFrames) {
for (int i = 0; i < mFrameNum; i++) {
mFrames[i].pMaterial->~Material();
Layout::FreeMemory(mFrames[i].pMaterial);
}
Layout::FreeMemory(mFrames);
}
if (mpMaterial && !mpMaterial->IsUserAllocated()) {
mpMaterial->~Material();
Layout::FreeMemory(mpMaterial);
mpMaterial = NULL;
}
mContent.texCoordAry.Free();
}
Material* Window::FindMaterialByName(const char* findName, bool bRecursive) {
if (mpMaterial && detail::EqualsMaterialName(mpMaterial->GetName(), findName)) {
return mpMaterial;
}
for (int i = 0; i < mFrameNum; i++) {
if (detail::EqualsMaterialName(mFrames[i].pMaterial->GetName(), findName)) {
return mFrames[i].pMaterial;
}
}
if (bRecursive) {
for (PaneList::Iterator it = mChildList.GetBeginIter();
it != mChildList.GetEndIter(); it++)
{
Material* pMat = it->FindMaterialByName(findName, true);
if (pMat) {
return pMat;
}
}
}
return NULL;
}
AnimationLink* Window::FindAnimationLink(AnimTransform* pAnimTrans) {
if (AnimationLink* ret = Pane::FindAnimationLink(pAnimTrans)) {
return ret;
}
for (int i = 0; i < mFrameNum; i++) {
if (AnimationLink* ret = mFrames[i].pMaterial->FindAnimationLink(pAnimTrans)) {
return ret;
}
}
return NULL;
}
void Window::SetAnimationEnable(AnimTransform* pAnimTrans, bool bEnable, bool bRecursive) {
for (int i = 0; i < mFrameNum; i++) {
mFrames[i].pMaterial->SetAnimationEnable(pAnimTrans, bEnable);
}
Pane::SetAnimationEnable(pAnimTrans, bEnable, bRecursive);
}
ut::Color Window::GetVtxColor(u32 idx) const {
NW4HBM_ASSERT(360, idx < VERTEXCOLOR_MAX);
return mContent.vtxColors[idx];
}
void Window::SetVtxColor(u32 idx, ut::Color value) {
NW4HBM_ASSERT(371, idx < VERTEXCOLOR_MAX);
mContent.vtxColors[idx] = value;
}
u8 Window::GetVtxColorElement(u32 idx) const {
return detail::GetVtxColorElement(mContent.vtxColors, idx);
}
void Window::SetVtxColorElement(u32 idx, u8 value) {
detail::SetVtxColorElement(mContent.vtxColors, idx, value);
}
void Window::DrawSelf(const DrawInfo& drawInfo) {
LoadMtx(drawInfo);
WindowFrameSize frameSize = GetFrameSize(mFrameNum, mFrames);
math::VEC2 basePt = GetVtxPos();
DrawContent(basePt, frameSize, mGlbAlpha);
switch (mFrameNum) {
case 1:
DrawFrame(basePt, *mFrames, frameSize, mGlbAlpha);
break;
case 4:
DrawFrame4(basePt, mFrames, frameSize, mGlbAlpha);
break;
case 8:
DrawFrame8(basePt, mFrames, frameSize, mGlbAlpha);
break;
}
}
void Window::AnimateSelf(u32 option) {
Pane::AnimateSelf(option);
if (detail::TestBit<>(mFlag, 0) || !(option & 1)) {
for (int i = 0; i < mFrameNum; i++) {
mFrames[i].pMaterial->Animate();
}
}
}
void Window::UnbindAnimationSelf(AnimTransform* pAnimTrans) {
for (int i = 0; i < mFrameNum; i++) {
mFrames[i].pMaterial->UnbindAnimation(pAnimTrans);
}
Pane::UnbindAnimationSelf(pAnimTrans);
}
void Window::DrawContent(const math::VEC2& basePt, const WindowFrameSize& frameSize,
u8 alpha) {
bool bUseVtxCol = mpMaterial->SetupGX(
detail::IsModulateVertexColor(mContent.vtxColors, alpha), alpha);
detail::SetVertexFormat(bUseVtxCol, mContent.texCoordAry.GetSize());
// clang-format off
detail::DrawQuad(
math::VEC2(basePt.x + frameSize.l - mContentInflation.l,
basePt.y + frameSize.t - mContentInflation.t),
Size(mSize.width - frameSize.l + mContentInflation.l
- frameSize.r + mContentInflation.r,
mSize.height - frameSize.t + mContentInflation.t
- frameSize.b + mContentInflation.b),
mContent.texCoordAry.GetSize(),
mContent.texCoordAry.GetArray(),
bUseVtxCol ? mContent.vtxColors : NULL,
alpha
);
// clang-format on
}
void Window::DrawFrame(const math::VEC2& basePt, const Frame& frame,
const WindowFrameSize& frameSize, u8 alpha) {
bool bUseVtxCol =
frame.pMaterial->SetupGX(detail::IsModulateVertexColor(NULL, alpha), alpha);
detail::SetVertexFormat(bUseVtxCol, GX_TEXMAP1);
const Size texSize = detail::GetTextureSize(frame.pMaterial, GX_TEXMAP0);
const ut::Color vtxColors[VERTEXCOLOR_MAX];
detail::TexCoords texCds[1];
math::VEC2 polPt;
Size polSize;
#define DRAW_QUAD_FOR_FRAME_1(corner_, frameIdx_) \
{ \
Get##corner_##FrameSize(&polPt, &polSize, basePt, mSize, frameSize); \
Get##corner_##TexCoord(*texCds, polSize, texSize, frameIdx_); \
detail::DrawQuad(polPt, polSize, GX_TEXMAP1, texCds, bUseVtxCol ? vtxColors : NULL, \
alpha); \
}
DRAW_QUAD_FOR_FRAME_1(LT, TEXTUREFLIP_NONE);
DRAW_QUAD_FOR_FRAME_1(RT, TEXTUREFLIP_H);
DRAW_QUAD_FOR_FRAME_1(RB, TEXTUREFLIP_180);
DRAW_QUAD_FOR_FRAME_1(LB, TEXTUREFLIP_V);
#undef DRAW_QUAD_FOR_FRAME_1
}
void Window::DrawFrame4(const math::VEC2& basePt, const Frame* frames,
const WindowFrameSize& frameSize, u8 alpha) {
ut::Color vtxColors[4];
detail::TexCoords texCds[1];
math::VEC2 polPt;
Size polSize;
bool bModVtxCol = detail::IsModulateVertexColor(NULL, alpha);
#define DRAW_FRAME_4_QUAD_(corner_, frameIdx_) \
do { \
bool bUseVtxCol = frames[frameIdx_].pMaterial->SetupGX(bModVtxCol, alpha); \
\
Get##corner_##FrameSize(&polPt, &polSize, basePt, mSize, frameSize); \
Get##corner_##TexCoord(*texCds, polSize, \
detail::GetTextureSize(frames[frameIdx_].pMaterial, 0), \
frames[frameIdx_].textureFlip); \
\
detail::SetVertexFormat(bUseVtxCol, 1); \
\
detail::DrawQuad(polPt, polSize, 1, texCds, bUseVtxCol ? vtxColors : NULL, alpha); \
} while (0)
DRAW_FRAME_4_QUAD_(LT, 0);
DRAW_FRAME_4_QUAD_(RT, 1);
DRAW_FRAME_4_QUAD_(RB, 3);
DRAW_FRAME_4_QUAD_(LB, 2);
#undef DRAW_FRAME_4_QUAD_
}
void Window::DrawFrame8(const math::VEC2& basePt, const Frame* frames,
const WindowFrameSize& frameSize, u8 alpha) {
ut::Color vtxColors[4];
detail::TexCoords texCds[1];
Size polSize;
bool bModVtxCol = detail::IsModulateVertexColor(NULL, alpha);
#define DRAW_FRAME_8_QUAD_(corner_, frameIdx_, polSizeInit_, basePtInit_) \
do { \
bool bUseVtxCol = frames[frameIdx_].pMaterial->SetupGX(bModVtxCol, alpha); \
polSize = Size polSizeInit_; \
\
Get##corner_##TexCoord(*texCds, polSize, \
detail::GetTextureSize(frames[frameIdx_].pMaterial, 0), \
frames[frameIdx_].textureFlip); \
\
detail::SetVertexFormat(bUseVtxCol, 1); \
\
detail::DrawQuad(VEC_CTOR_ basePtInit_, polSize, 1, texCds, bUseVtxCol ? vtxColors : NULL, \
alpha); \
} while (0)
#define VEC_CTOR_ // avoid copy construction specifically for this first call
DRAW_FRAME_8_QUAD_(LT, 0, (frameSize.l, frameSize.t), basePt);
#undef VEC_CTOR_
#define VEC_CTOR_ math::VEC2
DRAW_FRAME_8_QUAD_(LT, 6, (mSize.width - frameSize.l - frameSize.r, frameSize.t),
(basePt.x + frameSize.l, basePt.y));
DRAW_FRAME_8_QUAD_(RT, 1, (frameSize.r, frameSize.t),
(basePt.x + mSize.width - frameSize.r, basePt.y));
DRAW_FRAME_8_QUAD_(RT, 5, (frameSize.r, mSize.height - frameSize.t - frameSize.b),
(basePt.x + mSize.width - frameSize.r, basePt.y + frameSize.t));
DRAW_FRAME_8_QUAD_(
RB, 3, (frameSize.r, frameSize.b),
(basePt.x + mSize.width - frameSize.r, basePt.y + mSize.height - frameSize.b));
DRAW_FRAME_8_QUAD_(RB, 7, (mSize.width - frameSize.l - frameSize.r, frameSize.b),
(basePt.x + frameSize.l, basePt.y + mSize.height - frameSize.b));
DRAW_FRAME_8_QUAD_(LB, 2, (frameSize.l, frameSize.b),
(basePt.x, basePt.y + mSize.height - frameSize.b));
DRAW_FRAME_8_QUAD_(LB, 4, (frameSize.l, mSize.height - frameSize.t - frameSize.b),
(basePt.x, basePt.y + frameSize.t));
#undef VEC_CTOR_
#undef DRAW_FRAME_8_QUAD_
}
WindowFrameSize Window::GetFrameSize(u8 frameNum, const Frame* frames) {
WindowFrameSize ret = {};
switch (frameNum) {
case 1: {
Size texSize = detail::GetTextureSize(frames->pMaterial, 0);
ret.l = texSize.width;
ret.t = texSize.height;
ret.r = texSize.width;
ret.b = texSize.height;
} break;
case 4:
case 8: {
Size texSize = detail::GetTextureSize(frames[0].pMaterial, 0);
ret.l = texSize.width;
ret.t = texSize.height;
texSize = detail::GetTextureSize(frames[3].pMaterial, 0);
ret.r = texSize.width;
ret.b = texSize.height;
} break;
}
return ret;
}
Material* Window::GetFrameMaterial(u32 frameIdx) const {
NW4HBM_ASSERT(658, frameIdx < WINDOWFRAME_MAX);
if (frameIdx >= mFrameNum) {
return NULL;
}
return mFrames[frameIdx].pMaterial;
}
Material* Window::GetContentMaterial() const {
return GetMaterial();
}
} // namespace lyt
} // namespace nw4hbm

View File

@ -0,0 +1,154 @@
#ifndef NW4HBM_LYT_MATERIAL_H
#define NW4HBM_LYT_MATERIAL_H
#include <revolution/types.h>
#include <revolution/tpl.h>
#include <revolution/gx.h>
#include "animation.h"
#include "lyt_types.h"
#include "resources.h"
#include "../ut/Color.h"
namespace nw4hbm {
namespace lyt {
class Material;
namespace detail {
typedef struct BitGXNums {
u32 texMap : 4; // 11110000000000000000000000000000
u32 texSRT : 4; // 00001111000000000000000000000000
u32 texCoordGen : 4; // 00000000111100000000000000000000
u32 indSRT : 2; // 00000000000011000000000000000000
u32 indStage : 3; // 00000000000000111000000000000000
u32 tevSwap : 1; // 00000000000000000100000000000000
u32 tevStage : 5; // 00000000000000000011111000000000
u32 chanCtrl : 1; // 00000000000000000000000100000000
u32 matCol : 1; // 00000000000000000000000010000000
u32 alpComp : 1; // 00000000000000000000000001000000
u32 blendMode : 1; // 00000000000000000000000000100000
} BitGXNums;
Size GetTextureSize(Material* pMaterial, u8 texMapIdx);
} // namespace detail
class Material {
public:
Material();
Material(const res::Material* pRes, const ResBlockSet& resBlockSet);
/* 0x08 */ virtual ~Material();
/* 0x0C */ virtual bool SetupGX(bool bModVtxCol, u8 alpha);
/* 0x10 */ virtual void BindAnimation(AnimTransform* animTrans);
/* 0x14 */ virtual void UnbindAnimation(AnimTransform* animTrans);
/* 0x18 */ virtual void UnbindAllAnimation();
/* 0x1C */ virtual void Animate();
/* 0x20 */ virtual AnimationLink* FindAnimationLink(AnimTransform* animTrans);
/* 0x24 */ virtual void SetAnimationEnable(AnimTransform* animTrans, bool bEnable);
const char* GetName() const { return mName; }
GXColorS10 GetTevColor(u32 idx) const { return mTevCols[idx]; }
u8 GetTextureCap() const { return mGXMemCap.texMap; }
u8 GetTexSRTCap() const { return mGXMemCap.texSRT; }
u8 GetTexCoordGenCap() const { return mGXMemCap.texCoordGen; }
u8 GetIndTexSRTCap() const { return mGXMemCap.indSRT; }
bool IsTevSwapCap() const { return static_cast<bool>(mGXMemCap.tevSwap); }
bool IsBlendModeCap() const { return static_cast<bool>(mGXMemCap.blendMode); }
bool IsAlphaCompareCap() const { return static_cast<bool>(mGXMemCap.alpComp); }
bool IsMatColorCap() const { return static_cast<bool>(mGXMemCap.matCol); }
bool IsChanCtrlCap() const { return static_cast<bool>(mGXMemCap.chanCtrl); }
u8 GetTextureNum() const { return mGXMemNum.texMap; }
bool IsUserAllocated() const { return mbUserAllocated; }
void SetName(const char* name);
const GXTexObj* GetTexMapAry() const;
const TexSRT* GetTexSRTAry() const;
const TexCoordGen* GetTexCoordGenAry() const;
const ChanCtrl* GetChanCtrlAry() const;
const ut::Color* GetMatColAry() const;
const TevSwapMode* GetTevSwapAry() const;
const AlphaCompare* GetAlphaComparePtr() const;
const BlendMode* GetBlendModePtr() const;
const IndirectStage* GetIndirectStageAry() const;
const TexSRT* GetIndTexSRTAry() const;
const TevStage* GetTevStageAry() const;
GXTexObj* GetTexMapAry();
TexSRT* GetTexSRTAry();
TexCoordGen* GetTexCoordGenAry();
ChanCtrl* GetChanCtrlAry();
ut::Color* GetMatColAry();
TevSwapMode* GetTevSwapAry();
AlphaCompare* GetAlphaComparePtr();
BlendMode* GetBlendModePtr();
IndirectStage* GetIndirectStageAry();
TexSRT* GetIndTexSRTAry();
TevStage* GetTevStageAry();
void GetTexture(GXTexObj* pTexObj, u8 texMapIdx) const;
void SetTextureNum(u8 num);
void SetTexCoordGenNum(u8 num);
void SetIndStageNum(u8 num);
void SetTevStageNum(u8 num);
void SetTexture(u8 texMapIdx, const GXTexObj& texObj);
void SetTexture(u8 texMapIdx, TPLPalette* pTplRes);
void SetTextureNoWrap(u8 texMapIdx, TPLPalette* pTplRes);
void SetColorElement(u32 colorType, s16 value);
void SetTexCoordGen(u32 idx, TexCoordGen value) {
NW4HBM_ASSERT(180, idx < mGXMemNum.texCoordGen);
GetTexCoordGenAry()[idx] = value;
}
void SetTexSRTElement(u32 texSRTIdx, u32 eleIdx, f32 value) {
NW4HBM_ASSERT(293, texSRTIdx < mGXMemNum.texSRT);
f32* srtAry = reinterpret_cast<f32*>(&GetTexSRTAry()[texSRTIdx]);
srtAry[eleIdx] = value;
}
void SetIndTexSRTElement(u32 texSRTIdx, u32 eleIdx, f32 value) {
NW4HBM_ASSERT(309, texSRTIdx < mGXMemNum.indSRT);
f32* srtAry = reinterpret_cast<f32*>(&GetIndTexSRTAry()[texSRTIdx]);
srtAry[eleIdx] = value;
}
void Init();
void InitBitGXNums(detail::BitGXNums* ptr);
void ReserveGXMem(u8 texMapNum, u8 texSRTNum, u8 texCoordGenNum, u8 tevStageNum,
bool allocTevSwap, u8 indStageNum, u8 indSRTNum, bool allocChanCtrl,
bool allocMatCol, bool allocAlpComp, bool allocBlendMode);
void AddAnimationLink(AnimationLink* animationLink);
private:
static const int MAX_TEX_SRT = (GX_TEXMTX9 - GX_TEXMTX0) / 3 + 1;
static const int MAX_IND_SRT = (GX_ITM_2 - GX_ITM_0) + 1;
/* 0x00 (vtable) */
/* 0x04 */ char mName[20];
/* 0x18 */ AnimationLinkList mAnimList;
/* 0x24 */ GXColorS10 mTevCols[TEVCOLOR_MAX];
/* 0x3C */ ut::Color mTevKCols[GX_MAX_KCOLOR];
/* 0x4C */ detail::BitGXNums mGXMemCap;
/* 0x50 */ detail::BitGXNums mGXMemNum;
/* 0x54 */ bool mbUserAllocated;
/* 0x58 */ void* mpGXMem;
};
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,175 @@
#ifndef NW4HBM_LYT_PANE_H
#define NW4HBM_LYT_PANE_H
#include "revolution/types.h"
#include "../ut/Color.h"
#include "../ut/LinkList.h"
#include "../ut/Rect.h"
#include "../ut/RuntimeTypeInfo.h"
#include "../db/assert.h"
#include "../math/types.h"
#include "animation.h"
#include "drawInfo.h"
#include "lyt_types.h"
#include "material.h"
namespace nw4hbm {
namespace lyt {
class Pane;
namespace detail {
class PaneBase {
public:
inline PaneBase() : mLink() {}
/* 0x08 */ virtual ~PaneBase() {}
/* 0x00 (vtable) */
/* 0x04 */ ut::LinkListNode mLink;
};
} // namespace detail
typedef ut::LinkList<Pane, offsetof(detail::PaneBase, mLink)> PaneList;
enum {
/* 1 */ ANIMOPTION_SKIP_INVISIBLE = (1 << 0),
};
class Pane : detail::PaneBase {
private:
enum {
/* 0 */ BIT_VISIBLE = 0,
/* 1 */ BIT_INFLUENCED_ALPHA,
/* 2 */ BIT_LOCATION_ADJUST
};
public:
Pane();
Pane(const res::Pane* pBlock);
/* 0x08 */ virtual ~Pane();
/* 0x0C */ NW4HBM_UT_RUNTIME_TYPEINFO;
/* 0x10 */ virtual void CalculateMtx(const DrawInfo& drawInfo);
/* 0x14 */ virtual void Draw(const DrawInfo& drawInfo);
/* 0x18 */ virtual void DrawSelf(const DrawInfo& drawInfo);
/* 0x1C */ virtual void Animate(u32 option = 0);
/* 0x20 */ virtual void AnimateSelf(u32 option = 0);
/* 0x24 */ virtual ut::Color GetVtxColor(u32 idx) const;
/* 0x28 */ virtual void SetVtxColor(u32 idx, ut::Color valuw);
/* 0x2C */ virtual u8 GetColorElement(u32 idx) const;
/* 0x30 */ virtual void SetColorElement(u32 idx, u8 color);
/* 0x34 */ virtual u8 GetVtxColorElement(u32 idx) const;
/* 0x38 */ virtual void SetVtxColorElement(u32 idx, u8 element);
/* 0x3C */ virtual Pane* FindPaneByName(const char* findName, bool bRecursive = true);
/* 0x40 */ virtual Material* FindMaterialByName(const char* findName,
bool bRecursive = true);
/* 0x44 */ virtual void BindAnimation(AnimTransform* animTrans, bool bRecursive = true);
/* 0x48 */ virtual void UnbindAnimation(AnimTransform* animTrans,
bool bRecursive = true);
/* 0x4C */ virtual void UnbindAllAnimation(bool bRecursive = true);
/* 0x50 */ virtual void UnbindAnimationSelf(AnimTransform* animTrans);
/* 0x54 */ virtual AnimationLink* FindAnimationLink(AnimTransform* animTrans);
/* 0x58 */ virtual void SetAnimationEnable(AnimTransform* animTrans, bool bEnable,
bool bRecursive = true);
/* 0x5C */ virtual Material* GetMaterial() const;
/* 0x60 */ virtual void LoadMtx(const DrawInfo& drawInfo);
Pane* GetParent() const { return mpParent; }
PaneList& GetChildList() { return mChildList; }
const math::VEC3& GetTranslate() { return mTranslate; }
void SetTranslate(const math::VEC3& translate) { mTranslate = translate; }
void SetTranslate(const math::VEC2& translate) {
SetTranslate(math::VEC3(translate.x, translate.y, 0.0f));
}
const math::VEC3& GetRotate() const { return mRotate; }
void SetRotate(const math::VEC3& rotate) { mRotate = rotate; }
const math::VEC2& GetScale() const { return mScale; }
void SetScale(const math::VEC2& scale) { mScale = scale; }
const Size& GetSize() const { return mSize; }
void SetSize(const Size& size) { mSize = size; }
bool IsVisible() { return detail::TestBit(mFlag, BIT_VISIBLE); };
void SetVisible(bool visible) { detail::SetBit(&mFlag, BIT_VISIBLE, visible); };
bool IsInfluencedAlpha() { return detail::TestBit(mFlag, BIT_INFLUENCED_ALPHA); };
void SetInfluencedAlpha(bool visible) {
detail::SetBit(&mFlag, BIT_INFLUENCED_ALPHA, visible);
};
bool IsLocationAdjust() { return detail::TestBit(mFlag, BIT_LOCATION_ADJUST); };
void SetLocationAdjust(bool visible) {
detail::SetBit(&mFlag, BIT_LOCATION_ADJUST, visible);
};
const math::MTX34& GetGlobalMtx() const { return mGlbMtx; }
void SetGlobalMtx(const math::MTX34& mtx) { mGlbMtx = mtx; }
const math::MTX34& GetMtx() const { return mMtx; }
void SetMtx(const math::MTX34& mtx) { mMtx = mtx; }
u8 GetAlpha() { return mAlpha; }
void SetAlpha(u8 alpha) { mAlpha = alpha; }
const char* GetName() const { return mName; }
void SetSRTElement(u32 idx, f32 value) {
NW4HBM_ASSERT(250, idx < ANIMTARGET_PANE_MAX);
reinterpret_cast<f32*>(&mTranslate)[idx] = value;
}
bool IsUserAllocated() const { return mbUserAllocated; }
const ut::Rect GetPaneRect(const DrawInfo& drawInfo) const;
math::VEC2 GetVtxPos() const;
void SetName(const char* name);
void SetUserData(const char* userData);
void Init();
void InsertChild(PaneList::Iterator next, Pane* pChild);
void InsertChild(Pane* pNext, Pane* pChild);
void PrependChild(Pane* pChild);
void AppendChild(Pane* pChild);
void RemoveChild(Pane* pChild);
void CalculateMtxChild(const DrawInfo& drawInfo);
void AddAnimationLink(AnimationLink* animationLink);
protected:
/* 0x00 (base) */
/* 0x0C */ Pane* mpParent;
/* 0x10 */ PaneList mChildList;
/* 0x1C */ AnimationLinkList mAnimList;
/* 0x28 */ Material* mpMaterial;
/* 0x2C */ math::VEC3 mTranslate;
/* 0x38 */ math::VEC3 mRotate;
/* 0x44 */ math::VEC2 mScale;
/* 0x4C */ Size mSize;
/* 0x54 */ math::MTX34 mMtx;
/* 0x84 */ math::MTX34 mGlbMtx;
/* 0xB4 */ char mName[16];
/* 0xC4 */ char mUserData[8];
/* 0xCC */ u8 mBasePosition;
/* 0xCD */ u8 mAlpha;
/* 0xCE */ u8 mGlbAlpha;
/* 0xCF */ u8 mFlag;
/* 0xD0 */ bool mbUserAllocated;
}; // size = 0xD4
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,44 @@
#ifndef NW4HBM_LYT_PICTURE_H
#define NW4HBM_LYT_PICTURE_H
#include "pane.h"
#include "common.h"
namespace nw4hbm {
namespace lyt {
class Picture : public Pane {
public:
Picture(u8 num);
Picture(const res::Picture* pResPic, const ResBlockSet& resBlockSet);
/* 0x08 */ virtual ~Picture();
/* 0x0C */ NW4HBM_UT_RUNTIME_TYPEINFO;
/* 0x18 */ virtual void DrawSelf(const DrawInfo& drawInfo);
/* 0x24 */ virtual ut::Color GetVtxColor(u32 idx) const;
/* 0x28 */ virtual void SetVtxColor(u32 idx, ut::Color value);
/* 0x34 */ virtual u8 GetVtxColorElement(u32 idx) const;
/* 0x38 */ virtual void SetVtxColorElement(u32 idx, u8 value);
/* 0x64 */ virtual void Append(TPLPalette* pTplRes);
/* 0x68 */ virtual void Append(const GXTexObj& texObj);
void SetTexCoordNum(u8 num);
u8 GetTexCoordNum() const;
void GetTexCoord(u32 idx, math::VEC2* coords) const;
void SetTexCoord(u32 idx, const math::VEC2* coords);
void Init(u8 texNum);
void ReserveTexCoord(u8 num);
private:
/* 0x00 (base) */
/* 0xD4 */ ut::Color mVtxColors[VERTEXCOLOR_MAX] ATTRIBUTE_ALIGN(4);
/* 0xE4 */ detail::TexCoordAry mTexCoordAry;
};
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,27 @@
#ifndef NW4HBM_LYT_RESOURCE_ACCESSOR_H
#define NW4HBM_LYT_RESOURCE_ACCESSOR_H
#include "revolution/types.h"
namespace nw4hbm {
namespace ut {
class Font;
}
namespace lyt {
class ResourceAccessor {
public:
ResourceAccessor();
/* 0x08 */ virtual ~ResourceAccessor();
/* 0x0C */ virtual void* GetResource(u32 resType, const char* name, u32* pSize) = 0;
/* 0x10 */ virtual ut::Font* GetFont(const char* name);
/* 0x00 (vtable) */
}; // size = 0x04
} // namespace lyt
} // namespace nw4hbm
#endif

View File

@ -0,0 +1,292 @@
#ifndef NW4HBM_LYT_RESOURCES_H
#define NW4HBM_LYT_RESOURCES_H
#include <revolution/gx.h>
#include <revolution/types.h>
#include "../ut/binaryFileFormat.h"
#include "lyt_types.h"
#include "resourceAccessor.h"
namespace nw4hbm {
namespace lyt {
typedef struct InflationLRTB {
/* 0x00 */ f32 l;
/* 0x04 */ f32 r;
/* 0x08 */ f32 t;
/* 0x0C */ f32 b;
} InflationLRTB;
typedef struct WindowFrameSize {
/* 0x00 */ f32 l;
/* 0x04 */ f32 r;
/* 0x08 */ f32 t;
/* 0x0C */ f32 b;
} WindowFrameSize;
class MaterialResourceNum {
public:
u8 GetTexMapNum() const { return detail::GetBits<>(bits, 0, 4); }
u8 GetTexSRTNum() const { return detail::GetBits<>(bits, 4, 4); }
u8 GetTexCoordGenNum() const { return detail::GetBits<>(bits, 8, 4); }
bool HasTevSwapTable() const { return detail::TestBit<>(bits, 12); }
u8 GetIndTexSRTNum() const { return detail::GetBits<>(bits, 13, 2); }
u8 GetIndTexStageNum() const { return detail::GetBits<>(bits, 15, 3); }
u8 GetTevStageNum() const { return detail::GetBits<>(bits, 18, 5); }
bool HasAlphaCompare() const { return detail::TestBit<>(bits, 23); }
bool HasBlendMode() const { return detail::TestBit<>(bits, 24); }
u8 GetChanCtrlNum() const { return detail::GetBits<>(bits, 25, 1); }
u8 GetMatColNum() const { return detail::GetBits<>(bits, 27, 1); }
private:
/* 0x00 */ u32 bits;
}; // size = 0x04
namespace res {
/*** COMMON ***/
typedef struct BinaryFileHeader {
/* 0x00 */ char signature[4];
/* 0x04 */ u16 byteOrder;
/* 0x06 */ u16 version;
/* 0x08 */ u32 fileSize;
/* 0x0C */ u16 headerSize;
/* 0x0E */ u16 dataBlocks;
} BinaryFileHeader; // size = 0x10
typedef struct DataBlockHeader {
/* 0x00 */ char kind[4];
/* 0x04 */ u32 size;
} DataBlockHeader; // size = 0x08
/*** ANIMATION ***/
typedef struct StepKey {
/* 0x00 */ f32 frame;
/* 0x04 */ u16 value;
/* 0x06 */ u16 padding;
} StepKey; // size = 0x08
typedef struct HermiteKey {
/* 0x00 */ f32 frame;
/* 0x04 */ f32 value;
/* 0x08 */ f32 slope;
} HermiteKey; // size = 0x0C
typedef struct AnimationInfo {
public:
/* 0x00 */ u32 kind;
/* 0x04 */ u8 num;
/* 0x05 */ u8 padding[3];
public:
static const u32 ANIM_INFO_PANE_PAIN_SRT = 'RLPA';
static const u32 ANIM_INFO_PANE_VERTEX_COLOR = 'RLVC';
static const u32 ANIM_INFO_PANE_VISIBILITY = 'RLVI';
static const u32 ANIM_INFO_MATERIAL_COLOR = 'RLMC';
static const u32 ANIM_INFO_MATERIAL_TEXTURE_PATTERN = 'RLTP';
static const u32 ANIM_INFO_MATERIAL_TEXTURE_SRT = 'RLTS';
static const u32 ANIM_INFO_MATERIAL_IND_TEX_SRT = 'RLIM';
} AnimationInfo;
typedef struct AnimationTarget {
/* 0x00 */ u8 id;
/* 0x01 */ u8 target;
/* 0x02 */ u8 curveType;
/* 0x03 */ u8 padding1;
/* 0x04 */ u16 keyNum;
/* 0x06 */ u8 padding2[2];
/* 0x08 */ u32 keysOffset;
} AnimationTarget; // size = 0x10
typedef struct AnimationBlock {
/* 0x00 */ DataBlockHeader blockHeader;
/* 0x08 */ u16 frameSize;
/* 0x0A */ u8 loop;
/* 0x0B */ u8 padding1;
/* 0x0C */ u16 fileNum;
/* 0x0E */ u16 animContNum;
/* 0x10 */ u32 animContOffsetsOffset;
} AnimationBlock; // size = 0x14
typedef struct AnimationContent {
public:
enum {
/* 0 */ ACType_Pane = 0,
/* 1 */ ACType_Material,
/* 2 */ ACType_Max
};
public:
/* 0x00 */ char name[20];
/* 0x14 */ u8 num;
/* 0x15 */ u8 type;
/* 0x16 */ u8 padding[2];
} AnimationContent; // size = 0x18
/*** MATERIAL ***/
typedef struct Texture {
/* 0x00 */ u32 nameStrOffset;
/* 0x04 */ u8 type;
/* 0x05 */ u8 padding[3];
} Texture; // size = 0x08
typedef struct Material {
/* 0x00 */ char name[20];
/* 0x14 */ GXColorS10 tevCols[TEVCOLOR_MAX];
/* 0x2C */ GXColor tevKCols[GX_MAX_KCOLOR];
/* 0x3C */ MaterialResourceNum resNum;
} Material; // size = 0x40
typedef struct TexMap {
/* 0x00 */ u16 texIdx;
/* 0x02 */ u8 wrapS;
/* 0x03 */ u8 wrapT;
} TexMap; // size = 0x04
/*** PANES ***/
static const u32 FILE_HEADER_SIGNATURE_ANIMATION = 'RLAN';
static const u32 FILE_HEADER_SIGNATURE_LAYOUT = 'RLYT';
static const u32 OBJECT_SIGNATURE_LAYOUT = 'lyt1';
static const u32 OBJECT_SIGNATURE_FONT_LIST = 'fnl1';
static const u32 OBJECT_SIGNATURE_MATERIAL_LIST = 'mat1';
static const u32 OBJECT_SIGNATURE_TEXTURE_LIST = 'txl1';
static const u32 OBJECT_SIGNATURE_PANE = 'pan1';
static const u32 OBJECT_SIGNATURE_PANE_CHILD_START = 'pas1';
static const u32 OBJECT_SIGNATURE_PANE_CHILD_END = 'pae1';
static const u32 OBJECT_SIGNATURE_PICTURE = 'pic1';
static const u32 OBJECT_SIGNATURE_BOUNDING = 'bnd1';
static const u32 OBJECT_SIGNATURE_WINDOW = 'wnd1';
static const u32 OBJECT_SIGNATURE_TEXT_BOX = 'txt1';
static const u32 OBJECT_SIGNATURE_GROUP = 'grp1';
static const u32 OBJECT_SIGNATURE_GROUP_CHILD_START = 'grs1';
static const u32 OBJECT_SIGNATURE_GROUP_CHILD_END = 'gre1';
static const u32 OBJECT_SIGNATURE_PANE_ANIM = 'pai1';
typedef struct Pane {
/* 0x00 */ DataBlockHeader blockHeader;
/* 0x08 */ u8 flag;
/* 0x09 */ u8 basePosition;
/* 0x0A */ u8 alpha;
/* 0x0B */ u8 padding;
/* 0x0C */ char name[16];
/* 0x1C */ char userData[8];
/* 0x24 */ math::VEC3 translate;
/* 0x30 */ math::VEC3 rotate;
/* 0x3C */ math::VEC2 scale;
/* 0x44 */ Size size;
} Pane; // size = 0x4C
typedef struct Bounding : Pane {
// (empty)
} Bounding;
typedef struct Picture : public Pane {
/* 0x4C */ u32 vtxCols[4];
/* 0x5C */ u16 materialIdx;
/* 0x5E */ u8 texCoordNum;
/* 0x5F */ u8 padding[1];
} Picture;
typedef struct Font {
/* 0x00 */ u32 nameStrOffset;
/* 0x04 */ u8 type;
u8 padding[3];
} Font;
typedef struct TextBox : public Pane {
/* 0x4C */ u16 textBufBytes;
/* 0x4E */ u16 textStrBytes;
/* 0x50 */ u16 materialIdx;
/* 0x52 */ u16 fontIdx;
/* 0x54 */ u8 textPosition;
u8 padding[3];
/* 0x58 */ u32 textStrOffset;
/* 0x5C */ u32 textCols[TEXTCOLOR_MAX];
/* 0x64 */ Size fontSize;
/* 0x6C */ f32 charSpace;
/* 0x70 */ f32 lineSpace;
} TextBox;
typedef struct WindowFrame {
/* 0x00 */ u16 materialIdx;
/* 0x02 */ u8 textureFlip;
/* 0x03 */ u8 padding1;
} WindowFrame;
typedef struct WindowContent {
/* 0x00 */ u32 vtxCols[VERTEXCOLOR_MAX];
/* 0x10 */ u16 materialIdx;
/* 0x12 */ u8 texCoordNum;
/* 0x13 */ u8 padding[1];
} WindowContent;
typedef struct Window : public Pane {
/* 0x4C */ InflationLRTB inflation;
/* 0x5C */ u8 frameNum;
/* 0x5D */ u8 padding1;
/* 0x5E */ u8 padding2;
/* 0x5F */ u8 padding3;
/* 0x60 */ u32 contentOffset;
/* 0x64 */ u32 frameOffsetTableOffset;
} Window;
/*** GROUP ***/
typedef struct Group {
/* 0x00 */ DataBlockHeader blockHeader;
/* 0x08 */ char name[16];
/* 0x18 */ u16 paneNum;
/* 0x19 */ u8 padding[2];
} Group;
/*** LAYOUT ***/
typedef struct Layout {
/* 0x00 */ DataBlockHeader blockHeader;
/* 0x08 */ u8 originType;
/* 0x09 */ u8 padding[3];
/* 0x0C */ Size layoutSize;
} Layout;
} // namespace res
namespace res {
typedef struct TextureList {
/* 0x00 */ DataBlockHeader blockHeader;
/* 0x08 */ u16 texNum;
u8 padding[2];
} TextureList;
typedef struct FontList {
/* 0x00 */ DataBlockHeader blockHeader;
/* 0x08 */ u16 fontNum;
u8 padding[2];
} FontList;
typedef struct MaterialList {
/* 0x00 */ DataBlockHeader blockHeader;
/* 0x08 */ u16 materialNum;
u8 padding[2];
} MaterialList;
} // namespace res
typedef struct ResBlockSet {
/* 0x00 */ const res::TextureList* pTextureList;
/* 0x04 */ const res::FontList* pFontList;
/* 0x08 */ const res::MaterialList* pMaterialList;
/* 0x0C */ ResourceAccessor* pResAccessor;
} ResBlockSet;
} // namespace lyt
} // namespace nw4hbm
#endif

Some files were not shown because too many files have changed in this diff Show More