mirror of https://github.com/zeldaret/tp
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:
parent
c8104b6d62
commit
8185d87f85
|
|
@ -2345,7 +2345,7 @@ revolution/gf/GFPixel.cpp:
|
|||
revolution/gf/GFTev.cpp:
|
||||
.text start:0x802B20AC end:0x802B210C
|
||||
|
||||
revolution/hbm/HBMBase.cpp:
|
||||
revolution/homebuttonLib/HBMBase.cpp:
|
||||
.text start:0x802B210C end:0x802BA91C
|
||||
.rodata start:0x803EF1C8 end:0x803EF478
|
||||
.data start:0x804253D8 end:0x80426308
|
||||
|
|
@ -2354,125 +2354,125 @@ revolution/hbm/HBMBase.cpp:
|
|||
.sbss start:0x8053B090 end:0x8053B098
|
||||
.sdata2 start:0x8053FCD0 end:0x8053FD30
|
||||
|
||||
revolution/hbm/HBMAnmController.cpp:
|
||||
revolution/homebuttonLib/HBMAnmController.cpp:
|
||||
.text start:0x802BA91C end:0x802BAA3C
|
||||
.data start:0x80426308 end:0x80426318
|
||||
|
||||
revolution/hbm/HBMFrameController.cpp:
|
||||
revolution/homebuttonLib/HBMFrameController.cpp:
|
||||
.text start:0x802BAA3C end:0x802BABDC
|
||||
.sdata2 start:0x8053FD30 end:0x8053FD38
|
||||
|
||||
revolution/hbm/HBMGUIManager.cpp:
|
||||
revolution/homebuttonLib/HBMGUIManager.cpp:
|
||||
.text start:0x802BABDC end:0x802BC260
|
||||
.data start:0x80426318 end:0x804264F8
|
||||
.sdata start:0x8053A118 end:0x8053A120
|
||||
.sbss start:0x8053B098 end:0x8053B0A0
|
||||
.sdata2 start:0x8053FD38 end:0x8053FD48
|
||||
|
||||
revolution/hbm/HBMController.cpp:
|
||||
revolution/homebuttonLib/HBMController.cpp:
|
||||
.text start:0x802BC260 end:0x802BCAB8
|
||||
.bss start:0x804C2448 end:0x804C25D8
|
||||
.sbss start:0x8053B0A0 end:0x8053B0A8
|
||||
.sdata2 start:0x8053FD48 end:0x8053FD58
|
||||
|
||||
revolution/hbm/HBMRemoteSpk.cpp:
|
||||
revolution/homebuttonLib/HBMRemoteSpk.cpp:
|
||||
.text start:0x802BCAB8 end:0x802BD2B8
|
||||
.data start:0x804264F8 end:0x80426568
|
||||
.sbss start:0x8053B0A8 end:0x8053B0B0
|
||||
|
||||
revolution/db/db_assert.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/db/db_assert.cpp:
|
||||
.text start:0x802BD2B8 end:0x802BD8C8
|
||||
.data start:0x80426568 end:0x80426618
|
||||
.bss start:0x804C25D8 end:0x804C2608
|
||||
.sdata start:0x8053A120 end:0x8053A128
|
||||
.sbss start:0x8053B0B0 end:0x8053B0C0
|
||||
|
||||
revolution/db/db_console.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/db/db_console.cpp:
|
||||
.text start:0x802BD8C8 end:0x802BE1C8
|
||||
.data start:0x80426618 end:0x80426738
|
||||
.bss start:0x804C2608 end:0x804C2A20
|
||||
.sdata start:0x8053A128 end:0x8053A130
|
||||
|
||||
revolution/db/db_DbgPrintBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/db/db_DbgPrintBase.cpp:
|
||||
.text start:0x802BE1C8 end:0x802BE208
|
||||
|
||||
revolution/db/db_directPrint.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/db/db_directPrint.cpp:
|
||||
.text start:0x802BE208 end:0x802BEC18
|
||||
.rodata start:0x803EF478 end:0x803EF730
|
||||
.data start:0x80426738 end:0x804267E8
|
||||
.bss start:0x804C2A20 end:0x804C2A60
|
||||
.sbss start:0x8053B0C0 end:0x8053B0C8
|
||||
|
||||
revolution/db/db_mapFile.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/db/db_mapFile.cpp:
|
||||
.text start:0x802BEC18 end:0x802BF52C
|
||||
.data start:0x804267E8 end:0x804269F0
|
||||
.bss start:0x804C2A60 end:0x804C2CA0
|
||||
.sdata start:0x8053A130 end:0x8053A138
|
||||
.sbss start:0x8053B0C8 end:0x8053B0D8
|
||||
|
||||
revolution/homebuttonLib/lyt_animation.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_animation.cpp:
|
||||
.text start:0x802BF52C end:0x802C049C
|
||||
.data start:0x804269F0 end:0x80426E60
|
||||
.sdata start:0x8053A138 end:0x8053A140
|
||||
.sdata2 start:0x8053FD58 end:0x8053FD78
|
||||
|
||||
revolution/homebuttonLib/lyt_arcResourceAccessor.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_arcResourceAccessor.cpp:
|
||||
.text start:0x802C049C end:0x802C0BA0
|
||||
.data start:0x80426E60 end:0x804270D8
|
||||
.sdata start:0x8053A140 end:0x8053A148
|
||||
|
||||
revolution/homebuttonLib/lyt_bounding.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_bounding.cpp:
|
||||
.text start:0x802C0BA0 end:0x802C0CB8
|
||||
.ctors start:0x803CE384 end:0x803CE388
|
||||
.data start:0x804270D8 end:0x80427140
|
||||
.sbss start:0x8053B0D8 end:0x8053B0E8
|
||||
|
||||
revolution/homebuttonLib/lyt_common.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_common.cpp:
|
||||
.text start:0x802C0CB8 end:0x802C1B38
|
||||
.data start:0x80427140 end:0x804271B0
|
||||
.bss start:0x804C2CA0 end:0x804C2CC0
|
||||
.sdata2 start:0x8053FD78 end:0x8053FD88
|
||||
|
||||
revolution/homebuttonLib/lyt_drawInfo.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_drawInfo.cpp:
|
||||
.text start:0x802C1B38 end:0x802C1BEC
|
||||
.data start:0x804271B0 end:0x804271C0
|
||||
.sdata2 start:0x8053FD88 end:0x8053FD90
|
||||
|
||||
revolution/homebuttonLib/lyt_group.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_group.cpp:
|
||||
.text start:0x802C1BEC end:0x802C2094
|
||||
.data start:0x804271C0 end:0x804272C0
|
||||
|
||||
revolution/homebuttonLib/lyt_layout.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_layout.cpp:
|
||||
.text start:0x802C2094 end:0x802C3048
|
||||
.data start:0x804272C0 end:0x80427528
|
||||
.sbss start:0x8053B0E8 end:0x8053B0F0
|
||||
.sdata2 start:0x8053FD90 end:0x8053FD98
|
||||
|
||||
revolution/homebuttonLib/lyt_material.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_material.cpp:
|
||||
.text start:0x802C3048 end:0x802C6768
|
||||
.data start:0x80427528 end:0x80427B28
|
||||
.sdata2 start:0x8053FD98 end:0x8053FDB8
|
||||
.sbss2 start:0x80540BD0 end:0x80540BE8
|
||||
|
||||
revolution/homebuttonLib/lyt_pane.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_pane.cpp:
|
||||
.text start:0x802C6768 end:0x802C7AC0
|
||||
.ctors start:0x803CE388 end:0x803CE38C
|
||||
.data start:0x80427B28 end:0x80427EB8
|
||||
.sbss start:0x8053B0F0 end:0x8053B0F8
|
||||
.sdata2 start:0x8053FDB8 end:0x8053FDD8
|
||||
|
||||
revolution/homebuttonLib/lyt_picture.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_picture.cpp:
|
||||
.text start:0x802C7AC0 end:0x802C81E0
|
||||
.ctors start:0x803CE38C end:0x803CE390
|
||||
.data start:0x80427EB8 end:0x804280E0
|
||||
.sbss start:0x8053B0F8 end:0x8053B100
|
||||
.sdata2 start:0x8053FDD8 end:0x8053FDE0
|
||||
|
||||
revolution/homebuttonLib/lyt_resourceAccessor.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_resourceAccessor.cpp:
|
||||
.text start:0x802C81E0 end:0x802C8238
|
||||
.data start:0x804280E0 end:0x804280F8
|
||||
|
||||
revolution/homebuttonLib/lyt_textBox.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_textBox.cpp:
|
||||
.text start:0x802C8238 end:0x802CB080
|
||||
.ctors start:0x803CE390 end:0x803CE394
|
||||
.data start:0x804280F8 end:0x80428770
|
||||
|
|
@ -2480,74 +2480,74 @@ revolution/homebuttonLib/lyt_textBox.cpp:
|
|||
.sbss start:0x8053B100 end:0x8053B108
|
||||
.sdata2 start:0x8053FDE0 end:0x8053FDF8
|
||||
|
||||
revolution/homebuttonLib/lyt_window.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_window.cpp:
|
||||
.text start:0x802CB080 end:0x802CD954
|
||||
.ctors start:0x803CE394 end:0x803CE398
|
||||
.data start:0x80428770 end:0x804289D0
|
||||
.sbss start:0x8053B108 end:0x8053B114
|
||||
.sdata2 start:0x8053FDF8 end:0x8053FE10
|
||||
|
||||
revolution/homebuttonLib/math_triangular.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/math/math_triangular.cpp:
|
||||
.text start:0x802CD954 end:0x802CDBC4
|
||||
.data start:0x804289D0 end:0x80429AE8
|
||||
.sdata2 start:0x8053FE10 end:0x8053FE30
|
||||
|
||||
revolution/homebuttonLib/snd_SoundArchivePlayer.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundArchivePlayer.cpp:
|
||||
.text start:0x802CDBC4 end:0x802CDC34
|
||||
.data start:0x80429AE8 end:0x80429B48
|
||||
|
||||
revolution/homebuttonLib/snd_SoundHandle.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundHandle.cpp:
|
||||
.text start:0x802CDC34 end:0x802CDC84
|
||||
|
||||
revolution/homebuttonLib/snd_SoundPlayer.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundPlayer.cpp:
|
||||
.text start:0x802CDC84 end:0x802CDD74
|
||||
.data start:0x80429B48 end:0x80429BB8
|
||||
.sdata2 start:0x8053FE30 end:0x8053FE38
|
||||
|
||||
revolution/homebuttonLib/snd_SoundStartable.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundStartable.cpp:
|
||||
.text start:0x802CDD74 end:0x802CDDE0
|
||||
|
||||
revolution/homebuttonLib/ut_binaryFileFormat.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_binaryFileFormat.cpp:
|
||||
.text start:0x802CDDE0 end:0x802CE038
|
||||
.data start:0x80429BB8 end:0x80429D08
|
||||
|
||||
revolution/homebuttonLib/ut_CharStrmReader.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_CharStrmReader.cpp:
|
||||
.text start:0x802CE038 end:0x802CE998
|
||||
.data start:0x80429D08 end:0x80429E50
|
||||
|
||||
revolution/homebuttonLib/ut_CharWriter.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_CharWriter.cpp:
|
||||
.text start:0x802CE998 end:0x802D2EF4
|
||||
.data start:0x80429E50 end:0x8042A130
|
||||
.bss start:0x804C2CC0 end:0x804C2CE0
|
||||
.sbss start:0x8053B114 end:0x8053B118
|
||||
.sdata2 start:0x8053FE38 end:0x8053FE58
|
||||
|
||||
revolution/homebuttonLib/ut_Font.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_Font.cpp:
|
||||
.text start:0x802D2EF4 end:0x802D30B8
|
||||
.data start:0x8042A130 end:0x8042A1A8
|
||||
|
||||
revolution/homebuttonLib/ut_LinkList.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_LinkList.cpp:
|
||||
.text start:0x802D30B8 end:0x802D3528
|
||||
.data start:0x8042A1A8 end:0x8042A350
|
||||
|
||||
revolution/homebuttonLib/ut_list.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_list.cpp:
|
||||
.text start:0x802D3528 end:0x802D38D0
|
||||
.data start:0x8042A350 end:0x8042A3B0
|
||||
|
||||
revolution/homebuttonLib/ut_ResFont.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_ResFont.cpp:
|
||||
.text start:0x802D38D0 end:0x802D48E8
|
||||
.data start:0x8042A3B0 end:0x8042AC68
|
||||
|
||||
revolution/homebuttonLib/ut_ResFontBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_ResFontBase.cpp:
|
||||
.text start:0x802D48E8 end:0x802D80C8
|
||||
.data start:0x8042AC68 end:0x8042AF80
|
||||
|
||||
revolution/homebuttonLib/ut_TagProcessorBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_TagProcessorBase.cpp:
|
||||
.text start:0x802D80C8 end:0x802D92D0
|
||||
.data start:0x8042AF80 end:0x8042B058
|
||||
.sdata2 start:0x8053FE58 end:0x8053FE60
|
||||
|
||||
revolution/homebuttonLib/ut_TextWriterBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_TextWriterBase.cpp:
|
||||
.text start:0x802D92D0 end:0x802E1FB4
|
||||
.ctors start:0x803CE398 end:0x803CE39C
|
||||
.data start:0x8042B058 end:0x8042B680
|
||||
|
|
|
|||
|
|
@ -2348,7 +2348,7 @@ revolution/gf/GFPixel.cpp:
|
|||
revolution/gf/GFTev.cpp:
|
||||
.text start:0x802B1D5C end:0x802B1DBC
|
||||
|
||||
revolution/hbm/HBMBase.cpp:
|
||||
revolution/homebuttonLib/HBMBase.cpp:
|
||||
.text start:0x802B1DBC end:0x802BA3D4
|
||||
.rodata start:0x803DA7C8 end:0x803DAA78
|
||||
.data start:0x804107F0 end:0x80411398
|
||||
|
|
@ -2357,95 +2357,95 @@ revolution/hbm/HBMBase.cpp:
|
|||
.sbss start:0x805210B0 end:0x805210B8
|
||||
.sdata2 start:0x80525D58 end:0x80525DB8
|
||||
|
||||
revolution/hbm/HBMAnmController.cpp:
|
||||
revolution/homebuttonLib/HBMAnmController.cpp:
|
||||
.text start:0x802BA3D4 end:0x802BA4E0
|
||||
.data start:0x80411398 end:0x804113A8
|
||||
|
||||
revolution/hbm/HBMFrameController.cpp:
|
||||
revolution/homebuttonLib/HBMFrameController.cpp:
|
||||
.text start:0x802BA4E0 end:0x802BA680
|
||||
.sdata2 start:0x80525DB8 end:0x80525DC0
|
||||
|
||||
revolution/hbm/HBMGUIManager.cpp:
|
||||
revolution/homebuttonLib/HBMGUIManager.cpp:
|
||||
.text start:0x802BA680 end:0x802BBAB8
|
||||
.data start:0x804113A8 end:0x80411500
|
||||
.sbss start:0x805210B8 end:0x805210C0
|
||||
.sdata2 start:0x80525DC0 end:0x80525DD0
|
||||
|
||||
revolution/hbm/HBMController.cpp:
|
||||
revolution/homebuttonLib/HBMController.cpp:
|
||||
.text start:0x802BBAB8 end:0x802BC310
|
||||
.bss start:0x804A8B78 end:0x804A8D08
|
||||
.sbss start:0x805210C0 end:0x805210C8
|
||||
.sdata2 start:0x80525DD0 end:0x80525DE0
|
||||
|
||||
revolution/hbm/HBMRemoteSpk.cpp:
|
||||
revolution/homebuttonLib/HBMRemoteSpk.cpp:
|
||||
.text start:0x802BC310 end:0x802BCA6C
|
||||
.data start:0x80411500 end:0x80411510
|
||||
.sbss start:0x805210C8 end:0x805210D0
|
||||
|
||||
revolution/db/db_DbgPrintBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/db/db_DbgPrintBase.cpp:
|
||||
.text start:0x802BCA6C end:0x802BCAAC
|
||||
|
||||
revolution/homebuttonLib/lyt_animation.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_animation.cpp:
|
||||
.text start:0x802BCAAC end:0x802BD61C
|
||||
.data start:0x80411510 end:0x80411530
|
||||
.sdata2 start:0x80525DE0 end:0x80525E00
|
||||
|
||||
revolution/homebuttonLib/lyt_arcResourceAccessor.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_arcResourceAccessor.cpp:
|
||||
.text start:0x802BD61C end:0x802BD990
|
||||
.data start:0x80411530 end:0x80411548
|
||||
.sdata start:0x80520160 end:0x80520168
|
||||
|
||||
revolution/homebuttonLib/lyt_bounding.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_bounding.cpp:
|
||||
.text start:0x802BD990 end:0x802BDAA8
|
||||
.ctors start:0x803B8DC8 end:0x803B8DCC
|
||||
.data start:0x80411548 end:0x804115B0
|
||||
.sbss start:0x805210D0 end:0x805210E0
|
||||
|
||||
revolution/homebuttonLib/lyt_common.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_common.cpp:
|
||||
.text start:0x802BDAA8 end:0x802BE8A0
|
||||
.bss start:0x804A8D08 end:0x804A8D28
|
||||
.sdata2 start:0x80525E00 end:0x80525E10
|
||||
|
||||
revolution/homebuttonLib/lyt_drawInfo.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_drawInfo.cpp:
|
||||
.text start:0x802BE8A0 end:0x802BE954
|
||||
.data start:0x804115B0 end:0x804115C0
|
||||
.sdata2 start:0x80525E10 end:0x80525E18
|
||||
|
||||
revolution/homebuttonLib/lyt_group.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_group.cpp:
|
||||
.text start:0x802BE954 end:0x802BEC74
|
||||
.data start:0x804115C0 end:0x804115D0
|
||||
|
||||
revolution/homebuttonLib/lyt_layout.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_layout.cpp:
|
||||
.text start:0x802BEC74 end:0x802BF8E4
|
||||
.data start:0x804115D0 end:0x80411608
|
||||
.sbss start:0x805210E0 end:0x805210E8
|
||||
.sdata2 start:0x80525E18 end:0x80525E20
|
||||
|
||||
revolution/homebuttonLib/lyt_material.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_material.cpp:
|
||||
.text start:0x802BF8E4 end:0x802C2CB8
|
||||
.data start:0x80411608 end:0x80411670
|
||||
.sdata2 start:0x80525E20 end:0x80525E40
|
||||
.sbss2 start:0x80526C50 end:0x80526C68
|
||||
|
||||
revolution/homebuttonLib/lyt_pane.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_pane.cpp:
|
||||
.text start:0x802C2CB8 end:0x802C3BEC
|
||||
.ctors start:0x803B8DCC end:0x803B8DD0
|
||||
.data start:0x80411670 end:0x804116D8
|
||||
.sbss start:0x805210E8 end:0x805210F0
|
||||
.sdata2 start:0x80525E40 end:0x80525E60
|
||||
|
||||
revolution/homebuttonLib/lyt_picture.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_picture.cpp:
|
||||
.text start:0x802C3BEC end:0x802C410C
|
||||
.ctors start:0x803B8DD0 end:0x803B8DD4
|
||||
.data start:0x804116D8 end:0x80411748
|
||||
.sbss start:0x805210F0 end:0x805210F8
|
||||
.sdata2 start:0x80525E60 end:0x80525E68
|
||||
|
||||
revolution/homebuttonLib/lyt_resourceAccessor.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_resourceAccessor.cpp:
|
||||
.text start:0x802C410C end:0x802C4164
|
||||
.data start:0x80411748 end:0x80411760
|
||||
|
||||
revolution/homebuttonLib/lyt_textBox.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_textBox.cpp:
|
||||
.text start:0x802C4164 end:0x802C5794
|
||||
.ctors start:0x803B8DD4 end:0x803B8DD8
|
||||
.data start:0x80411760 end:0x804117D8
|
||||
|
|
@ -2453,66 +2453,66 @@ revolution/homebuttonLib/lyt_textBox.cpp:
|
|||
.sbss start:0x805210F8 end:0x80521100
|
||||
.sdata2 start:0x80525E68 end:0x80525E80
|
||||
|
||||
revolution/homebuttonLib/lyt_window.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_window.cpp:
|
||||
.text start:0x802C5794 end:0x802C7C10
|
||||
.ctors start:0x803B8DD8 end:0x803B8DDC
|
||||
.data start:0x804117D8 end:0x80411890
|
||||
.sbss start:0x80521100 end:0x8052110C
|
||||
.sdata2 start:0x80525E80 end:0x80525E98
|
||||
|
||||
revolution/homebuttonLib/math_triangular.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/math/math_triangular.cpp:
|
||||
.text start:0x802C7C10 end:0x802C7E80
|
||||
.data start:0x80411890 end:0x804129A8
|
||||
.sdata2 start:0x80525E98 end:0x80525EB8
|
||||
|
||||
revolution/homebuttonLib/snd_SoundArchivePlayer.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundArchivePlayer.cpp:
|
||||
.text start:0x802C7E80 end:0x802C7E90
|
||||
|
||||
revolution/homebuttonLib/snd_SoundHandle.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundHandle.cpp:
|
||||
.text start:0x802C7E90 end:0x802C7EE0
|
||||
|
||||
revolution/homebuttonLib/snd_SoundPlayer.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundPlayer.cpp:
|
||||
.text start:0x802C7EE0 end:0x802C7F50
|
||||
|
||||
revolution/homebuttonLib/snd_SoundStartable.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundStartable.cpp:
|
||||
.text start:0x802C7F50 end:0x802C7FBC
|
||||
|
||||
revolution/homebuttonLib/ut_binaryFileFormat.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_binaryFileFormat.cpp:
|
||||
.text start:0x802C7FBC end:0x802C8030
|
||||
|
||||
revolution/homebuttonLib/ut_CharStrmReader.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_CharStrmReader.cpp:
|
||||
.text start:0x802C8030 end:0x802C8140
|
||||
|
||||
revolution/homebuttonLib/ut_CharWriter.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_CharWriter.cpp:
|
||||
.text start:0x802C8140 end:0x802C9BC4
|
||||
.bss start:0x804A8D28 end:0x804A8D48
|
||||
.sbss start:0x8052110C end:0x80521110
|
||||
.sdata2 start:0x80525EB8 end:0x80525ED8
|
||||
|
||||
revolution/homebuttonLib/ut_Font.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_Font.cpp:
|
||||
.text start:0x802C9BC4 end:0x802C9C6C
|
||||
.data start:0x804129A8 end:0x804129D8
|
||||
|
||||
revolution/homebuttonLib/ut_LinkList.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_LinkList.cpp:
|
||||
.text start:0x802C9C6C end:0x802C9D64
|
||||
|
||||
revolution/homebuttonLib/ut_list.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_list.cpp:
|
||||
.text start:0x802C9D64 end:0x802C9EC4
|
||||
|
||||
revolution/homebuttonLib/ut_ResFont.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_ResFont.cpp:
|
||||
.text start:0x802C9EC4 end:0x802CA1C8
|
||||
.data start:0x804129D8 end:0x80412A30
|
||||
|
||||
revolution/homebuttonLib/ut_ResFontBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_ResFontBase.cpp:
|
||||
.text start:0x802CA1C8 end:0x802CA798
|
||||
.data start:0x80412A30 end:0x80412AF0
|
||||
|
||||
revolution/homebuttonLib/ut_TagProcessorBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_TagProcessorBase.cpp:
|
||||
.text start:0x802CA798 end:0x802CAF58
|
||||
.data start:0x80412AF0 end:0x80412B48
|
||||
.sdata2 start:0x80525ED8 end:0x80525EE0
|
||||
|
||||
revolution/homebuttonLib/ut_TextWriterBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_TextWriterBase.cpp:
|
||||
.text start:0x802CAF58 end:0x802CC984
|
||||
.ctors start:0x803B8DDC end:0x803B8DE0
|
||||
.bss start:0x804A8D48 end:0x804A8D60
|
||||
|
|
|
|||
|
|
@ -2348,7 +2348,7 @@ revolution/gf/GFPixel.cpp:
|
|||
revolution/gf/GFTev.cpp:
|
||||
.text start:0x802B387C end:0x802B38DC
|
||||
|
||||
revolution/hbm/HBMBase.cpp:
|
||||
revolution/homebuttonLib/HBMBase.cpp:
|
||||
.text start:0x802B38DC end:0x802BBEF4
|
||||
.rodata start:0x803D8788 end:0x803D8A38
|
||||
.data start:0x8040E670 end:0x8040F218
|
||||
|
|
@ -2357,95 +2357,95 @@ revolution/hbm/HBMBase.cpp:
|
|||
.sbss start:0x8051EF20 end:0x8051EF28
|
||||
.sdata2 start:0x80523BB0 end:0x80523C10
|
||||
|
||||
revolution/hbm/HBMAnmController.cpp:
|
||||
revolution/homebuttonLib/HBMAnmController.cpp:
|
||||
.text start:0x802BBEF4 end:0x802BC000
|
||||
.data start:0x8040F218 end:0x8040F228
|
||||
|
||||
revolution/hbm/HBMFrameController.cpp:
|
||||
revolution/homebuttonLib/HBMFrameController.cpp:
|
||||
.text start:0x802BC000 end:0x802BC1A0
|
||||
.sdata2 start:0x80523C10 end:0x80523C18
|
||||
|
||||
revolution/hbm/HBMGUIManager.cpp:
|
||||
revolution/homebuttonLib/HBMGUIManager.cpp:
|
||||
.text start:0x802BC1A0 end:0x802BD5D8
|
||||
.data start:0x8040F228 end:0x8040F380
|
||||
.sbss start:0x8051EF28 end:0x8051EF30
|
||||
.sdata2 start:0x80523C18 end:0x80523C28
|
||||
|
||||
revolution/hbm/HBMController.cpp:
|
||||
revolution/homebuttonLib/HBMController.cpp:
|
||||
.text start:0x802BD5D8 end:0x802BDE30
|
||||
.bss start:0x804A69F8 end:0x804A6B88
|
||||
.sbss start:0x8051EF30 end:0x8051EF38
|
||||
.sdata2 start:0x80523C28 end:0x80523C38
|
||||
|
||||
revolution/hbm/HBMRemoteSpk.cpp:
|
||||
revolution/homebuttonLib/HBMRemoteSpk.cpp:
|
||||
.text start:0x802BDE30 end:0x802BE58C
|
||||
.data start:0x8040F380 end:0x8040F390
|
||||
.sbss start:0x8051EF38 end:0x8051EF40
|
||||
|
||||
revolution/db/db_DbgPrintBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/db/db_DbgPrintBase.cpp:
|
||||
.text start:0x802BE58C end:0x802BE5CC
|
||||
|
||||
revolution/homebuttonLib/lyt_animation.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_animation.cpp:
|
||||
.text start:0x802BE5CC end:0x802BF13C
|
||||
.data start:0x8040F390 end:0x8040F3B0
|
||||
.sdata2 start:0x80523C38 end:0x80523C58
|
||||
|
||||
revolution/homebuttonLib/lyt_arcResourceAccessor.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_arcResourceAccessor.cpp:
|
||||
.text start:0x802BF13C end:0x802BF4B0
|
||||
.data start:0x8040F3B0 end:0x8040F3C8
|
||||
.sdata start:0x8051DFD0 end:0x8051DFD8
|
||||
|
||||
revolution/homebuttonLib/lyt_bounding.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_bounding.cpp:
|
||||
.text start:0x802BF4B0 end:0x802BF5C8
|
||||
.ctors start:0x803BA888 end:0x803BA88C
|
||||
.data start:0x8040F3C8 end:0x8040F430
|
||||
.sbss start:0x8051EF40 end:0x8051EF50
|
||||
|
||||
revolution/homebuttonLib/lyt_common.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_common.cpp:
|
||||
.text start:0x802BF5C8 end:0x802C03C0
|
||||
.bss start:0x804A6B88 end:0x804A6BA8
|
||||
.sdata2 start:0x80523C58 end:0x80523C68
|
||||
|
||||
revolution/homebuttonLib/lyt_drawInfo.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_drawInfo.cpp:
|
||||
.text start:0x802C03C0 end:0x802C0474
|
||||
.data start:0x8040F430 end:0x8040F440
|
||||
.sdata2 start:0x80523C68 end:0x80523C70
|
||||
|
||||
revolution/homebuttonLib/lyt_group.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_group.cpp:
|
||||
.text start:0x802C0474 end:0x802C0794
|
||||
.data start:0x8040F440 end:0x8040F450
|
||||
|
||||
revolution/homebuttonLib/lyt_layout.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_layout.cpp:
|
||||
.text start:0x802C0794 end:0x802C1404
|
||||
.data start:0x8040F450 end:0x8040F488
|
||||
.sbss start:0x8051EF50 end:0x8051EF58
|
||||
.sdata2 start:0x80523C70 end:0x80523C78
|
||||
|
||||
revolution/homebuttonLib/lyt_material.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_material.cpp:
|
||||
.text start:0x802C1404 end:0x802C47D8
|
||||
.data start:0x8040F488 end:0x8040F4F0
|
||||
.sdata2 start:0x80523C78 end:0x80523C98
|
||||
.sbss2 start:0x80524A90 end:0x80524AA8
|
||||
|
||||
revolution/homebuttonLib/lyt_pane.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_pane.cpp:
|
||||
.text start:0x802C47D8 end:0x802C570C
|
||||
.ctors start:0x803BA88C end:0x803BA890
|
||||
.data start:0x8040F4F0 end:0x8040F558
|
||||
.sbss start:0x8051EF58 end:0x8051EF60
|
||||
.sdata2 start:0x80523C98 end:0x80523CB8
|
||||
|
||||
revolution/homebuttonLib/lyt_picture.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_picture.cpp:
|
||||
.text start:0x802C570C end:0x802C5C2C
|
||||
.ctors start:0x803BA890 end:0x803BA894
|
||||
.data start:0x8040F558 end:0x8040F5C8
|
||||
.sbss start:0x8051EF60 end:0x8051EF68
|
||||
.sdata2 start:0x80523CB8 end:0x80523CC0
|
||||
|
||||
revolution/homebuttonLib/lyt_resourceAccessor.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_resourceAccessor.cpp:
|
||||
.text start:0x802C5C2C end:0x802C5C84
|
||||
.data start:0x8040F5C8 end:0x8040F5E0
|
||||
|
||||
revolution/homebuttonLib/lyt_textBox.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_textBox.cpp:
|
||||
.text start:0x802C5C84 end:0x802C72B4
|
||||
.ctors start:0x803BA894 end:0x803BA898
|
||||
.data start:0x8040F5E0 end:0x8040F658
|
||||
|
|
@ -2453,66 +2453,66 @@ revolution/homebuttonLib/lyt_textBox.cpp:
|
|||
.sbss start:0x8051EF68 end:0x8051EF70
|
||||
.sdata2 start:0x80523CC0 end:0x80523CD8
|
||||
|
||||
revolution/homebuttonLib/lyt_window.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/lyt/lyt_window.cpp:
|
||||
.text start:0x802C72B4 end:0x802C9730
|
||||
.ctors start:0x803BA898 end:0x803BA89C
|
||||
.data start:0x8040F658 end:0x8040F710
|
||||
.sbss start:0x8051EF70 end:0x8051EF7C
|
||||
.sdata2 start:0x80523CD8 end:0x80523CF0
|
||||
|
||||
revolution/homebuttonLib/math_triangular.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/math/math_triangular.cpp:
|
||||
.text start:0x802C9730 end:0x802C99A0
|
||||
.data start:0x8040F710 end:0x80410828
|
||||
.sdata2 start:0x80523CF0 end:0x80523D10
|
||||
|
||||
revolution/homebuttonLib/snd_SoundArchivePlayer.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundArchivePlayer.cpp:
|
||||
.text start:0x802C99A0 end:0x802C99B0
|
||||
|
||||
revolution/homebuttonLib/snd_SoundHandle.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundHandle.cpp:
|
||||
.text start:0x802C99B0 end:0x802C9A00
|
||||
|
||||
revolution/homebuttonLib/snd_SoundPlayer.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundPlayer.cpp:
|
||||
.text start:0x802C9A00 end:0x802C9A70
|
||||
|
||||
revolution/homebuttonLib/snd_SoundStartable.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/snd/snd_SoundStartable.cpp:
|
||||
.text start:0x802C9A70 end:0x802C9ADC
|
||||
|
||||
revolution/homebuttonLib/ut_binaryFileFormat.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_binaryFileFormat.cpp:
|
||||
.text start:0x802C9ADC end:0x802C9B50
|
||||
|
||||
revolution/homebuttonLib/ut_CharStrmReader.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_CharStrmReader.cpp:
|
||||
.text start:0x802C9B50 end:0x802C9C60
|
||||
|
||||
revolution/homebuttonLib/ut_CharWriter.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_CharWriter.cpp:
|
||||
.text start:0x802C9C60 end:0x802CB6E4
|
||||
.bss start:0x804A6BA8 end:0x804A6BC8
|
||||
.sbss start:0x8051EF7C end:0x8051EF80
|
||||
.sdata2 start:0x80523D10 end:0x80523D30
|
||||
|
||||
revolution/homebuttonLib/ut_Font.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_Font.cpp:
|
||||
.text start:0x802CB6E4 end:0x802CB78C
|
||||
.data start:0x80410828 end:0x80410858
|
||||
|
||||
revolution/homebuttonLib/ut_LinkList.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_LinkList.cpp:
|
||||
.text start:0x802CB78C end:0x802CB884
|
||||
|
||||
revolution/homebuttonLib/ut_list.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_list.cpp:
|
||||
.text start:0x802CB884 end:0x802CB9E4
|
||||
|
||||
revolution/homebuttonLib/ut_ResFont.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_ResFont.cpp:
|
||||
.text start:0x802CB9E4 end:0x802CBCE8
|
||||
.data start:0x80410858 end:0x804108B0
|
||||
|
||||
revolution/homebuttonLib/ut_ResFontBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_ResFontBase.cpp:
|
||||
.text start:0x802CBCE8 end:0x802CC2B8
|
||||
.data start:0x804108B0 end:0x80410970
|
||||
|
||||
revolution/homebuttonLib/ut_TagProcessorBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_TagProcessorBase.cpp:
|
||||
.text start:0x802CC2B8 end:0x802CCA78
|
||||
.data start:0x80410970 end:0x804109C8
|
||||
.sdata2 start:0x80523D30 end:0x80523D38
|
||||
|
||||
revolution/homebuttonLib/ut_TextWriterBase.cpp:
|
||||
revolution/homebuttonLib/nw4hbm/ut/ut_TextWriterBase.cpp:
|
||||
.text start:0x802CCA78 end:0x802CE4A4
|
||||
.ctors start:0x803BA89C end:0x803BA8A0
|
||||
.bss start:0x804A6BC8 end:0x804A6BE0
|
||||
|
|
|
|||
72
configure.py
72
configure.py
|
|
@ -496,6 +496,14 @@ def RevolutionLib(lib_name: str, objects: List[Object]) -> Dict[str, Any]:
|
|||
"progress_category": "sdk",
|
||||
"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:
|
||||
return {
|
||||
"lib": lib_name,
|
||||
|
|
@ -1614,6 +1622,25 @@ config.libs = [
|
|||
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(
|
||||
"hio2",
|
||||
[
|
||||
|
|
@ -1693,6 +1720,51 @@ config.libs = [
|
|||
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",
|
||||
"mw_version": MWVersion(config.version),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef _DOLPHIN_CARD_H_
|
||||
#define _DOLPHIN_CARD_H_
|
||||
|
||||
#ifdef __REVOLUTION_SDK__
|
||||
#include <revolution/card.h>
|
||||
#else
|
||||
#include <dolphin/os.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
|
|
@ -320,3 +323,4 @@ s32 CARDWrite(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset);
|
|||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@
|
|||
#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1))
|
||||
#define TRUNC(n, a) (((u32)(n)) & ~((a)-1))
|
||||
|
||||
#ifndef decltype
|
||||
#define decltype __decltype__
|
||||
#endif
|
||||
|
||||
#define JUT_EXPECT(...)
|
||||
|
||||
#define _SDA_BASE_(dummy) 0
|
||||
|
|
@ -77,6 +81,9 @@ void* __memcpy(void*, const void*, int);
|
|||
|
||||
#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
|
||||
#define _HUGE_ENUF 1e+300
|
||||
#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
|
||||
|
|
@ -91,6 +98,14 @@ static const float INF = 2000000000.0f;
|
|||
#define READU32_BE(ptr, offset) \
|
||||
(((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.
|
||||
#define FORCE_DONT_INLINE \
|
||||
(void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; (void*)0; \
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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 mDoPrintf_vprintf_Interrupt(char const*, va_list);
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
@ -7,6 +7,16 @@
|
|||
extern "C" {
|
||||
#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 {
|
||||
/* 0x00 */ u16 vL;
|
||||
/* 0x02 */ u16 vDeltaL;
|
||||
|
|
@ -210,7 +220,45 @@ typedef struct AX_AUX_DATA_DPL2 {
|
|||
/* 0x00 */ s32* rs;
|
||||
} 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 (*AXAuxCallback)(void* chans, void* context);
|
||||
|
||||
#define AX_DSP_SLAVE_LENGTH 0xF80
|
||||
#define AX_MAX_VOICES 64
|
||||
|
|
@ -268,7 +316,7 @@ AXVPB* AXAcquireVoice(u32 priority, void (*callback)(void *), u32 userContext);
|
|||
void AXSetVoicePriority(AXVPB* p, u32 priority);
|
||||
|
||||
// AXAux
|
||||
void AXRegisterAuxACallback(void (*callback)(void*, void*), void* context);
|
||||
void AXRegisterAuxACallback(AXAuxCallback callback, void* context);
|
||||
void AXRegisterAuxBCallback(void (*callback)(void*, void*), void* context);
|
||||
|
||||
// AXCL
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define _REVOLUTION_AXFX_H_
|
||||
|
||||
#include <revolution/types.h>
|
||||
#include <revolution/ax.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -158,6 +159,9 @@ typedef struct AXFX_CHORUS {
|
|||
/* 0x98 */ u32 period;
|
||||
} AXFX_CHORUS;
|
||||
|
||||
typedef void* (*AXFXAllocFunc)(u32);
|
||||
typedef void (*AXFXFreeFunc)(void*);
|
||||
|
||||
// chorus
|
||||
int AXFXChorusInit(AXFX_CHORUS* c);
|
||||
int AXFXChorusShutdown(AXFX_CHORUS* c);
|
||||
|
|
@ -175,7 +179,6 @@ void DoCrossTalk(s32* l, s32* r, f32 cross, f32 invcross);
|
|||
int AXFXReverbHiInit(AXFX_REVERBHI* rev);
|
||||
int AXFXReverbHiShutdown(AXFX_REVERBHI* rev);
|
||||
int AXFXReverbHiSettings(AXFX_REVERBHI* rev);
|
||||
void AXFXReverbHiCallback(AXFX_BUFFERUPDATE* bufferUpdate, AXFX_REVERBHI* reverb);
|
||||
|
||||
// reverb_hi_4ch
|
||||
int AXFXReverbHiInitDpl2(AXFX_REVERBHI_DPL2* reverb);
|
||||
|
|
@ -189,6 +192,21 @@ int AXFXReverbStdShutdown(AXFX_REVERBSTD* rev);
|
|||
int AXFXReverbStdSettings(AXFX_REVERBSTD* rev);
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -2,10 +2,14 @@
|
|||
#define _REVOLUTION_HBM_H_
|
||||
|
||||
#include <revolution/kpad.h>
|
||||
#include <revolution/mem.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NW4HBM_VERSION(major, minor) ((major & 0xFF) << 8 | minor & 0xFF)
|
||||
|
||||
typedef enum HBMSelectBtnNum {
|
||||
HBM_SELECT_NULL = -1,
|
||||
|
||||
|
|
@ -18,8 +22,45 @@ typedef enum HBMSelectBtnNum {
|
|||
HBM_SELECT_MAX
|
||||
} HBMSelectBtnNum;
|
||||
|
||||
// TODO: move this later
|
||||
typedef struct MEMAllocator MEMAllocator;
|
||||
enum HBMSoundEvent_et {
|
||||
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 struct HBMDataInfo {
|
||||
|
|
@ -32,11 +73,11 @@ typedef struct HBMDataInfo {
|
|||
/* 0x18 */ int backFlag;
|
||||
/* 0x1C */ int region;
|
||||
/* 0x20 */ int cursor;
|
||||
/* 0x24 */ u32 memSize;
|
||||
/* 0x28 */ f32 frameDelta;
|
||||
/* 0x2C */ Vec2 adjust;
|
||||
/* 0x34 */ MEMAllocator* pAllocator;
|
||||
} HBMDataInfo; // size 0x38
|
||||
/* 0x28 */ u32 memSize;
|
||||
/* 0x2C */ f32 frameDelta;
|
||||
/* 0x30 */ Vec2 adjust;
|
||||
/* 0x38 */ MEMAllocator* pAllocator;
|
||||
} HBMDataInfo; // size 0x3C
|
||||
|
||||
typedef struct HBMKPadData {
|
||||
KPADStatus* kpad;
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -11,6 +11,8 @@ typedef struct Vec {
|
|||
f32 x, y, z;
|
||||
} Vec, *VecPtr, Point3d, *Point3dPtr;
|
||||
|
||||
typedef const VecPtr CVecPtr;
|
||||
|
||||
typedef struct {
|
||||
s16 x, y, z;
|
||||
} S16Vec, *S16VecPtr;
|
||||
|
|
|
|||
|
|
@ -320,46 +320,98 @@ extern BOOL __OSInReboot;
|
|||
|
||||
#define ASSERT(cond) ASSERTLINE(__LINE__, cond)
|
||||
|
||||
inline s16 __OSf32tos16(__REGISTER f32 inF) {
|
||||
#ifdef __MWERKS__
|
||||
register s16 out;
|
||||
u32 tmp;
|
||||
register u32* tmpPtr = &tmp;
|
||||
// clang-format off
|
||||
static inline u8 __OSf32tou8(register f32 in) {
|
||||
f32 a;
|
||||
register f32* ptr = &a;
|
||||
u8 r;
|
||||
|
||||
asm {
|
||||
psq_st inF, 0(tmpPtr), 0x1, 5
|
||||
lha out, 0(tmpPtr)
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
return out;
|
||||
#if defined(__MWERKS__)
|
||||
asm { psq_st in, 0(ptr), 1, 2 };
|
||||
#else
|
||||
# pragma unused(in)
|
||||
#endif
|
||||
|
||||
r = *(u8 *)ptr;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline void OSf32tos16(f32* f, s16* out) {
|
||||
*out = __OSf32tos16(*f);
|
||||
}
|
||||
static inline u16 __OSf32tou16(register f32 in) {
|
||||
f32 a;
|
||||
register f32* ptr = &a;
|
||||
u16 r;
|
||||
|
||||
inline u8 __OSf32tou8(__REGISTER f32 inF) {
|
||||
#ifdef __MWERKS__
|
||||
register u8 out;
|
||||
u32 tmp;
|
||||
register u32* tmpPtr = &tmp;
|
||||
// clang-format off
|
||||
|
||||
asm {
|
||||
psq_st inF, 0(tmpPtr), 0x1, 2
|
||||
lbz out, 0(tmpPtr)
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
return out;
|
||||
#if defined(__MWERKS__)
|
||||
asm { psq_st in, 0(ptr), 1, 3 };
|
||||
#else
|
||||
# pragma unused(in)
|
||||
#endif
|
||||
|
||||
r = *(u16 *)ptr;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline void OSf32tou8(f32* f, u8* out) {
|
||||
*out = __OSf32tou8(*f);
|
||||
static inline s16 __OSf32tos16(register f32 in) {
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
@ -11,15 +11,9 @@ typedef enum {
|
|||
WENC_FLAG_USER_INFO = (1 << 0),
|
||||
} WENCFlag;
|
||||
|
||||
typedef struct WENCInfo {
|
||||
/* 0x00 */ s32 xn;
|
||||
/* 0x04 */ s32 dl;
|
||||
/* 0x08 */ s32 qn;
|
||||
/* 0x0C */ s32 dn;
|
||||
/* 0x10 */ s32 dlh;
|
||||
/* 0x14 */ s32 dlq;
|
||||
/* 0x18 */ u8 padding[8];
|
||||
} WENCInfo;
|
||||
typedef struct {
|
||||
u8 data[32];
|
||||
} WENCInfo; // size 0x20
|
||||
|
||||
s32 WENCGetEncodeData(WENCInfo* info, u32 flag, const s16* pcmData, s32 samples, u8* adpcmData);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define _REVOLUTION_WPAD_H_
|
||||
|
||||
#include <revolution/types.h>
|
||||
#include <revolution/sc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -21,6 +22,22 @@ extern "C" {
|
|||
#define WPAD_BUTTON_C 0x4000
|
||||
#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_CHAN0 0
|
||||
|
|
@ -62,11 +79,44 @@ enum WPADResult_et {
|
|||
#define WPAD_CE6 (WPAD_E6 + 0)
|
||||
#define WPAD_CEBADE (WPAD_EBADE + 0)
|
||||
|
||||
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);
|
||||
#define WPAD_DEV_CORE 0
|
||||
#define WPAD_DEV_FS 1
|
||||
#define WPAD_DEV_CLASSIC 2
|
||||
#define WPAD_DEV_BALANCE_CHECKER 3
|
||||
#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 {
|
||||
/* 0x00 */ s16 x;
|
||||
|
|
@ -264,14 +314,33 @@ typedef struct WPADInfo {
|
|||
#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_MOTOR_STOP 0
|
||||
#define WPAD_MOTOR_RUMBLE 1
|
||||
|
||||
s32 WPADProbe(s32 chan, u32* devType);
|
||||
u8 WPADGetRadioSensitivity(s32 chan);
|
||||
void WPADRead(s32 chan, WPADStatus* status);
|
||||
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);
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -39,6 +39,14 @@ inline float tan(float 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) {
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,14 @@
|
|||
namespace std {
|
||||
using ::strlen;
|
||||
using ::strcpy;
|
||||
using ::wcslen;
|
||||
using ::strncpy;
|
||||
using ::strcmp;
|
||||
using ::strncmp;
|
||||
using ::strcat;
|
||||
|
||||
using ::memset;
|
||||
using ::memcpy;
|
||||
|
||||
inline char* strchr(char* str, int c) {
|
||||
return ::strchr(str, c);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,15 @@ int snprintf(char* s, size_t n, const char* format, ...);
|
|||
int vsnprintf(char* s, size_t n, 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
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define _MSL_COMMON_STRING_H
|
||||
|
||||
#include "stddef.h"
|
||||
#include "ansi_files.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -22,6 +23,8 @@ char* strncpy(char* dst, const char* src, size_t n);
|
|||
char* strcpy(char* dst, const char* src);
|
||||
size_t strlen(const char* str);
|
||||
|
||||
size_t wcslen(const wchar_t* s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1000,7 +1000,7 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
|
|||
if (format.argument_options == long_double_argument) {
|
||||
long_double_num = va_arg(arg, long double);
|
||||
} 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))) {
|
||||
|
|
@ -1015,7 +1015,7 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
|
|||
if (format.argument_options == long_double_argument) {
|
||||
long_double_num = va_arg(arg, long double);
|
||||
} 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))) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#ifndef __VA_ARG_H
|
||||
#define __VA_ARG_H
|
||||
|
||||
#include "dolphin/types.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct __va_list_struct {
|
||||
char gpr;
|
||||
|
|
@ -13,11 +15,7 @@ typedef struct __va_list_struct {
|
|||
|
||||
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);
|
||||
#endif
|
||||
|
||||
#ifndef __MWERKS__
|
||||
#define __builtin_va_info(...)
|
||||
|
|
@ -37,4 +35,12 @@ void* __va_arg(_va_list_struct*, int);
|
|||
|
||||
#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 */
|
||||
|
|
|
|||
|
|
@ -5,12 +5,15 @@
|
|||
#include "Z2AudioLib/Z2SeqMgr.h"
|
||||
#include "Z2AudioLib/Z2SeMgr.h"
|
||||
#include "Z2AudioLib/Z2SoundInfo.h"
|
||||
#include "Z2AudioLib/Z2AudioCS.h"
|
||||
#include "JSystem/JAudio2/JASCalc.h"
|
||||
#include "JSystem/JAudio2/JASDriverIF.h"
|
||||
#include "JSystem/JAudio2/JAUSectionHeap.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
|
||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||
#include "Z2AudioLib/Z2AudioCS.h"
|
||||
#endif
|
||||
|
||||
u16 seqCallback(JASTrack* track, u16 command) {
|
||||
switch (command) {
|
||||
case 0x1000:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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, ¤tDir);
|
||||
errors += VerifyFAT(card, ¤tFat);
|
||||
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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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_
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
Loading…
Reference in New Issue