From 129e419efefca984c2a763b597c618e6ae86f9df Mon Sep 17 00:00:00 2001 From: mrshigure Date: Mon, 30 Dec 2024 12:58:33 -0800 Subject: [PATCH 1/4] US: matched m423Dll --- config/GMPE01_00/rels/m423Dll/symbols.txt | 390 +- configure.py | 2 +- include/game/gamework_data.h | 99 +- src/REL/m409Dll/cursor.c | 12 +- src/REL/m409Dll/main.c | 8 +- src/REL/m415Dll/map.c | 14 +- src/REL/m423Dll/main.c | 5648 +++++++++++++++++++++ src/REL/m426Dll/main.c | 2 +- src/REL/m440Dll/main.c | 12 +- src/REL/m448Dll/main.c | 4 +- src/REL/modeltestDll/main.c | 8 +- 11 files changed, 5926 insertions(+), 273 deletions(-) create mode 100755 src/REL/m423Dll/main.c diff --git a/config/GMPE01_00/rels/m423Dll/symbols.txt b/config/GMPE01_00/rels/m423Dll/symbols.txt index bd1d1367..ddeb5a66 100644 --- a/config/GMPE01_00/rels/m423Dll/symbols.txt +++ b/config/GMPE01_00/rels/m423Dll/symbols.txt @@ -103,234 +103,234 @@ fn_1_1367C = .text:0x0001367C; // type:function size:0x148 fn_1_137C4 = .text:0x000137C4; // type:function size:0x78C _ctors = .ctors:0x00000000; // type:label scope:global data:4byte _dtors = .dtors:0x00000000; // type:label scope:global data:4byte -lbl_1_rodata_10 = .rodata:0x00000010; // type:object size:0x4 data:float -lbl_1_rodata_14 = .rodata:0x00000014; // type:object size:0x4 data:float -lbl_1_rodata_18 = .rodata:0x00000018; // type:object size:0x4 data:float -lbl_1_rodata_1C = .rodata:0x0000001C; // type:object size:0x4 data:float -lbl_1_rodata_20 = .rodata:0x00000020; // type:object size:0x4 data:float -lbl_1_rodata_24 = .rodata:0x00000024; // type:object size:0x4 data:float -lbl_1_rodata_28 = .rodata:0x00000028; // type:object size:0x4 data:float -lbl_1_rodata_2C = .rodata:0x0000002C; // type:object size:0x4 data:float -lbl_1_rodata_30 = .rodata:0x00000030; // type:object size:0x4 data:float -lbl_1_rodata_38 = .rodata:0x00000038; // type:object size:0x8 data:double -lbl_1_rodata_40 = .rodata:0x00000040; // type:object size:0x8 data:double -lbl_1_rodata_48 = .rodata:0x00000048; // type:object size:0x4 data:float -lbl_1_rodata_50 = .rodata:0x00000050; // type:object size:0x8 data:double -lbl_1_rodata_58 = .rodata:0x00000058; // type:object size:0x4 data:float -lbl_1_rodata_5C = .rodata:0x0000005C; // type:object size:0x4 data:float -lbl_1_rodata_60 = .rodata:0x00000060; // type:object size:0x4 data:float -lbl_1_rodata_64 = .rodata:0x00000064; // type:object size:0x4 data:float -lbl_1_rodata_68 = .rodata:0x00000068; // type:object size:0x4 data:float -lbl_1_rodata_6C = .rodata:0x0000006C; // type:object size:0x4 data:float -lbl_1_rodata_70 = .rodata:0x00000070; // type:object size:0x4 data:float -lbl_1_rodata_74 = .rodata:0x00000074; // type:object size:0x4 data:float -lbl_1_rodata_78 = .rodata:0x00000078; // type:object size:0x4 data:float -lbl_1_rodata_7C = .rodata:0x0000007C; // type:object size:0x4 data:float -lbl_1_rodata_80 = .rodata:0x00000080; // type:object size:0x4 data:float -lbl_1_rodata_84 = .rodata:0x00000084; // type:object size:0x4 data:float -lbl_1_rodata_88 = .rodata:0x00000088; // type:object size:0x4 data:float -lbl_1_rodata_8C = .rodata:0x0000008C; // type:object size:0x4 data:float -lbl_1_rodata_90 = .rodata:0x00000090; // type:object size:0x4 data:float -lbl_1_rodata_94 = .rodata:0x00000094; // type:object size:0x4 data:float -lbl_1_rodata_98 = .rodata:0x00000098; // type:object size:0x4 data:float -lbl_1_rodata_9C = .rodata:0x0000009C; // type:object size:0x4 data:float -lbl_1_rodata_A0 = .rodata:0x000000A0; // type:object size:0x8 data:double -lbl_1_rodata_A8 = .rodata:0x000000A8; // type:object size:0x4 data:float -lbl_1_rodata_B0 = .rodata:0x000000B0; // type:object size:0x8 data:double -lbl_1_rodata_B8 = .rodata:0x000000B8; // type:object size:0x4 data:float -lbl_1_rodata_C0 = .rodata:0x000000C0; // type:object size:0x8 data:double -lbl_1_rodata_C8 = .rodata:0x000000C8; // type:object size:0x4 data:float -lbl_1_rodata_CC = .rodata:0x000000CC; // type:object size:0x4 data:float -lbl_1_rodata_D0 = .rodata:0x000000D0; // type:object size:0x4 data:float -lbl_1_rodata_D4 = .rodata:0x000000D4; // type:object size:0x4 data:float -lbl_1_rodata_D8 = .rodata:0x000000D8; // type:object size:0x4 data:float -lbl_1_rodata_DC = .rodata:0x000000DC; // type:object size:0x4 data:float -lbl_1_rodata_E0 = .rodata:0x000000E0; // type:object size:0x4 data:float -lbl_1_rodata_E4 = .rodata:0x000000E4; // type:object size:0x4 data:float -lbl_1_rodata_E8 = .rodata:0x000000E8; // type:object size:0x4 data:float -lbl_1_rodata_EC = .rodata:0x000000EC; // type:object size:0x4 data:float -lbl_1_rodata_F0 = .rodata:0x000000F0; // type:object size:0x4 data:float -lbl_1_rodata_F4 = .rodata:0x000000F4; // type:object size:0x4 data:float -lbl_1_rodata_F8 = .rodata:0x000000F8; // type:object size:0x4 data:float -lbl_1_rodata_FC = .rodata:0x000000FC; // type:object size:0x4 data:float -lbl_1_rodata_100 = .rodata:0x00000100; // type:object size:0x4 data:float -lbl_1_rodata_104 = .rodata:0x00000104; // type:object size:0x4 data:float -lbl_1_rodata_108 = .rodata:0x00000108; // type:object size:0x4 data:float -lbl_1_rodata_10C = .rodata:0x0000010C; // type:object size:0x4 data:float -lbl_1_rodata_110 = .rodata:0x00000110; // type:object size:0x4 data:float -lbl_1_rodata_118 = .rodata:0x00000118; // type:object size:0x8 data:double -lbl_1_rodata_120 = .rodata:0x00000120; // type:object size:0x8 data:double -lbl_1_rodata_128 = .rodata:0x00000128; // type:object size:0x8 data:double -lbl_1_rodata_130 = .rodata:0x00000130; // type:object size:0x8 data:double -lbl_1_rodata_138 = .rodata:0x00000138; // type:object size:0x4 data:float -lbl_1_rodata_140 = .rodata:0x00000140; // type:object size:0x8 data:double -lbl_1_rodata_148 = .rodata:0x00000148; // type:object size:0x4 data:float -lbl_1_rodata_150 = .rodata:0x00000150; // type:object size:0x8 data:double -lbl_1_rodata_158 = .rodata:0x00000158; // type:object size:0x4 data:float -lbl_1_rodata_15C = .rodata:0x0000015C; // type:object size:0x4 data:float -lbl_1_rodata_160 = .rodata:0x00000160; // type:object size:0x4 data:float -lbl_1_rodata_164 = .rodata:0x00000164; // type:object size:0x4 data:float -lbl_1_rodata_168 = .rodata:0x00000168; // type:object size:0x4 data:float -lbl_1_rodata_16C = .rodata:0x0000016C; // type:object size:0x4 data:float -lbl_1_rodata_170 = .rodata:0x00000170; // type:object size:0x4 data:float -lbl_1_rodata_174 = .rodata:0x00000174; // type:object size:0x4 data:float -lbl_1_rodata_178 = .rodata:0x00000178; // type:object size:0x4 data:float -lbl_1_rodata_17C = .rodata:0x0000017C; // type:object size:0x4 data:float -lbl_1_rodata_180 = .rodata:0x00000180; // type:object size:0x4 data:float -lbl_1_rodata_184 = .rodata:0x00000184; // type:object size:0x4 data:float -lbl_1_rodata_188 = .rodata:0x00000188; // type:object size:0x8 data:double -lbl_1_rodata_190 = .rodata:0x00000190; // type:object size:0x4 data:float -lbl_1_rodata_194 = .rodata:0x00000194; // type:object size:0x4 data:float -lbl_1_rodata_198 = .rodata:0x00000198; // type:object size:0x4 data:float -lbl_1_rodata_19C = .rodata:0x0000019C; // type:object size:0x4 data:float -lbl_1_rodata_1A0 = .rodata:0x000001A0; // type:object size:0x4 data:float -lbl_1_rodata_1A4 = .rodata:0x000001A4; // type:object size:0x4 data:float -lbl_1_rodata_1A8 = .rodata:0x000001A8; // type:object size:0x4 data:float -lbl_1_rodata_1B0 = .rodata:0x000001B0; // type:object size:0x8 data:double -lbl_1_rodata_1B8 = .rodata:0x000001B8; // type:object size:0x4 data:float -lbl_1_rodata_1BC = .rodata:0x000001BC; // type:object size:0x4 data:float -lbl_1_rodata_1C0 = .rodata:0x000001C0; // type:object size:0x4 data:float -lbl_1_rodata_1C4 = .rodata:0x000001C4; // type:object size:0x4 data:float -lbl_1_rodata_1C8 = .rodata:0x000001C8; // type:object size:0x4 data:float -lbl_1_rodata_1CC = .rodata:0x000001CC; // type:object size:0x4 data:float -lbl_1_rodata_1D0 = .rodata:0x000001D0; // type:object size:0x4 data:float -lbl_1_rodata_1D4 = .rodata:0x000001D4; // type:object size:0x4 data:float -lbl_1_rodata_1D8 = .rodata:0x000001D8; // type:object size:0x4 data:float -lbl_1_rodata_1DC = .rodata:0x000001DC; // type:object size:0x4 data:float -lbl_1_rodata_1E0 = .rodata:0x000001E0; // type:object size:0x4 data:float -lbl_1_rodata_1E8 = .rodata:0x000001E8; // type:object size:0x8 data:double -lbl_1_rodata_1F0 = .rodata:0x000001F0; // type:object size:0x4 data:float -lbl_1_rodata_1F8 = .rodata:0x000001F8; // type:object size:0x8 data:double -lbl_1_rodata_200 = .rodata:0x00000200; // type:object size:0x4 data:float -lbl_1_rodata_208 = .rodata:0x00000208; // type:object size:0x8 data:double -lbl_1_rodata_210 = .rodata:0x00000210; // type:object size:0x4 data:float -lbl_1_rodata_214 = .rodata:0x00000214; // type:object size:0x4 data:float -lbl_1_rodata_218 = .rodata:0x00000218; // type:object size:0x4 data:float -lbl_1_rodata_21C = .rodata:0x0000021C; // type:object size:0x4 data:float -lbl_1_rodata_220 = .rodata:0x00000220; // type:object size:0x4 data:float -lbl_1_rodata_224 = .rodata:0x00000224; // type:object size:0x4 data:float -lbl_1_rodata_228 = .rodata:0x00000228; // type:object size:0x8 data:double -lbl_1_rodata_230 = .rodata:0x00000230; // type:object size:0x8 data:double -lbl_1_rodata_238 = .rodata:0x00000238; // type:object size:0x8 data:double -lbl_1_rodata_240 = .rodata:0x00000240; // type:object size:0x4 data:float -lbl_1_rodata_248 = .rodata:0x00000248; // type:object size:0x8 data:double -lbl_1_rodata_250 = .rodata:0x00000250; // type:object size:0x8 data:double -lbl_1_rodata_258 = .rodata:0x00000258; // type:object size:0x4 data:float -lbl_1_rodata_25C = .rodata:0x0000025C; // type:object size:0x4 data:float -lbl_1_rodata_260 = .rodata:0x00000260; // type:object size:0x4 data:float -lbl_1_rodata_264 = .rodata:0x00000264; // type:object size:0x4 data:float -lbl_1_rodata_268 = .rodata:0x00000268; // type:object size:0x4 data:float -lbl_1_rodata_26C = .rodata:0x0000026C; // type:object size:0x4 data:float -lbl_1_rodata_270 = .rodata:0x00000270; // type:object size:0x4 data:float -lbl_1_rodata_274 = .rodata:0x00000274; // type:object size:0x4 data:float -lbl_1_rodata_278 = .rodata:0x00000278; // type:object size:0x4 data:float -lbl_1_rodata_27C = .rodata:0x0000027C; // type:object size:0x4 data:float -lbl_1_rodata_280 = .rodata:0x00000280; // type:object size:0x4 data:float -lbl_1_rodata_284 = .rodata:0x00000284; // type:object size:0x4 data:float -lbl_1_rodata_288 = .rodata:0x00000288; // type:object size:0x4 data:float -lbl_1_rodata_28C = .rodata:0x0000028C; // type:object size:0x4 data:float -lbl_1_rodata_290 = .rodata:0x00000290; // type:object size:0x4 data:float -lbl_1_rodata_294 = .rodata:0x00000294; // type:object size:0x4 data:float -lbl_1_rodata_298 = .rodata:0x00000298; // type:object size:0x4 data:float -lbl_1_rodata_29C = .rodata:0x0000029C; // type:object size:0x4 data:float -lbl_1_rodata_2A0 = .rodata:0x000002A0; // type:object size:0x4 data:float -lbl_1_rodata_2A8 = .rodata:0x000002A8; // type:object size:0x8 data:double -lbl_1_rodata_2B0 = .rodata:0x000002B0; // type:object size:0x4 data:float -lbl_1_rodata_2B4 = .rodata:0x000002B4; // type:object size:0x4 data:float -lbl_1_rodata_2B8 = .rodata:0x000002B8; // type:object size:0x4 data:float -lbl_1_rodata_2BC = .rodata:0x000002BC; // type:object size:0x4 data:float -lbl_1_rodata_2C0 = .rodata:0x000002C0; // type:object size:0x4 data:float -lbl_1_rodata_2C4 = .rodata:0x000002C4; // type:object size:0x1 data:byte -lbl_1_rodata_2C8 = .rodata:0x000002C8; // type:object size:0x4 data:float -lbl_1_rodata_2CC = .rodata:0x000002CC; // type:object size:0x4 data:float -lbl_1_rodata_2D0 = .rodata:0x000002D0; // type:object size:0x4 data:float -lbl_1_rodata_2D4 = .rodata:0x000002D4; // type:object size:0x4 data:float -lbl_1_rodata_2D8 = .rodata:0x000002D8; // type:object size:0x4 data:float -lbl_1_rodata_2DC = .rodata:0x000002DC; // type:object size:0x4 data:float -lbl_1_rodata_2E0 = .rodata:0x000002E0; // type:object size:0x4 data:float -lbl_1_rodata_2E8 = .rodata:0x000002E8; // type:object size:0x8 data:double -lbl_1_rodata_2F0 = .rodata:0x000002F0; // type:object size:0x4 data:float -lbl_1_rodata_2F4 = .rodata:0x000002F4; // type:object size:0x4 data:float -lbl_1_rodata_2F8 = .rodata:0x000002F8; // type:object size:0x4 data:float -lbl_1_rodata_2FC = .rodata:0x000002FC; // type:object size:0x4 data:float -lbl_1_rodata_300 = .rodata:0x00000300; // type:object size:0x4 data:float -lbl_1_rodata_304 = .rodata:0x00000304; // type:object size:0x4 data:float -lbl_1_rodata_308 = .rodata:0x00000308; // type:object size:0x4 data:float -lbl_1_rodata_310 = .rodata:0x00000310; // type:object size:0x8 data:double -lbl_1_rodata_318 = .rodata:0x00000318; // type:object size:0x8 data:double -lbl_1_rodata_320 = .rodata:0x00000320; // type:object size:0x8 data:double -lbl_1_rodata_328 = .rodata:0x00000328; // type:object size:0x4 data:float -lbl_1_rodata_32C = .rodata:0x0000032C; // type:object size:0x4 data:float -lbl_1_rodata_330 = .rodata:0x00000330; // type:object size:0x4 data:float -lbl_1_rodata_338 = .rodata:0x00000338; // type:object size:0x8 data:double -lbl_1_rodata_340 = .rodata:0x00000340; // type:object size:0x8 data:double +lbl_1_rodata_10 = .rodata:0x00000010; // type:object size:0x4 scope:local data:float +lbl_1_rodata_14 = .rodata:0x00000014; // type:object size:0x4 scope:local data:float +lbl_1_rodata_18 = .rodata:0x00000018; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1C = .rodata:0x0000001C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_20 = .rodata:0x00000020; // type:object size:0x4 scope:local data:float +lbl_1_rodata_24 = .rodata:0x00000024; // type:object size:0x4 scope:local data:float +lbl_1_rodata_28 = .rodata:0x00000028; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2C = .rodata:0x0000002C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_30 = .rodata:0x00000030; // type:object size:0x4 scope:local data:float +lbl_1_rodata_38 = .rodata:0x00000038; // type:object size:0x8 scope:local data:double +lbl_1_rodata_40 = .rodata:0x00000040; // type:object size:0x8 scope:local data:double +lbl_1_rodata_48 = .rodata:0x00000048; // type:object size:0x4 scope:local data:float +lbl_1_rodata_50 = .rodata:0x00000050; // type:object size:0x8 scope:local data:double +lbl_1_rodata_58 = .rodata:0x00000058; // type:object size:0x4 scope:local data:float +lbl_1_rodata_5C = .rodata:0x0000005C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_60 = .rodata:0x00000060; // type:object size:0x4 scope:local data:float +lbl_1_rodata_64 = .rodata:0x00000064; // type:object size:0x4 scope:local data:float +lbl_1_rodata_68 = .rodata:0x00000068; // type:object size:0x4 scope:local data:float +lbl_1_rodata_6C = .rodata:0x0000006C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_70 = .rodata:0x00000070; // type:object size:0x4 scope:local data:float +lbl_1_rodata_74 = .rodata:0x00000074; // type:object size:0x4 scope:local data:float +lbl_1_rodata_78 = .rodata:0x00000078; // type:object size:0x4 scope:local data:float +lbl_1_rodata_7C = .rodata:0x0000007C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_80 = .rodata:0x00000080; // type:object size:0x4 scope:local data:float +lbl_1_rodata_84 = .rodata:0x00000084; // type:object size:0x4 scope:local data:float +lbl_1_rodata_88 = .rodata:0x00000088; // type:object size:0x4 scope:local data:float +lbl_1_rodata_8C = .rodata:0x0000008C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_90 = .rodata:0x00000090; // type:object size:0x4 scope:local data:float +lbl_1_rodata_94 = .rodata:0x00000094; // type:object size:0x4 scope:local data:float +lbl_1_rodata_98 = .rodata:0x00000098; // type:object size:0x4 scope:local data:float +lbl_1_rodata_9C = .rodata:0x0000009C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_A0 = .rodata:0x000000A0; // type:object size:0x8 scope:local data:double +lbl_1_rodata_A8 = .rodata:0x000000A8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_B0 = .rodata:0x000000B0; // type:object size:0x8 scope:local data:double +lbl_1_rodata_B8 = .rodata:0x000000B8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_C0 = .rodata:0x000000C0; // type:object size:0x8 scope:local data:double +lbl_1_rodata_C8 = .rodata:0x000000C8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_CC = .rodata:0x000000CC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_D0 = .rodata:0x000000D0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_D4 = .rodata:0x000000D4; // type:object size:0x4 scope:local data:float +lbl_1_rodata_D8 = .rodata:0x000000D8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_DC = .rodata:0x000000DC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_E0 = .rodata:0x000000E0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_E4 = .rodata:0x000000E4; // type:object size:0x4 scope:local data:float +lbl_1_rodata_E8 = .rodata:0x000000E8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_EC = .rodata:0x000000EC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_F0 = .rodata:0x000000F0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_F4 = .rodata:0x000000F4; // type:object size:0x4 scope:local data:float +lbl_1_rodata_F8 = .rodata:0x000000F8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_FC = .rodata:0x000000FC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_100 = .rodata:0x00000100; // type:object size:0x4 scope:local data:float +lbl_1_rodata_104 = .rodata:0x00000104; // type:object size:0x4 scope:local data:float +lbl_1_rodata_108 = .rodata:0x00000108; // type:object size:0x4 scope:local data:float +lbl_1_rodata_10C = .rodata:0x0000010C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_110 = .rodata:0x00000110; // type:object size:0x4 scope:local data:float +lbl_1_rodata_118 = .rodata:0x00000118; // type:object size:0x8 scope:local data:double +lbl_1_rodata_120 = .rodata:0x00000120; // type:object size:0x8 scope:local data:double +lbl_1_rodata_128 = .rodata:0x00000128; // type:object size:0x8 scope:local data:double +lbl_1_rodata_130 = .rodata:0x00000130; // type:object size:0x8 scope:local data:double +lbl_1_rodata_138 = .rodata:0x00000138; // type:object size:0x4 scope:local data:float +lbl_1_rodata_140 = .rodata:0x00000140; // type:object size:0x8 scope:local data:double +lbl_1_rodata_148 = .rodata:0x00000148; // type:object size:0x4 scope:local data:float +lbl_1_rodata_150 = .rodata:0x00000150; // type:object size:0x8 scope:local data:double +lbl_1_rodata_158 = .rodata:0x00000158; // type:object size:0x4 scope:local data:float +lbl_1_rodata_15C = .rodata:0x0000015C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_160 = .rodata:0x00000160; // type:object size:0x4 scope:local data:float +lbl_1_rodata_164 = .rodata:0x00000164; // type:object size:0x4 scope:local data:float +lbl_1_rodata_168 = .rodata:0x00000168; // type:object size:0x4 scope:local data:float +lbl_1_rodata_16C = .rodata:0x0000016C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_170 = .rodata:0x00000170; // type:object size:0x4 scope:local data:float +lbl_1_rodata_174 = .rodata:0x00000174; // type:object size:0x4 scope:local data:float +lbl_1_rodata_178 = .rodata:0x00000178; // type:object size:0x4 scope:local data:float +lbl_1_rodata_17C = .rodata:0x0000017C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_180 = .rodata:0x00000180; // type:object size:0x4 scope:local data:float +lbl_1_rodata_184 = .rodata:0x00000184; // type:object size:0x4 scope:local data:float +lbl_1_rodata_188 = .rodata:0x00000188; // type:object size:0x8 scope:local data:double +lbl_1_rodata_190 = .rodata:0x00000190; // type:object size:0x4 scope:local data:float +lbl_1_rodata_194 = .rodata:0x00000194; // type:object size:0x4 scope:local data:float +lbl_1_rodata_198 = .rodata:0x00000198; // type:object size:0x4 scope:local data:float +lbl_1_rodata_19C = .rodata:0x0000019C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1A0 = .rodata:0x000001A0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1A4 = .rodata:0x000001A4; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1A8 = .rodata:0x000001A8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1B0 = .rodata:0x000001B0; // type:object size:0x8 scope:local data:double +lbl_1_rodata_1B8 = .rodata:0x000001B8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1BC = .rodata:0x000001BC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1C0 = .rodata:0x000001C0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1C4 = .rodata:0x000001C4; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1C8 = .rodata:0x000001C8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1CC = .rodata:0x000001CC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1D0 = .rodata:0x000001D0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1D4 = .rodata:0x000001D4; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1D8 = .rodata:0x000001D8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1DC = .rodata:0x000001DC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1E0 = .rodata:0x000001E0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1E8 = .rodata:0x000001E8; // type:object size:0x8 scope:local data:double +lbl_1_rodata_1F0 = .rodata:0x000001F0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_1F8 = .rodata:0x000001F8; // type:object size:0x8 scope:local data:double +lbl_1_rodata_200 = .rodata:0x00000200; // type:object size:0x4 scope:local data:float +lbl_1_rodata_208 = .rodata:0x00000208; // type:object size:0x8 scope:local data:double +lbl_1_rodata_210 = .rodata:0x00000210; // type:object size:0x4 scope:local data:float +lbl_1_rodata_214 = .rodata:0x00000214; // type:object size:0x4 scope:local data:float +lbl_1_rodata_218 = .rodata:0x00000218; // type:object size:0x4 scope:local data:float +lbl_1_rodata_21C = .rodata:0x0000021C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_220 = .rodata:0x00000220; // type:object size:0x4 scope:local data:float +lbl_1_rodata_224 = .rodata:0x00000224; // type:object size:0x4 scope:local data:float +lbl_1_rodata_228 = .rodata:0x00000228; // type:object size:0x8 scope:local data:double +lbl_1_rodata_230 = .rodata:0x00000230; // type:object size:0x8 scope:local data:double +lbl_1_rodata_238 = .rodata:0x00000238; // type:object size:0x8 scope:local data:double +lbl_1_rodata_240 = .rodata:0x00000240; // type:object size:0x4 scope:local data:float +lbl_1_rodata_248 = .rodata:0x00000248; // type:object size:0x8 scope:local data:double +lbl_1_rodata_250 = .rodata:0x00000250; // type:object size:0x8 scope:local data:double +lbl_1_rodata_258 = .rodata:0x00000258; // type:object size:0x4 scope:local data:float +lbl_1_rodata_25C = .rodata:0x0000025C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_260 = .rodata:0x00000260; // type:object size:0x4 scope:local data:float +lbl_1_rodata_264 = .rodata:0x00000264; // type:object size:0x4 scope:local data:float +lbl_1_rodata_268 = .rodata:0x00000268; // type:object size:0x4 scope:local data:float +lbl_1_rodata_26C = .rodata:0x0000026C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_270 = .rodata:0x00000270; // type:object size:0x4 scope:local data:float +lbl_1_rodata_274 = .rodata:0x00000274; // type:object size:0x4 scope:local data:float +lbl_1_rodata_278 = .rodata:0x00000278; // type:object size:0x4 scope:local data:float +lbl_1_rodata_27C = .rodata:0x0000027C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_280 = .rodata:0x00000280; // type:object size:0x4 scope:local data:float +lbl_1_rodata_284 = .rodata:0x00000284; // type:object size:0x4 scope:local data:float +lbl_1_rodata_288 = .rodata:0x00000288; // type:object size:0x4 scope:local data:float +lbl_1_rodata_28C = .rodata:0x0000028C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_290 = .rodata:0x00000290; // type:object size:0x4 scope:local data:float +lbl_1_rodata_294 = .rodata:0x00000294; // type:object size:0x4 scope:local data:float +lbl_1_rodata_298 = .rodata:0x00000298; // type:object size:0x4 scope:local data:float +lbl_1_rodata_29C = .rodata:0x0000029C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2A0 = .rodata:0x000002A0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2A8 = .rodata:0x000002A8; // type:object size:0x8 scope:local data:double +lbl_1_rodata_2B0 = .rodata:0x000002B0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2B4 = .rodata:0x000002B4; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2B8 = .rodata:0x000002B8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2BC = .rodata:0x000002BC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2C0 = .rodata:0x000002C0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2C4 = .rodata:0x000002C4; // type:object size:0x4 scope:local data:byte +lbl_1_rodata_2C8 = .rodata:0x000002C8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2CC = .rodata:0x000002CC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2D0 = .rodata:0x000002D0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2D4 = .rodata:0x000002D4; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2D8 = .rodata:0x000002D8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2DC = .rodata:0x000002DC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2E0 = .rodata:0x000002E0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2E8 = .rodata:0x000002E8; // type:object size:0x8 scope:local data:double +lbl_1_rodata_2F0 = .rodata:0x000002F0; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2F4 = .rodata:0x000002F4; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2F8 = .rodata:0x000002F8; // type:object size:0x4 scope:local data:float +lbl_1_rodata_2FC = .rodata:0x000002FC; // type:object size:0x4 scope:local data:float +lbl_1_rodata_300 = .rodata:0x00000300; // type:object size:0x4 scope:local data:float +lbl_1_rodata_304 = .rodata:0x00000304; // type:object size:0x4 scope:local data:float +lbl_1_rodata_308 = .rodata:0x00000308; // type:object size:0x4 scope:local data:float +lbl_1_rodata_310 = .rodata:0x00000310; // type:object size:0x8 scope:local data:double +lbl_1_rodata_318 = .rodata:0x00000318; // type:object size:0x8 scope:local data:double +lbl_1_rodata_320 = .rodata:0x00000320; // type:object size:0x8 scope:local data:double +lbl_1_rodata_328 = .rodata:0x00000328; // type:object size:0x4 scope:local data:float +lbl_1_rodata_32C = .rodata:0x0000032C; // type:object size:0x4 scope:local data:float +lbl_1_rodata_330 = .rodata:0x00000330; // type:object size:0x4 scope:local data:float +lbl_1_rodata_338 = .rodata:0x00000338; // type:object size:0x8 scope:local data:double +lbl_1_rodata_340 = .rodata:0x00000340; // type:object size:0x8 scope:local data:double lbl_1_data_0 = .data:0x00000000; // type:object size:0x38 data:float -lbl_1_data_38 = .data:0x00000038; // type:object size:0x118 +lbl_1_data_38 = .data:0x00000038; // type:object size:0x118 data:float lbl_1_data_150 = .data:0x00000150; // type:object size:0x30 data:float lbl_1_data_180 = .data:0x00000180; // type:object size:0x30 data:float -lbl_1_data_1B0 = .data:0x000001B0; // type:object size:0x24 -lbl_1_data_1D4 = .data:0x000001D4; // type:object size:0xC -lbl_1_data_1E0 = .data:0x000001E0; // type:object size:0xC -lbl_1_data_1EC = .data:0x000001EC; // type:object size:0xC -lbl_1_data_1F8 = .data:0x000001F8; // type:object size:0x24 -lbl_1_data_21C = .data:0x0000021C; // type:object size:0xC -lbl_1_data_228 = .data:0x00000228; // type:object size:0xC +lbl_1_data_1B0 = .data:0x000001B0; // type:object size:0x24 data:float +lbl_1_data_1D4 = .data:0x000001D4; // type:object size:0xC data:float +lbl_1_data_1E0 = .data:0x000001E0; // type:object size:0xC data:float +lbl_1_data_1EC = .data:0x000001EC; // type:object size:0xC data:float +lbl_1_data_1F8 = .data:0x000001F8; // type:object size:0x23 scope:local data:string +lbl_1_data_21C = .data:0x0000021C; // type:object size:0xC data:float +lbl_1_data_228 = .data:0x00000228; // type:object size:0xC data:float lbl_1_data_234 = .data:0x00000234; // type:object size:0x4 lbl_1_data_238 = .data:0x00000238; // type:object size:0x18 lbl_1_data_250 = .data:0x00000250; // type:object size:0x18 jumptable_1_data_268 = .data:0x00000268; // type:object size:0x30 scope:local -lbl_1_data_298 = .data:0x00000298; // type:object size:0x1 data:byte -lbl_1_data_29C = .data:0x0000029C; // type:object size:0x30 -lbl_1_data_2CC = .data:0x000002CC; // type:object size:0x20 -lbl_1_data_2EC = .data:0x000002EC; // type:object size:0x20 -lbl_1_data_30C = .data:0x0000030C; // type:object size:0x4 -lbl_1_data_310 = .data:0x00000310; // type:object size:0x1 data:byte +lbl_1_data_298 = .data:0x00000298; // type:object size:0x4 data:byte +lbl_1_data_29C = .data:0x0000029C; // type:object size:0x30 data:float +lbl_1_data_2CC = .data:0x000002CC; // type:object size:0x20 data:float +lbl_1_data_2EC = .data:0x000002EC; // type:object size:0x20 data:float +lbl_1_data_30C = .data:0x0000030C; // type:object size:0x4 data:byte +lbl_1_data_310 = .data:0x00000310; // type:object size:0x4 data:byte lbl_1_data_314 = .data:0x00000314; // type:object size:0x20 data:4byte -lbl_1_data_334 = .data:0x00000334; // type:object size:0x30 -lbl_1_data_364 = .data:0x00000364; // type:object size:0x24 +lbl_1_data_334 = .data:0x00000334; // type:object size:0x30 data:float +lbl_1_data_364 = .data:0x00000364; // type:object size:0x24 data:float lbl_1_data_388 = .data:0x00000388; // type:object size:0x4 data:byte -lbl_1_data_38C = .data:0x0000038C; // type:object size:0x1F data:string +lbl_1_data_38C = .data:0x0000038C; // type:object size:0x1F scope:local data:string lbl_1_data_3AB = .data:0x000003AB; // type:object size:0x4 data:byte lbl_1_data_3AF = .data:0x000003AF; // type:object size:0x4 data:byte lbl_1_data_3B3 = .data:0x000003B3; // type:object size:0x4 data:byte -lbl_1_data_3B8 = .data:0x000003B8; // type:object size:0xF0 +lbl_1_data_3B8 = .data:0x000003B8; // type:object size:0xF0 data:float lbl_1_data_4A8 = .data:0x000004A8; // type:object size:0x54 lbl_1_data_4FC = .data:0x000004FC; // type:object size:0xC lbl_1_data_508 = .data:0x00000508; // type:object size:0x18 -lbl_1_data_520 = .data:0x00000520; // type:object size:0x6 +lbl_1_data_520 = .data:0x00000520; // type:object size:0x6 data:2byte lbl_1_data_526 = .data:0x00000526; // type:object size:0x6 lbl_1_data_52C = .data:0x0000052C; // type:object size:0x8 lbl_1_data_534 = .data:0x00000534; // type:object size:0x40 lbl_1_data_574 = .data:0x00000574; // type:object size:0xC lbl_1_data_580 = .data:0x00000580; // type:object size:0x58 lbl_1_data_5D8 = .data:0x000005D8; // type:object size:0x10 -lbl_1_data_5E8 = .data:0x000005E8; // type:object size:0xC data:4byte -lbl_1_data_5F4 = .data:0x000005F4; // type:object size:0x1 data:byte -lbl_1_data_5F8 = .data:0x000005F8; // type:object size:0x1 data:byte +lbl_1_data_5E8 = .data:0x000005E8; // type:object size:0xC data:float +lbl_1_data_5F4 = .data:0x000005F4; // type:object size:0x4 data:byte +lbl_1_data_5F8 = .data:0x000005F8; // type:object size:0x4 data:byte jumptable_1_data_5FC = .data:0x000005FC; // type:object size:0x34 scope:local -lbl_1_data_630 = .data:0x00000630; // type:object size:0x1 data:byte +lbl_1_data_630 = .data:0x00000630; // type:object size:0x4 data:byte jumptable_1_data_634 = .data:0x00000634; // type:object size:0x34 scope:local lbl_1_data_668 = .data:0x00000668; // type:object size:0x10 -lbl_1_data_678 = .data:0x00000678; // type:object size:0x10 +lbl_1_data_678 = .data:0x00000678; // type:object size:0x10 data:float lbl_1_data_688 = .data:0x00000688; // type:object size:0x20 lbl_1_data_6A8 = .data:0x000006A8; // type:object size:0x20 data:4byte lbl_1_data_6C8 = .data:0x000006C8; // type:object size:0x10 -lbl_1_data_6D8 = .data:0x000006D8; // type:object size:0x20 +lbl_1_data_6D8 = .data:0x000006D8; // type:object size:0x20 data:float lbl_1_data_6F8 = .data:0x000006F8; // type:object size:0x20 lbl_1_data_718 = .data:0x00000718; // type:object size:0x20 lbl_1_data_738 = .data:0x00000738; // type:object size:0x20 -lbl_1_data_758 = .data:0x00000758; // type:object size:0x1 data:byte -lbl_1_data_75C = .data:0x0000075C; // type:object size:0x48 +lbl_1_data_758 = .data:0x00000758; // type:object size:0x4 data:byte +lbl_1_data_75C = .data:0x0000075C; // type:object size:0x48 data:2byte jumptable_1_data_7A4 = .data:0x000007A4; // type:object size:0x20 scope:local lbl_1_data_7C4 = .data:0x000007C4; // type:object size:0x18 jumptable_1_data_7DC = .data:0x000007DC; // type:object size:0x20 scope:local -lbl_1_data_7FC = .data:0x000007FC; // type:object size:0x20 +lbl_1_data_7FC = .data:0x000007FC; // type:object size:0x20 data:byte lbl_1_data_81C = .data:0x0000081C; // type:object size:0x20 -lbl_1_data_83C = .data:0x0000083C; // type:object size:0x8 -lbl_1_data_844 = .data:0x00000844; // type:object size:0x60 -lbl_1_data_8A4 = .data:0x000008A4; // type:object size:0x20 -lbl_1_data_8C4 = .data:0x000008C4; // type:object size:0x30 -lbl_1_data_8F4 = .data:0x000008F4; // type:object size:0x20 +lbl_1_data_83C = .data:0x0000083C; // type:object size:0x8 data:2byte +lbl_1_data_844 = .data:0x00000844; // type:object size:0x60 data:2byte +lbl_1_data_8A4 = .data:0x000008A4; // type:object size:0x20 data:float +lbl_1_data_8C4 = .data:0x000008C4; // type:object size:0x30 data:float +lbl_1_data_8F4 = .data:0x000008F4; // type:object size:0x20 data:float lbl_1_data_914 = .data:0x00000914; // type:object size:0x6 data:byte lbl_1_bss_0 = .bss:0x00000000; // type:object size:0x4 data:4byte lbl_1_bss_4 = .bss:0x00000004; // type:object size:0x3C data:4byte @@ -359,7 +359,7 @@ lbl_1_bss_EC = .bss:0x000000EC; // type:object size:0x10 data:4byte lbl_1_bss_FC = .bss:0x000000FC; // type:object size:0x4 data:4byte lbl_1_bss_100 = .bss:0x00000100; // type:object size:0x4 data:4byte lbl_1_bss_104 = .bss:0x00000104; // type:object size:0x4 data:4byte -lbl_1_bss_108 = .bss:0x00000108; // type:object size:0x8 data:4byte +lbl_1_bss_108 = .bss:0x00000108; // type:object size:0x4 data:4byte lbl_1_bss_110 = .bss:0x00000110; // type:object size:0x4 data:4byte lbl_1_bss_114 = .bss:0x00000114; // type:object size:0x4 data:4byte lbl_1_bss_118 = .bss:0x00000118; // type:object size:0x4 data:4byte diff --git a/configure.py b/configure.py index 1dd001d7..08fc269a 100644 --- a/configure.py +++ b/configure.py @@ -1037,7 +1037,7 @@ config.libs = [ Rel( "m423Dll", # GOOOOOOOAL!! objects={ - Object(NonMatching, "REL/m423Dll/main.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "REL/m423Dll/main.c"), }, ), Rel( diff --git a/include/game/gamework_data.h b/include/game/gamework_data.h index 53500e51..08b3e075 100644 --- a/include/game/gamework_data.h +++ b/include/game/gamework_data.h @@ -110,11 +110,11 @@ typedef struct player_state { } PlayerState; //size of 0x30 typedef struct pause_backup_config { - u8 explain_mg : 1; - u8 show_com_mg : 1; - u8 mg_list : 2; - u8 mess_speed : 2; - u8 save_mode : 2; + u8 explain_mg : 1; + u8 show_com_mg : 1; + u8 mg_list : 2; + u8 mess_speed : 2; + u8 save_mode : 2; } PauseBackupConfig; typedef struct game_stat { @@ -152,6 +152,11 @@ extern PlayerState GWPlayer[4]; extern SystemState GWSystem; extern GameStat GWGameStat; +static inline s32 GWPlayerCfgGroupGet(s32 player) +{ + return GWPlayerCfg[player].group; +} + static inline s32 GWTeamGet(void) { return GWSystem.team; @@ -159,12 +164,12 @@ static inline s32 GWTeamGet(void) static inline s32 GWMGTypeGet(void) { - return GWSystem.mg_type; + return GWSystem.mg_type; } static inline void GWMGTypeSet(s32 type) { - GWSystem.mg_type = type; + GWSystem.mg_type = type; } static inline s32 GWPartyGet(void) @@ -190,9 +195,9 @@ static inline s32 GWRumbleGet(void) static inline void GWRumbleSet(s32 value) { GWGameStat.rumble = value; - if(value == 0) { - HuPadRumbleAllStop(); - } + if(value == 0) { + HuPadRumbleAllStop(); + } } static inline s32 GWBonusStarGet(void) @@ -245,39 +250,39 @@ static inline s32 GWMessSpeedGet(void) static inline void GWMessSpeedSet(s32 value) { #if VERSION_NTSC - GWSystem.mess_speed = value; - switch(value) { - case 0: - GWSystem.mess_delay = 16; - break; - - case 2: - GWSystem.mess_delay = 48; - break; - - default: - GWSystem.mess_delay = 32; - break; - } + GWSystem.mess_speed = value; + switch(value) { + case 0: + GWSystem.mess_delay = 16; + break; + + case 2: + GWSystem.mess_delay = 48; + break; + + default: + GWSystem.mess_delay = 32; + break; + } #else GWSystem.mess_speed = value; - switch(value) { - case 0: - GWSystem.mess_delay = 32; - break; - + switch(value) { + case 0: + GWSystem.mess_delay = 32; + break; + case 2: - GWSystem.mess_delay = 64; - break; + GWSystem.mess_delay = 64; + break; - case 1: - GWSystem.mess_delay = 48; - break; - - default: - GWSystem.mess_delay = 120; - break; - } + case 1: + GWSystem.mess_delay = 48; + break; + + default: + GWSystem.mess_delay = 120; + break; + } #endif } @@ -289,7 +294,7 @@ static inline void GWSaveModeSet(s32 value) static inline s32 GWSaveModeGet(void) { if (GWSystem.save_mode == 3) { - GWSaveModeSet(1); + GWSaveModeSet(1); } return GWSystem.save_mode; } @@ -326,29 +331,29 @@ static inline void GWLuckyValueSet(s32 value) static inline s16 GWPlayerCoinBattleGet(s32 player) { - return GWPlayer[player].coins_battle; + return GWPlayer[player].coins_battle; } static inline s16 GWPlayerCoinCollectGet(s32 player) { - return GWPlayer[player].coin_collect; + return GWPlayer[player].coin_collect; } static inline void GWPlayerCoinCollectSet(s32 player, s16 value) { - GWPlayer[player].coin_collect = value; + GWPlayer[player].coin_collect = value; } static inline s16 GWPlayerCoinWinGet(s32 player) { - return GWPlayer[player].coin_win; + return GWPlayer[player].coin_win; } static inline void GWPlayerCoinWinSet(s32 player, s16 value) { - if (_CheckFlag(FLAG_ID_MAKE(1, 12)) == 0) { - GWPlayer[player].coin_win = value; - } + if (_CheckFlag(FLAG_ID_MAKE(1, 12)) == 0) { + GWPlayer[player].coin_win = value; + } } #define GWPlayerCoinWinAdd(player, value) GWPlayerCoinWinSet((player), GWPlayerCoinWinGet((player))+(value)) diff --git a/src/REL/m409Dll/cursor.c b/src/REL/m409Dll/cursor.c index 021bc823..c007391c 100644 --- a/src/REL/m409Dll/cursor.c +++ b/src/REL/m409Dll/cursor.c @@ -206,19 +206,19 @@ void fn_1_C164(unkStruct8* arg0) { } GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_RGBA6, 0); - GXSetArray(GX_VA_POS, var_r31->unk40, 0xC); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetArray(GX_VA_POS, var_r31->unk40, 12); GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_TEX_ST, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); GXSetArray(GX_VA_CLR0, var_r31->unk44, 4); for (var_r26 = 0; var_r26 < var_r31->unk32; var_r26++) { GXSetVtxDesc(var_r26 + GX_VA_TEX0, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, var_r26 + GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, var_r26 + GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GXSetArray(var_r26 + GX_VA_TEX0, var_r31->unk54[var_r26].unk4, 8); } GXSetVtxDesc(GX_VA_NRM, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_TEX_S, GX_RGBA6, 0); - GXSetArray(GX_VA_NRM, var_r31->unk48, 0xC); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); + GXSetArray(GX_VA_NRM, var_r31->unk48, 12); GXCallDisplayList(var_r31->unk3C, var_r31->unk38); } } diff --git a/src/REL/m409Dll/main.c b/src/REL/m409Dll/main.c index 5071127d..3e51e855 100644 --- a/src/REL/m409Dll/main.c +++ b/src/REL/m409Dll/main.c @@ -1376,13 +1376,13 @@ void fn_1_602C(ModelData *arg0, f32 (*arg1)[4]) } GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_RGBA6, 0); - GXSetArray(GX_VA_POS, temp_r30->unk1C, 0xC); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetArray(GX_VA_POS, temp_r30->unk1C, 12); GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_TEX_ST, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); GXSetArray(GX_VA_CLR0, temp_r30->unk24, 4); GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GXSetArray(GX_VA_TEX0, temp_r30->unk20, 8); fn_1_40A4(arg1, sp128); PSMTXReorder(sp128, spF8); diff --git a/src/REL/m415Dll/map.c b/src/REL/m415Dll/map.c index 45a83c57..31636233 100644 --- a/src/REL/m415Dll/map.c +++ b/src/REL/m415Dll/map.c @@ -230,20 +230,20 @@ void fn_1_88B8(unkSubStruct2* arg0) { } GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_RGBA6, 0); - GXSetArray(GX_VA_POS, var_r31->unk40, 0xC); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetArray(GX_VA_POS, var_r31->unk40, 12); GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_TEX_ST, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); GXSetArray(GX_VA_CLR0, var_r31->unk44, 4); for (var_r27 = 0; var_r27 < var_r31->unk33; var_r27++) { GXSetVtxDesc(var_r27 + GX_VA_TEX0, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, var_r27 + GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, var_r27 + GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GXSetArray(var_r27 + GX_VA_TEX0, var_r31->unk54[var_r27].unk4, 8); } GXSetVtxDesc(GX_VA_NRM, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_RGBA6, 0); - GXSetArray(GX_VA_NRM, var_r31->unk48, 0xC); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); + GXSetArray(GX_VA_NRM, var_r31->unk48, 12); GXCallDisplayList(var_r31->unk3C, var_r31->unk38); } } @@ -1433,4 +1433,4 @@ void fn_1_C81C(s16 arg0, u8 arg1) { var_r31 = &lbl_1_bss_36C.unk3C[arg0]; var_r31->unk4 = arg1; } -} \ No newline at end of file +} diff --git a/src/REL/m423Dll/main.c b/src/REL/m423Dll/main.c new file mode 100755 index 00000000..c063e916 --- /dev/null +++ b/src/REL/m423Dll/main.c @@ -0,0 +1,5648 @@ +#include "game/audio.h" +#include "game/chrman.h" +#include "game/data.h" +#include "game/esprite.h" +#include "game/gamework_data.h" +#include "game/hsfdraw.h" +#include "game/hsfman.h" +#include "game/hsfmotion.h" +#include "game/memory.h" +#include "game/minigame_seq.h" +#include "game/object.h" +#include "game/pad.h" +#include "game/process.h" +#include "game/sprite.h" +#include "game/wipe.h" + +#include "dolphin.h" +#include "ext_math.h" + +#define frand7() (frand() & 0x7F) + +extern u32 GlobalCounter; + +typedef struct { + /* 0x00 */ s32 unk00; + /* 0x04 */ s32 unk04; + /* 0x08 */ s32 unk08; + /* 0x0C */ s32 unk0C; + /* 0x10 */ void* unk10; +} StructBssD0Data; // Size 0x14 + +typedef struct { + /* 0x00 */ Vec unk00; + /* 0x0C */ Vec unk0C; + /* 0x18 */ float unk18; +} StructData0; // Size 0x1C + +typedef struct { + /* 0x00 */ StructBssD0Data* unk00; + /* 0x04 */ AnimData* unk04; +} StructM423_00; // Size 8 + +typedef struct { + /* 0x00 */ s16 unk00; + /* 0x02 */ s16 unk02; + /* 0x04 */ s16 unk04; + /* 0x06 */ s16 unk06; + /* 0x08 */ Vec unk08; +} StructM423_01; // Size 0x14 + +typedef struct { + /* 0x00 */ s16 unk00; + /* 0x02 */ s16 unk02; + /* 0x04 */ s16 unk04; + /* 0x06 */ char unk06[2]; + /* 0x08 */ Vec unk08; + /* 0x14 */ Vec* unk14; + /* 0x18 */ Vec* unk18; + /* 0x1C */ GXColor* unk1C; + /* 0x20 */ StructM423_01* unk20; + /* 0x24 */ float unk24[4]; + /* 0x34 */ u32 unk34; + /* 0x38 */ void* unk38; +} StructM423_02; // Size 0x3C + +typedef struct { + /* 0x00 */ s16 unk00; + /* 0x02 */ s16 unk02; + /* 0x04 */ StructM423_02* unk04; +} StructM423_03; // Size 8 + +typedef struct { + /* 0x00 */ s16 unk00; + /* 0x02 */ s16 unk02; + /* 0x04 */ Vec unk04; + /* 0x10 */ char unk10[8]; + /* 0x18 */ float unk18; + /* 0x1C */ char unk1C[0xC]; + /* 0x28 */ float unk28; + /* 0x2C */ float unk2C; + /* 0x30 */ float unk30; + /* 0x34 */ float unk34; + /* 0x38 */ Vec unk38; + /* 0x44 */ GXColor unk44; + /* 0x48 */ s32 unk48; +} StructM423_04; // Size 0x4C + +typedef struct struct_m423_05 { + /* 0x00 */ s16 unk00; + /* 0x02 */ s16 unk02; + /* 0x00 */ char unk04[0x1C]; + /* 0x20 */ u8 unk20; + /* 0x21 */ u8 unk21; + /* 0x22 */ u8 unk22; + /* 0x23 */ s8 unk23; + /* 0x24 */ char unk24[2]; + /* 0x26 */ s16 unk26; + /* 0x28 */ s32 unk28; + /* 0x2C */ s32 unk2C; + /* 0x30 */ u32 unk30; + /* 0x34 */ s32 unk34; + /* 0x38 */ AnimData* unk38; + /* 0x3C */ StructM423_04* unk3C; + /* 0x40 */ Vec* unk40; + /* 0x44 */ float (*unk44)[2]; + /* 0x48 */ void* unk48; + /* 0x4C */ void* unk4C; + /* 0x50 */ ModelData* unk50; +} StructM423_05; // Size 0x54 + +typedef struct { + /* 0x00 */ float unk00; + /* 0x04 */ float unk04; + /* 0x08 */ char unk08[4]; + /* 0x0C */ float unk0C; + /* 0x10 */ float unk10; + /* 0x14 */ char unk14[4]; + /* 0x18 */ float unk18; + /* 0x1C */ float unk1C; + /* 0x20 */ char unk20[4]; + /* 0x24 */ float unk24; + /* 0x28 */ float unk28; + /* 0x2C */ char unk2C[4]; + /* 0x30 */ float unk30; + /* 0x34 */ float unk34; + /* 0x38 */ char unk38[4]; +} StructM423_08; // Size 0x3C + +typedef struct { + /* 0x00 */ float unk00; + /* 0x04 */ float unk04; + /* 0x08 */ float unk08; + /* 0x0C */ float unk0C; + /* 0x10 */ float unk10; + /* 0x14 */ float unk14; + /* 0x18 */ float unk18; + /* 0x1C */ float unk1C; + /* 0x20 */ float unk20; + /* 0x24 */ float unk24; +} StructM423_09; // Size 0x28 + +typedef struct { + /* 0x000 */ u16 unk00; + /* 0x002 */ u16 unk02; + /* 0x004 */ float unk04; + /* 0x008 */ float unk08; + /* 0x00C */ float unk0C; + /* 0x010 */ float unk10; + /* 0x014 */ Vec unk14; +} StructM423_0A; // Size 0x20 + +typedef struct { + /* 0x000 */ StructM423_0A unk00[16]; + /* 0x200 */ AnimData* unk200; + /* 0x204 */ s32 unk204; + /* 0x208 */ void* unk208; + /* 0x20C */ StructM423_08* unk20C; + /* 0x210 */ StructM423_09* unk210; + /* 0x214 */ GXColor* unk214; + /* 0x218 */ s32 unk218; + /* 0x21C */ s32 unk21C; + /* 0x220 */ void* unk220; +} StructM423_0B; // Size 0x224 + +typedef struct { + /* 0x000 */ s32 unk00; + /* 0x004 */ s32 unk04; + /* 0x008 */ s32 unk08; + /* 0x00C */ s32 unk0C; + /* 0x010 */ s32 unk10[24]; + /* 0x070 */ s32 unk70[24][3]; + /* 0x190 */ s16 unk190[10][2]; +} StructM423_0C; // Size 0x1B8 + +typedef struct { + /* 0x00 */ s16 unk00; + /* 0x02 */ s16 unk02; + /* 0x04 */ s16 unk04; + /* 0x06 */ s16 unk06; + /* 0x08 */ s16 unk08; + /* 0x0A */ s16 unk0A; + /* 0x0C */ s16 unk0C; + /* 0x0E */ s16 unk0E; + /* 0x10 */ s16 unk10; + /* 0x12 */ s16 unk12; + /* 0x14 */ s32 unk14; + /* 0x18 */ s32 unk18; + /* 0x1C */ s32 unk1C; + /* 0x20 */ Vec unk20; + /* 0x2C */ Vec unk2C; + /* 0x38 */ Vec unk38; + /* 0x44 */ float unk44; + /* 0x48 */ float unk48; + /* 0x4C */ float unk4C; + /* 0x50 */ Vec unk50; + /* 0x5C */ Vec unk5C; + /* 0x68 */ Vec unk68; + /* 0x74 */ Vec unk74; + /* 0x80 */ Vec unk80; + /* 0x8C */ float unk8C; + /* 0x90 */ float unk90; +} StructBssA8Data; // Size 0x94 + +typedef struct { + /* 0x00 */ s16 unk00; + /* 0x02 */ s16 unk02; + /* 0x04 */ s16 unk04; + /* 0x06 */ s16 unk06; + /* 0x08 */ s16 unk08; + /* 0x0A */ s16 unk0A; +} StructBssCCData; // Size 0xC + +typedef struct { + /* 0x00 */ s16 unk00; + /* 0x02 */ s16 unk02; + /* 0x04 */ s16 unk04; + /* 0x06 */ s16 unk06; + /* 0x08 */ s16 unk08; + /* 0x0A */ s16 unk0A; + /* 0x0C */ s16 unk0C; + /* 0x0E */ s16 unk0E; + /* 0x10 */ s16 unk10; + /* 0x12 */ s16 unk12; + /* 0x14 */ s16 unk14; + /* 0x16 */ s16 unk16; + /* 0x18 */ s16 unk18; + /* 0x1A */ char unk1A[2]; + /* 0x1C */ float unk1C[15]; + /* 0x58 */ s32 unk58; + /* 0x5C */ s32 unk5C; + /* 0x60 */ float unk60; + /* 0x64 */ s32 unk64; + /* 0x68 */ s32 unk68; + /* 0x6C */ s32 unk6C; + /* 0x70 */ s32 unk70; + /* 0x74 */ s32 unk74; + /* 0x78 */ float unk78; + /* 0x7C */ float unk7C; + /* 0x80 */ s32 unk80; + /* 0x84 */ s32 unk84; + /* 0x88 */ float unk88; + /* 0x8C */ float unk8C; + /* 0x90 */ s32 unk90; + /* 0x94 */ s32 unk94; + /* 0x98 */ s32 unk98; + /* 0x9C */ s32 unk9C; + /* 0xA0 */ s32 unkA0; + /* 0xA4 */ s32 unkA4; + /* 0xA8 */ float unkA8; + /* 0xAC */ s32 unkAC; + /* 0xB0 */ float unkB0; + /* 0xB4 */ float unkB4; + /* 0xB8 */ float unkB8; + /* 0xBC */ float unkBC; + /* 0xC0 */ float unkC0; + /* 0xC4 */ float unkC4; + /* 0xC8 */ Vec unkC8; + /* 0xD4 */ Vec unkD4; + /* 0xE0 */ float unkE0; + /* 0xE4 */ float unkE4; + /* 0xE8 */ float unkE8; + /* 0xEC */ float unkEC; + /* 0xF0 */ float unkF0; + /* 0xF4 */ float unkF4; +} StructBssBCData; // Size 0xF8 + +typedef struct { + /* 0x000 */ s16 unk00; + /* 0x002 */ s16 unk02; + /* 0x004 */ Vec unk04; + /* 0x010 */ Vec unk10; + /* 0x004 */ char unk1C[0xC]; + /* 0x028 */ float unk28; + /* 0x02C */ float unk2C; + /* 0x030 */ float unk30; + /* 0x034 */ float unk34; + /* 0x038 */ char unk38[4]; + /* 0x03C */ float unk3C; + /* 0x040 */ s32 unk40; + /* 0x044 */ float unk44[12][4]; + /* 0x104 */ Vec unk104[12][3]; +} StructBss94Data; // Size 0x2B4 + +typedef struct { + /* 0x00 */ s32 unk00; + /* 0x04 */ s32 unk04; + /* 0x08 */ AnimData* unk08; +} StructBssA4Data; // Size 0xC + +void fn_1_318(omObjData* arg0); +void fn_1_3B0(omObjData* arg0); +void fn_1_DFC(omObjData* arg0); +void fn_1_E60(omObjData* arg0); +void fn_1_F10(void); +void fn_1_F60(omObjData* arg0); +void fn_1_11A4(omObjData* arg0); +void fn_1_1238(void); +void fn_1_12A0(ModelData* arg0, Mtx arg1); +s32 fn_1_13A0(StructBssD0Data* arg0); +void fn_1_1444(s32 arg0); +void fn_1_14A0(ModelData* arg0, Mtx arg1); +s32 fn_1_18FC(void); +void fn_1_1B5C(ModelData* arg0, StructM423_02* arg1); +void fn_1_1F5C(ModelData* arg0, StructM423_02* arg1); +void fn_1_2290(ModelData* arg0, StructM423_02* arg1); +void fn_1_2624(ModelData* arg0, StructM423_02* arg1); +void fn_1_29B8(s32 arg0); +void fn_1_29BC(ModelData* arg0, Mtx arg1); +void fn_1_2C08(s32 arg0); +void fn_1_34D8(void); +void fn_1_3528(omObjData* arg0); +void fn_1_3898(omObjData* arg0); +void fn_1_3A64(void); +void fn_1_3A8C(void); +void fn_1_3BFC(void); +void fn_1_3FE0(omObjData* arg0); +void fn_1_4778(omObjData* arg0); +void fn_1_5D18(omObjData* arg0); +void fn_1_77D0(void); +s32 fn_1_781C(void); +s32 fn_1_791C(void); +void fn_1_7AA8(s32 arg0); +void fn_1_82C8(s32 arg0, s32 arg1, s32 arg2); +void fn_1_8338(omObjData* arg0); +void fn_1_8CB4(omObjData* arg0); +void fn_1_95C4(void); +void fn_1_9614(omObjData* arg0); +void fn_1_98A0(omObjData* arg0); +void fn_1_A9AC(void); +s32 fn_1_A9D4(s32 arg0, Vec arg1, Vec arg2); +void fn_1_AC0C(s32 arg0, Vec arg1); +void fn_1_AC80(s32 arg0, Vec arg1); +s32 fn_1_AE64(s32 arg0); +void fn_1_AEE8(s32 arg0); +StructBssA8Data* fn_1_B13C(s32 arg0); +void fn_1_B1A4(void); +s32 fn_1_B304(StructBssA8Data** arg0); +void fn_1_B430(void); +void fn_1_BCD8(Vec* arg0, Vec* arg1, Vec* arg2, float arg3, s32 arg4, s32 arg5); +s32 fn_1_C498(Vec* arg0, Vec* arg1, Vec* arg2, Vec* arg3, float arg4, s32 arg5); +void fn_1_D930(void); +void fn_1_DA38(omObjData* arg0); +void fn_1_DBC8(void); +s32 fn_1_DC24(Vec arg0, Vec arg1, float arg2, float arg3, float arg4, GXColor arg5); +s32 fn_1_DD70(Vec arg0, Vec arg1, float arg2, float arg3, float arg4, float arg5, GXColor arg6); +void fn_1_E1BC(void); +void fn_1_E290(omObjData* arg0); +void fn_1_E330(void); +s32 fn_1_E334(Vec arg0, Vec arg1, float arg2); +void fn_1_E460(void); +void fn_1_E4EC(omObjData* arg0); +void fn_1_E60C(void); +s32 fn_1_E678(void); +void fn_1_EF44(ModelData* arg0, Mtx arg1); +s32 fn_1_F574(Vec arg0, float arg1, s32 arg2); +void fn_1_F690(void); +void fn_1_F6E0(omObjData* arg0); +void fn_1_FA40(omObjData* arg0); +void fn_1_FF98(void); +void fn_1_10028(s32 arg0); +void fn_1_100DC(void); +void fn_1_10480(omObjData* arg0); +void fn_1_10540(s32 arg0, s32 arg1, s32 arg2, float arg3); +void fn_1_106D8(s32 arg0); +void fn_1_10BC8(void); +void fn_1_11008(StructBssD0Data* arg0, void* arg1, s16 arg2, GXTexWrapMode arg3, s32 arg4, s32 arg5); +s16 fn_1_11114(AnimData* arg0, s16 arg1); +void fn_1_11900(ModelData* arg0, Mtx arg1); +float fn_1_121DC(float arg0, float arg1); +float fn_1_122F4(float arg0, float arg1, float arg2); +float fn_1_12544(float arg0, float arg1, float arg2); +void fn_1_1293C(Mtx arg0, Vec* arg1); +s32 fn_1_12C6C(Vec* arg0, Vec* arg1, float* arg2); +float fn_1_12E68(Vec* arg0, Vec* arg1, s32 arg2); +void fn_1_129F0(Vec* arg0, Vec* arg1, Vec* arg2, float* arg3); +void fn_1_1334C(float* arg0, Vec* arg1, Vec* arg2, Vec* arg3, Vec* arg4); +float fn_1_1367C(Vec* arg0, Vec* arg1, Vec* arg2, Vec* arg3, float* arg4); +s32 fn_1_137C4(Vec* arg0, Vec* arg1, Vec* arg2, Vec* arg3, float arg4, s32 arg5); + +Process* lbl_1_bss_120; +s32 lbl_1_bss_11C; +s32 lbl_1_bss_118; +s32 lbl_1_bss_114; +s32 lbl_1_bss_110; +s32 lbl_1_bss_10C; // unused +s32 lbl_1_bss_108; +s32 lbl_1_bss_104; +s32 lbl_1_bss_100; +s32 lbl_1_bss_FC; +s32 lbl_1_bss_EC[4]; +s32 lbl_1_bss_DC[4]; +s32 lbl_1_bss_D8; +omObjData* lbl_1_bss_D4; +omObjData* lbl_1_bss_D0; +omObjData* lbl_1_bss_CC; +omObjData* lbl_1_bss_BC[4]; +omObjData* lbl_1_bss_B8; +omObjData* lbl_1_bss_AC[3]; +omObjData* lbl_1_bss_A8; +omObjData* lbl_1_bss_A4; +omObjData* lbl_1_bss_A0; +omObjData* lbl_1_bss_9C; +omObjData* lbl_1_bss_98; +StructBss94Data* lbl_1_bss_94; +s32 lbl_1_bss_90; +omObjData* lbl_1_bss_8C; +s32 lbl_1_bss_88; +s32 lbl_1_bss_84; +s32 lbl_1_bss_80; +s32 lbl_1_bss_7C; +StructBssA8Data* lbl_1_bss_40[15]; +StructBssA8Data* lbl_1_bss_4[15]; +s32 lbl_1_bss_0; + +StructData0 lbl_1_data_0[] = { + { { 342.45f, 0.0f, 0.0f }, { 0.0f, 275.0f, 128.0f }, 550.0f }, + { { 6.0f, 0.0f, 0.0f }, { 0.0f, 190.0f, 0.0f }, 550.0f } +}; + +StructData0 lbl_1_data_38[] = { + { { 22.0f, 180.0f, 0.0f }, { -250.0f, 120.00001f, 0.0f }, 160.0f }, + { { 22.0f, 180.0f, 0.0f }, { 0.0f, 120.00001f, 0.0f }, 160.0f }, + { { 22.0f, 180.0f, 0.0f }, { 250.0f, 120.00001f, 0.0f }, 160.0f }, + { { -45.0f, 180.0f, 0.0f }, { -250.0f, 75.0f, 0.0f }, 180.0f }, + { { -45.0f, 180.0f, 0.0f }, { 0.0f, 75.0f, 0.0f }, 180.0f }, + { { -45.0f, 180.0f, 0.0f }, { 250.0f, 75.0f, 0.0f }, 180.0f }, + { { -45.0f, 0.0f, 0.0f }, { -250.0f, 95.0f, 0.0f }, 150.0f }, + { { -45.0f, 0.0f, 0.0f }, { 0.0f, 95.0f, 0.0f }, 150.0f }, + { { -45.0f, 0.0f, 0.0f }, { 250.0f, 95.0f, 0.0f }, 150.0f }, + { { -45.0f, 0.0f, 0.0f }, { 0.0f, 95.0f, -850.0f }, 150.0f } +}; + +Vec lbl_1_data_150[] = { + 0.0f, 0.0f, -850.0f, + -250.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 250.0f, 0.0f, 0.0f +}; + +Vec lbl_1_data_180[] = { + 0.0f, 0.0f, -850.0f, + 850.0f, 0.0f, 0.0f, + 1200.0f, 0.0f, 0.0f, + 1650.0f, 0.0f, 0.0f +}; + +Vec lbl_1_data_1B0[] = { + { -250.0f, 45.0f, 500.0f }, + { 0.0f, 45.0f, 500.0f }, + { 250.0f, 45.0f, 500.0f } +}; + +Vec lbl_1_data_1D4 = { 1000.0f, 2000.0f, 1000.0f }; +Vec lbl_1_data_1E0 = { 0.0f, 1.0f, 0.0f }; +Vec lbl_1_data_1EC = { 0.0f, 0.0f, -450.0f }; + +void ObjectSetup(void) { + Process* var_r30; + CameraData* var_r29; + s32 i; + + OSReport("******* M426ObjectSetup *********\n"); + var_r30 = omInitObjMan(50, 0x2000); + lbl_1_bss_120 = var_r30; + omGameSysInit(var_r30); + fn_1_100DC(); + Hu3DLightAllKill(); + Hu3DLighInit(); + HuAudSndGrpSet(0x30); + lbl_1_bss_D4 = omAddObjEx(var_r30, 0xFF, 2, 0, -1, fn_1_318); + lbl_1_bss_11C = lbl_1_bss_118 = -1; + lbl_1_bss_D0 = NULL; + lbl_1_bss_CC = NULL; + lbl_1_bss_A8 = NULL; + lbl_1_bss_B8 = NULL; + lbl_1_bss_AC[0] = lbl_1_bss_AC[1] = lbl_1_bss_AC[2] = NULL; + lbl_1_bss_114 = 0; + lbl_1_bss_110 = 0; + lbl_1_bss_108 = 0; + lbl_1_bss_104 = 10; + lbl_1_bss_100 = -1; + lbl_1_bss_FC = 0; + lbl_1_bss_90 = -1; + lbl_1_bss_D8 = -1; + for (i = 0; i < 4; i++) { + lbl_1_bss_DC[i] = 0; + lbl_1_bss_EC[i] = -1; + } + Hu3DShadowCreate(30.0f, 1000.0f, 250000.0f); + Hu3DShadowTPLvlSet(0.5f); + Hu3DShadowPosSet(&lbl_1_data_1D4, &lbl_1_data_1E0, &lbl_1_data_1EC); + for (i = 0; i < 3; i++) { + var_r29 = &Hu3DCamera[i]; + var_r29->fov = -1.0f; + } +} + +Vec lbl_1_data_21C = { 0.0f, 0.0f, 0.0f }; +Vec lbl_1_data_228 = { -1.0f, -2.0f, -1.0f }; +GXColor lbl_1_data_234 = { 0xFF, 0xFF, 0xFF, 0xFF }; + +void fn_1_318(omObjData* arg0) { + s32 var_r31; + + var_r31 = Hu3DGLightCreateV(&lbl_1_data_21C, &lbl_1_data_228, &lbl_1_data_234); + Hu3DGLightStaticSet(var_r31, 1); + Hu3DGLightInfinitytSet(var_r31); + fn_1_F10(); + fn_1_34D8(); + fn_1_3BFC(); + fn_1_95C4(); + fn_1_D930(); + fn_1_E1BC(); + fn_1_E460(); + fn_1_F690(); + HuAudFXPlay(0x618); + arg0->func = fn_1_3B0; +} + +s32 lbl_1_data_238[] = { 0, 4, 2, 3, 1, 5 }; +s32 lbl_1_data_250[] = { 186, 186, 186, 240, 240, 240 }; + +void fn_1_3B0(omObjData* arg0) { + CameraData* var_r28; + float var_f31; + s32 temp_r27; + s32 var_r30; + s32 var_r29; + s32 i; + + switch (lbl_1_bss_114) { + case 0: + fn_1_10540(2, 1, 1, 0.0f); + if (++lbl_1_bss_110 > 3) { + for (i = 0; i < 3; i++) { + var_r28 = &Hu3DCamera[i]; + var_r28->fov = 45.0f; + } + WipeCreate(WIPE_MODE_IN, WIPE_TYPE_NORMAL, 60); + lbl_1_bss_114 = 1; + lbl_1_bss_110 = 0; + } + break; + case 1: + fn_1_10540(2, 1, 1, 0.0f); + if (WipeStatGet() == 0) { + lbl_1_bss_114 = 2; + lbl_1_bss_110 = 0; + } + break; + case 2: + if (++lbl_1_bss_110 >= 30.0f) { + lbl_1_bss_114 = 3; + lbl_1_bss_110 = 0; + } + break; + case 3: + var_f31 = lbl_1_bss_110 / 90.0f; + if (var_f31 > 1.0f) { + var_f31 = 1.0f; + } + var_f31 = sind(90.0f * var_f31); + var_f31 *= var_f31; + fn_1_10540(2, 1, 0, var_f31); + if (++lbl_1_bss_110 >= 90.0f) { + lbl_1_bss_114 = 4; + lbl_1_bss_110 = 0; + } + break; + case 4: + if (fn_1_781C() != 0) { + lbl_1_bss_11C = MGSeqStartCreate(); + lbl_1_bss_114 = 5; + lbl_1_bss_110 = 0; + } + break; + case 5: + if (lbl_1_bss_11C != -1) { + var_r30 = MGSeqStatGet(lbl_1_bss_11C); + if ((var_r30 & 0x10) && lbl_1_bss_D8 == -1) { + lbl_1_bss_D8 = HuAudSeqPlay(0x46); + } + } else { + var_r30 = 0; + } + if (lbl_1_bss_11C == -1 || var_r30 == 0) { + lbl_1_bss_11C = -1; + lbl_1_bss_114 = 6; + lbl_1_bss_110 = 0; + lbl_1_bss_108 = 1800; + fn_1_10028(1); + lbl_1_bss_118 = MGSeqTimerCreate(lbl_1_bss_108 / 60); + } + break; + case 6: + temp_r27 = lbl_1_data_238[lbl_1_bss_0]; + fn_1_106D8(temp_r27); + if (lbl_1_bss_80 >= lbl_1_data_250[temp_r27] && ++lbl_1_bss_0 > 5) { + lbl_1_bss_0 = 0; + } + var_r29 = (lbl_1_bss_108 + 59) / 60; + if (var_r29 < 0) { + var_r29 = 0; + } + MGSeqParamSet(lbl_1_bss_118, 1, var_r29); + if (--lbl_1_bss_108 < -1 || lbl_1_bss_104 <= 0) { + MGSeqParamSet(lbl_1_bss_118, 2, -1); + lbl_1_bss_118 = -1; + fn_1_B1A4(); + if (lbl_1_bss_D8 != -1) { + HuAudSeqFadeOut(lbl_1_bss_D8, 100); + } + lbl_1_bss_11C = MGSeqFinishCreate(); + lbl_1_bss_114 = 7; + lbl_1_bss_110 = 0; + } + break; + case 7: + if (fn_1_791C() != 0 && (lbl_1_bss_11C == -1 || MGSeqStatGet(lbl_1_bss_11C) == 0)) { + lbl_1_bss_114 = 9; + lbl_1_bss_110 = 0; + } + break; + case 9: + if (lbl_1_bss_104 <= 0) { + lbl_1_bss_11C = MGSeqWinCreate(lbl_1_bss_EC[0], lbl_1_bss_EC[1], lbl_1_bss_EC[2], -1); + fn_1_7AA8(1); + for (i = 0; i < 4; i++) { + if (lbl_1_bss_EC[3] != GWPlayerCfg[i].character) { + GWPlayerCoinWinAdd(i, 10); + } + } + if (lbl_1_bss_DC[0] > lbl_1_bss_DC[1] && lbl_1_bss_DC[0] > lbl_1_bss_DC[2]) { + i = 0; + } else if (lbl_1_bss_DC[1] > lbl_1_bss_DC[0] && lbl_1_bss_DC[1] > lbl_1_bss_DC[2]) { + i = 1; + } else if (lbl_1_bss_DC[2] > lbl_1_bss_DC[0] && lbl_1_bss_DC[2] > lbl_1_bss_DC[1]) { + i = 2; + } else { + i = frand() & 3; + if (i > 2) { + i = 2; + } else if (i < 0) { + i = 0; + } + } + fn_1_106D8(i + 6); + lbl_1_bss_114 = 10; + lbl_1_bss_108 = 0; + } else { + lbl_1_bss_11C = MGSeqWinCreate(lbl_1_bss_EC[3], -1, -1, -1); + fn_1_7AA8(0); + for (i = 0; i < 4; i++) { + if (lbl_1_bss_EC[3] == GWPlayerCfg[i].character) { + GWPlayerCoinWinAdd(i, 10); + } + } + fn_1_106D8(9); + lbl_1_bss_114 = 10; + lbl_1_bss_108 = 0; + } + HuAudSStreamPlay(1); + HuAudFXPlay(0x618); + break; + case 10: + fn_1_3A8C(); + if (++lbl_1_bss_108 >= 210.0f) { + lbl_1_bss_11C = -1; + lbl_1_bss_114 = 11; + lbl_1_bss_108 = 0; + } + break; + case 11: + WipeCreate(WIPE_MODE_OUT, WIPE_TYPE_NORMAL, 60); + arg0->func = fn_1_DFC; + break; + } + fn_1_E60(arg0); +} + +void fn_1_DFC(omObjData* arg0) { + if (WipeStatGet() == 0) { + fn_1_1238(); + fn_1_3A64(); + fn_1_77D0(); + fn_1_A9AC(); + fn_1_DBC8(); + fn_1_E330(); + fn_1_E60C(); + fn_1_FF98(); + MGSeqKillAll(); + HuAudFadeOut(1); + omOvlReturnEx(1, 1); + } +} + +void fn_1_E60(omObjData* arg0) { + s32 var_r30; + + var_r30 = 0; + if (WipeStatGet() != 0 || arg0->func == fn_1_DFC) { + return; + } + if (omSysExitReq != 0) { + var_r30 = 1; + } + if (var_r30 != 0) { + WipeCreate(WIPE_MODE_OUT, WIPE_TYPE_NORMAL, 60); + HuAudStreamFadeOut(30); + arg0->func = fn_1_DFC; + } +} + +s32 fn_1_F00(void) { + return lbl_1_bss_114; +} + +void fn_1_F10(void) { + lbl_1_bss_D0 = omAddObjEx(lbl_1_bss_120, 0x7F, 8, 0, -1, fn_1_F60); +} + +void fn_1_F60(omObjData* arg0) { + StructBssD0Data* temp_r30; + ModelData* temp_r29; + + temp_r30 = arg0->data = HuMemDirectMallocNum(HEAP_SYSTEM, sizeof(*temp_r30), MEMORY_DEFAULT_NUM); + memset(temp_r30, 0, sizeof(*temp_r30)); + arg0->model[0] = Hu3DModelCreateFile(DATA_MAKE_NUM(DATADIR_M423, 0)); + Hu3DModelCameraSet(arg0->model[0], 5); + Hu3DModelShadowMapSet(arg0->model[0]); + arg0->model[1] = Hu3DModelCreateFile(DATA_MAKE_NUM(DATADIR_M423, 1)); + Hu3DModelCameraSet(arg0->model[1], 5); + arg0->model[2] = Hu3DModelCreateFile(DATA_MAKE_NUM(DATADIR_M423, 2)); + Hu3DModelScaleSet(arg0->model[2], 1.125f, 1.0f, 1.0f); + Hu3DModelCameraSet(arg0->model[2], 5); + Hu3DModelShadowSet(arg0->model[2]); + arg0->model[3] = Hu3DHookFuncCreate(fn_1_12A0); + Hu3DModelCameraSet(arg0->model[3], 2); + temp_r29 = &Hu3DData[arg0->model[3]]; + temp_r29->unk_120 = temp_r30; + temp_r30->unk00 = 160; + temp_r30->unk04 = 160; + temp_r30->unk08 = GXGetTexBufferSize(temp_r30->unk00, temp_r30->unk04, 5, 0, 0); + temp_r30->unk10 = HuMemDirectMallocNum(HEAP_DATA, temp_r30->unk08, (u32) temp_r29->unk_48); + temp_r30->unk0C = 0.0f; + arg0->model[4] = fn_1_13A0(temp_r30); + Hu3DModelCameraSet(arg0->model[4], 5); + Hu3DModelPosSet(arg0->model[4], 0.0f, 200.0f, -1700.0f); + arg0->model[5] = fn_1_18FC(); + Hu3DModelCameraSet(arg0->model[5], 4); + arg0->func = fn_1_11A4; +} + +void fn_1_11A4(omObjData* arg0) { + fn_1_2C08(arg0->model[5]); +} + +void fn_1_11D8(omObjData* arg0) { + fn_1_1444(arg0->model[4]); + arg0->model[4] = -1; + fn_1_29B8(arg0->model[5]); + arg0->model[5] = -1; + arg0->func = NULL; +} + +void fn_1_1238(void) { + fn_1_11D8(lbl_1_bss_D0); +} + +GXColor lbl_1_data_298 = { 0x00, 0x00, 0x00, 0xFF }; + +void fn_1_12A0(ModelData* arg0, Mtx arg1) { + StructBssD0Data* temp_r31; + CameraData* var_r30; + + temp_r31 = arg0->unk_120; + var_r30 = &Hu3DCamera[1]; + if (var_r30->fov <= 0.0f) { + return; + } + GXSetTexCopySrc(0, 0, 320, 240); + GXSetTexCopyDst(temp_r31->unk00, temp_r31->unk04, GX_TF_RGB5A3, GX_TRUE); + GXSetCopyClear(lbl_1_data_298, 0xFFFFFF); + GXCopyTex(temp_r31->unk10, GX_TRUE); + DCFlushRange(temp_r31->unk10, temp_r31->unk08); + GXPixModeSync(); + temp_r31->unk0C = 1; + fn_1_10BC8(); +} + +s32 fn_1_13A0(StructBssD0Data* arg0) { + StructM423_00* var_r31; + ModelData* temp_r30; + s32 var_r29; + + var_r29 = Hu3DHookFuncCreate(fn_1_14A0); + temp_r30 = &Hu3DData[var_r29]; + var_r31 = temp_r30->unk_120 = HuMemDirectMallocNum(HEAP_DATA, sizeof(*var_r31), temp_r30->unk_48); + memset(var_r31, 0, sizeof(*var_r31)); + var_r31->unk00 = arg0; + var_r31->unk04 = HuSprAnimRead(HuDataReadNum(DATA_MAKE_NUM(DATADIR_M423, 21), MEMORY_DEFAULT_NUM)); + return var_r29; +} + +void fn_1_1444(s32 arg0) { + StructM423_00* var_r31; + ModelData* var_r30; + + if (arg0 >= 0) { + var_r30 = &Hu3DData[arg0]; + var_r31 = var_r30->unk_120; + HuSprAnimKill(var_r31->unk04); + } +} + +f32 lbl_1_data_29C[] = { + -400.0f, 400.0f, 0.0f, + 400.0f, 400.0f, 0.0f, + 400.0f, 0.0f, 0.0f, + -400.0f, 0.0f, 0.0f +}; + +f32 lbl_1_data_2CC[] = { + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 0.75f, + 0.0f, 0.75f +}; + +f32 lbl_1_data_2EC[] = { + 0.0f, 0.0f, + 1.2f, 0.0f, + 1.2f, 0.75f, + 0.0f, 0.75f +}; + +GXColor lbl_1_data_30C[] = { + { 0x40, 0x40, 0x40, 0xFF } +}; + +GXColor lbl_1_data_310 = { 0x00, 0x00, 0x00, 0x80 }; + +void fn_1_14A0(ModelData* arg0, Mtx arg1) { + CameraData* var_r28; + StructM423_00* temp_r29; + StructBssD0Data* temp_r30; + Mtx spC; + s16 i; + + var_r28 = &Hu3DCamera[2]; + temp_r29 = arg0->unk_120; + temp_r30 = temp_r29->unk00; + if (temp_r30->unk0C != 0) { + if (var_r28->fov <= 0.0f) { + return; + } + GXLoadPosMtxImm(arg1, GX_PNMTX0); + PSMTXInvXpose(arg1, spC); + GXLoadNrmMtxImm(spC, GX_PNMTX0); + GXSetTevColor(GX_TEVREG2, lbl_1_data_310); + GXSetNumTevStages(2); + GXSetNumTexGens(2); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTexCoordGen2(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0); + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + if (Hu3DCameraNo != 0) { + GXSetTevOp(GX_TEVSTAGE1, GX_REPLACE); + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_CPREV, GX_CC_C2, GX_CC_TEXA, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + } else { + GXSetTevOp(GX_TEVSTAGE1, GX_REPLACE); + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + } + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_APREV, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetNumChans(1); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE); + fn_1_11008(temp_r30, temp_r30->unk10, GX_TEXMAP0, GX_CLAMP, 0, 1); + HuSprTexLoad(temp_r29->unk04, 0, 1, GX_REPEAT, GX_REPEAT, GX_LINEAR); + GXSetAlphaCompare(GX_GEQUAL, 1, GX_AOP_AND, GX_GEQUAL, 1); + GXSetZCompLoc(GX_FALSE); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetArray(GX_VA_POS, lbl_1_data_29C, 12); + GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetArray(GX_VA_CLR0, lbl_1_data_30C, 4); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXSetArray(GX_VA_TEX0, lbl_1_data_2CC, 8); + GXSetVtxDesc(GX_VA_TEX1, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0); + GXSetArray(GX_VA_TEX1, lbl_1_data_2EC, 8); + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + for (i = 0; i < 4; i++) { + GXPosition1x16(i); + GXColor1x16(0); + GXTexCoord1x16(i); + GXTexCoord1x16(i); + } + GXEnd(); + } +} + +s32 lbl_1_data_314[][2] = { + { 20, 10 }, { 20, 7 }, { 10, 10 }, { 10, 10 } +}; + +Vec lbl_1_data_334[] = { + { 0.0f, 100.0f, -1100.0f }, + { 0.0f, 200.0f, -1000.0f }, + { -225.0f, 100.0f, -1000.0f }, + { 225.0f, 100.0f, -1000.0f } +}; + +s32 fn_1_18FC(void) { + ModelData* temp_r30; + StructM423_03* var_r29; + StructM423_02* temp_r31; + s32 var_r27; + s32 i; + + var_r27 = Hu3DHookFuncCreate(fn_1_29BC); + temp_r30 = &Hu3DData[var_r27]; + var_r29 = temp_r30->unk_120 = HuMemDirectMallocNum(HEAP_DATA, sizeof(*var_r29), temp_r30->unk_48); + memset(var_r29, 0, sizeof(*var_r29)); + var_r29->unk00 = var_r27; + var_r29->unk02 = 4; + temp_r31 = var_r29->unk04 = HuMemDirectMallocNum(HEAP_DATA, var_r29->unk02 * sizeof(*temp_r31), temp_r30->unk_48); + memset(temp_r31, 0, var_r29->unk02 * sizeof(*temp_r31)); + for (i = 0; i < var_r29->unk02; i++) { + temp_r31 = &var_r29->unk04[i]; + temp_r31->unk02 = lbl_1_data_314[i][0]; + temp_r31->unk04 = lbl_1_data_314[i][1]; + temp_r31->unk00 = temp_r31->unk02 * temp_r31->unk04; + temp_r31->unk08 = lbl_1_data_334[i]; + temp_r31->unk14 = HuMemDirectMallocNum(HEAP_DATA, temp_r31->unk00 * sizeof(*temp_r31->unk14), temp_r30->unk_48); + memset(temp_r31->unk14, 0, temp_r31->unk00 * sizeof(*temp_r31->unk14)); + temp_r31->unk18 = HuMemDirectMallocNum(HEAP_DATA, temp_r31->unk00 * sizeof(*temp_r31->unk18), temp_r30->unk_48); + memset(temp_r31->unk18, 0, temp_r31->unk00 * sizeof(*temp_r31->unk18)); + temp_r31->unk1C = HuMemDirectMallocNum(HEAP_DATA, temp_r31->unk00 * sizeof(*temp_r31->unk1C), temp_r30->unk_48); + memset(temp_r31->unk1C, 0, temp_r31->unk00 * sizeof(*temp_r31->unk1C)); + temp_r31->unk20 = HuMemDirectMallocNum(HEAP_DATA, temp_r31->unk00 * sizeof(*temp_r31->unk20), temp_r30->unk_48); + memset(temp_r31->unk20, 0, temp_r31->unk00 * sizeof(*temp_r31->unk20)); + switch (i) { + case 0: + fn_1_1B5C(temp_r30, temp_r31); + break; + case 1: + fn_1_1F5C(temp_r30, temp_r31); + break; + case 2: + fn_1_2290(temp_r30, temp_r31); + break; + default: + fn_1_2624(temp_r30, temp_r31); + break; + } + } + return var_r27; +} + +Vec lbl_1_data_364[] = { + { -200.0f, 0.0f, -1100.0f }, + { -200.0f, 200.0f, -1050.0f }, + { 200.0f, 200.0f, -1050.0f } +}; + +GXColor lbl_1_data_388 = { 0xFF, 0xFF, 0xFF, 0xFF }; + +void fn_1_1B5C(ModelData* arg0, StructM423_02* arg1) { + float var_f31; + float var_f30; + float var_f29; + Vec* var_r27; + GXColor* var_r26; + StructM423_01* var_r28; + void* var_r25; + void* var_r23; + s32 i; + s32 j; + + var_r27 = arg1->unk14; + var_r26 = arg1->unk1C; + var_r28 = arg1->unk20; + for (i = 0; i < 10; i++) { + var_f30 = 200.0f * (i / 9.0f); + var_f29 = -1100.0f + 50.0f * (i / 9.0f); + for (j = 0; j < 20; var_r27++, var_r26++, var_r28++, j++) { + var_f31 = -225.0f + 450.0f * (j / 19.0f); + var_r27->x = var_f31; + var_r27->y = var_f30; + var_r27->z = var_f29; + *var_r26 = lbl_1_data_388; + var_r28->unk00 = j; + var_r28->unk02 = i; + if (i == 0 || i == 9 || j == 0 || j == 19) { + var_r28->unk04 = 1; + } else { + var_r28->unk04 = 0; + } + var_r28->unk06 = 0; + var_r28->unk08.x = var_r28->unk08.y = var_r28->unk08.z = 0.0f; + } + } + memcpy(arg1->unk18, arg1->unk14, arg1->unk00 * sizeof(*arg1->unk14)); + DCFlushRangeNoSync(arg1->unk14, arg1->unk00 * sizeof(*arg1->unk14)); + DCFlushRangeNoSync(arg1->unk1C, arg1->unk00 * sizeof(*arg1->unk1C)); + PPCSync(); + var_r23 = var_r25 = HuMemDirectMallocNum(HEAP_DATA, 0x10000, arg0->unk_48); + DCFlushRange(var_r25, 0x10000); + GXBeginDisplayList(var_r23, 0x10000); + GXBegin(GX_LINES, GX_VTXFMT0, 9 * 19 * 4); + for (i = 1; i < 10; i++) { + for (j = 1; j < 20; j++) { + GXPosition1x16(i * 20 + j); + GXColor1x16(i * 20 + j); + + GXPosition1x16(i * 20 + (j - 1)); + GXColor1x16(i * 20 + (j - 1)); + + GXPosition1x16(i * 20 + j); + GXColor1x16(i * 20 + j); + + GXPosition1x16((i - 1) * 20 + j); + GXColor1x16((i - 1) * 20 + j); + } + } + GXEnd(); + arg1->unk34 = GXEndDisplayList(); + if (arg1->unk34 >= 0x10000) { + OSReport("ERROR! GList test size over! \n"); + } + arg1->unk38 = HuMemDirectMallocNum(HEAP_DATA, arg1->unk34, arg0->unk_48); + memcpy(arg1->unk38, var_r25, arg1->unk34); + DCFlushRange(arg1->unk38, arg1->unk34); + HuMemDirectFree(var_r25); + fn_1_129F0(&lbl_1_data_364[0], &lbl_1_data_364[1], &lbl_1_data_364[2], arg1->unk24); +} + +GXColor lbl_1_data_3AB = { 0xFF, 0xFF, 0xFF, 0xFF }; + +void fn_1_1F5C(ModelData* arg0, StructM423_02* arg1) { + float var_f31; + float var_f30; + float var_f29; + Vec* var_r27; + GXColor* var_r26; + void* var_r25; + void* var_r23; + s32 i; + s32 j; + + var_r27 = arg1->unk14; + var_r26 = arg1->unk1C; + for (i = 0; i < 7; i++) { + var_f30 = 200.0f; + var_f29 = -900.0f - 150.0f * (i / 6.0f); + for (j = 0; j < 20; var_r27++, var_r26++, j++) { + var_f31 = -225.0f + 450.0f * (j / 19.0f); + var_r27->x = var_f31; + var_r27->y = var_f30; + var_r27->z = var_f29; + *var_r26 = lbl_1_data_3AB; + } + } + memcpy(arg1->unk18, arg1->unk14, arg1->unk00 * sizeof(*arg1->unk14)); + DCFlushRangeNoSync(arg1->unk14, arg1->unk00 * sizeof(*arg1->unk14)); + DCFlushRangeNoSync(arg1->unk1C, arg1->unk00 * sizeof(*arg1->unk1C)); + PPCSync(); + var_r23 = var_r25 = HuMemDirectMallocNum(HEAP_DATA, 0x10000, arg0->unk_48); + DCFlushRange(var_r25, 0x10000); + GXBeginDisplayList(var_r23, 0x10000); + GXBegin(GX_LINES, GX_VTXFMT0, 6 * 19 * 4); + for (i = 1; i < 7; i++) { + for (j = 1; j < 20; j++) { + GXPosition1x16(i * 20 + j); + GXColor1x16(i * 20 + j); + + GXPosition1x16(i * 20 + (j - 1)); + GXColor1x16(i * 20 + (j - 1)); + + GXPosition1x16(i * 20 + j); + GXColor1x16(i * 20 + j); + + GXPosition1x16((i - 1) * 20 + j); + GXColor1x16((i - 1) * 20 + j); + } + } + GXEnd(); + arg1->unk34 = GXEndDisplayList(); + if (arg1->unk34 >= 0x10000) { + OSReport("ERROR! GList test size over! \n"); + } + arg1->unk38 = HuMemDirectMallocNum(HEAP_DATA, arg1->unk34, arg0->unk_48); + memcpy(arg1->unk38, var_r25, arg1->unk34); + DCFlushRange(arg1->unk38, arg1->unk34); + HuMemDirectFree(var_r25); +} + +GXColor lbl_1_data_3AF = { 0xFF, 0xFF, 0xFF, 0xFF }; + +void fn_1_2290(ModelData* arg0, StructM423_02* arg1) { + float var_f31; + float var_f30; + float var_f29; + float var_f28; + Vec* var_r27; + GXColor* var_r26; + void* var_r25; + void* var_r23; + s32 i; + s32 j; + + var_r27 = arg1->unk14; + var_r26 = arg1->unk1C; + for (i = 0; i < 10; i++) { + var_f28 = 200.0f * (i / 9.0f); + var_f29 = -225.0f; + var_f30 = -1100.0f + 50.0f * (i / 9.0f); + for (j = 0; j < 10; var_r27++, var_r26++, j++) { + var_f31 = -900.0f - 200.0f * (j / 9.0f); + if (var_f31 < var_f30) { + var_f31 = var_f30; + } + var_r27->x = var_f29; + var_r27->y = var_f28; + var_r27->z = var_f31; + *var_r26 = lbl_1_data_3AF; + } + } + memcpy(arg1->unk18, arg1->unk14, arg1->unk00 * sizeof(*arg1->unk14)); + DCFlushRangeNoSync(arg1->unk14, arg1->unk00 * sizeof(*arg1->unk14)); + DCFlushRangeNoSync(arg1->unk1C, arg1->unk00 * sizeof(*arg1->unk1C)); + PPCSync(); + var_r23 = var_r25 = HuMemDirectMallocNum(HEAP_DATA, 0x10000, arg0->unk_48); + DCFlushRangeNoSync(var_r25, 0x10000); + GXBeginDisplayList(var_r23, 0x10000); + GXBegin(GX_LINES, GX_VTXFMT0, 9 * 9 * 4); + for (i = 1; i < 10; i++) { + for (j = 1; j < 10; j++) { + GXPosition1x16(i * 10 + j); + GXColor1x16(i * 10 + j); + + GXPosition1x16(i * 10 + (j - 1)); + GXColor1x16(i * 10 + (j - 1)); + + GXPosition1x16(i * 10 + j); + GXColor1x16(i * 10 + j); + + GXPosition1x16((i - 1) * 10 + j); + GXColor1x16((i - 1) * 10 + j); + } + } + GXEnd(); + arg1->unk34 = GXEndDisplayList(); + if (arg1->unk34 >= 0x10000) { + OSReport("ERROR! GList test size over! \n"); + } + arg1->unk38 = HuMemDirectMallocNum(HEAP_DATA, arg1->unk34, arg0->unk_48); + memcpy(arg1->unk38, var_r25, arg1->unk34); + DCFlushRange(arg1->unk38, arg1->unk34); + HuMemDirectFree(var_r25); +} + +GXColor lbl_1_data_3B3 = { 0xFF, 0xFF, 0xFF, 0xFF }; + +void fn_1_2624(ModelData* arg0, StructM423_02* arg1) { + float var_f31; + float var_f30; + float var_f29; + float var_f28; + Vec* var_r27; + GXColor* var_r26; + void* var_r25; + void* var_r23; + s32 i; + s32 j; + + var_r27 = arg1->unk14; + var_r26 = arg1->unk1C; + for (i = 0; i < 10; i++) { + var_f28 = 200.0f * (i / 9.0f); + var_f29 = 225.0f; + var_f30 = -1100.0f + 50.0f * (i / 9.0f); + for (j = 0; j < 10; var_r27++, var_r26++, j++) { + var_f31 = -900.0f - 200.0f * (j / 9.0f); + if (var_f31 < var_f30) { + var_f31 = var_f30; + } + var_r27->x = var_f29; + var_r27->y = var_f28; + var_r27->z = var_f31; + *var_r26 = lbl_1_data_3B3; + } + } + memcpy(arg1->unk18, arg1->unk14, arg1->unk00 * sizeof(*arg1->unk14)); + DCFlushRangeNoSync(arg1->unk14, arg1->unk00 * sizeof(*arg1->unk14)); + DCFlushRangeNoSync(arg1->unk1C, arg1->unk00 * sizeof(*arg1->unk1C)); + PPCSync(); + var_r23 = var_r25 = HuMemDirectMallocNum(HEAP_DATA, 0x10000, arg0->unk_48); + DCFlushRange(var_r25, 0x10000); + GXBeginDisplayList(var_r23, 0x10000); + GXBegin(GX_LINES, GX_VTXFMT0, 9 * 9 * 4); + for (i = 1; i < 10; i++) { + for (j = 1; j < 10; j++) { + GXPosition1x16(i * 10 + j); + GXColor1x16(i * 10 + j); + + GXPosition1x16(i * 10 + (j - 1)); + GXColor1x16(i * 10 + (j - 1)); + + GXPosition1x16(i * 10 + j); + GXColor1x16(i * 10 + j); + + GXPosition1x16((i - 1) * 10 + j); + GXColor1x16((i - 1) * 10 + j); + } + } + GXEnd(); + arg1->unk34 = GXEndDisplayList(); + if (arg1->unk34 >= 0x10000) { + OSReport("ERROR! GList test size over! \n"); + } + arg1->unk38 = HuMemDirectMallocNum(HEAP_DATA, arg1->unk34, arg0->unk_48); + memcpy(arg1->unk38, var_r25, arg1->unk34); + DCFlushRange(arg1->unk38, arg1->unk34); + HuMemDirectFree(var_r25); +} + +void fn_1_29B8(s32 arg0) { +} + +void fn_1_29BC(ModelData* arg0, Mtx arg1) { + StructM423_03* temp_r30; + StructM423_02* temp_r31; + Mtx sp8; + s16 i; + + temp_r30 = arg0->unk_120; + GXLoadPosMtxImm(arg1, GX_PNMTX0); + PSMTXInvXpose(arg1, sp8); + GXLoadNrmMtxImm(sp8, GX_PNMTX0); + GXSetLineWidth(6, GX_TO_ZERO); + GXSetNumTevStages(1); + GXSetNumTexGens(0); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_RASA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetNumChans(1); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE); + GXSetAlphaCompare(GX_GEQUAL, 1, GX_AOP_AND, GX_GEQUAL, 1); + GXSetZCompLoc(GX_FALSE); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + for (i = 0; i < temp_r30->unk02; i++) { + temp_r31 = &temp_r30->unk04[i]; + if (temp_r31->unk38 && temp_r31->unk34 != 0) { + DCFlushRangeNoSync(temp_r31->unk14, temp_r31->unk00 * sizeof(*temp_r31->unk14)); + DCFlushRangeNoSync(temp_r31->unk1C, temp_r31->unk00 * sizeof(*temp_r31->unk1C)); + PPCSync(); + GXSetArray(GX_VA_POS, temp_r31->unk14, sizeof(*temp_r31->unk14)); + GXSetArray(GX_VA_CLR0, temp_r31->unk1C, sizeof(*temp_r31->unk1C)); + GXCallDisplayList(temp_r31->unk38, temp_r31->unk34); + } + } +} + +void fn_1_2C08(s32 arg0) { + Vec sp3C; + Vec sp30; + Vec sp24; + Vec* var_r25; + Vec* var_r24; + Vec* temp_r27; + Vec* temp_r29; + float temp_f31; + float temp_f28; + float temp_f30; + float var_f29; + float var_f27; + StructM423_02* temp_r30; + StructM423_01* var_r28; + StructBssA8Data* var_r31; + StructM423_03* var_r17; + ModelData* sp20; + ModelData* sp1C; + StructM423_01* sp18; + s32 var_r20; + s32 temp_r19; + s32 temp_r18; + s32 i; + s32 j; + s32 k; + s32 temp_r21; + s32 sp14; + s32 sp10; + s32 spC; + Mtx sp48; + + sp20 = &Hu3DData[arg0]; + var_r17 = sp20->unk_120; + temp_r30 = var_r17->unk04; + var_r25 = temp_r30->unk14; + var_r24 = temp_r30->unk18; + var_r28 = temp_r30->unk20; + if (lbl_1_bss_A8 == NULL) { + return; + } + var_r31 = lbl_1_bss_A8->data; + for (i = 0; i < temp_r30->unk00; i++, var_r25++, var_r24++, var_r28++) { + if (var_r28->unk04 != 0) { + continue; + } + PSVECSubtract(var_r24, var_r25, &sp30); + temp_f31 = PSVECMag(&sp30); + if (temp_f31 >= 0.0f) { + PSVECScale(&sp30, &sp30, 0.05f); + PSVECAdd(&var_r28->unk08, &sp30, &var_r28->unk08); + temp_f31 = PSVECMag(&var_r28->unk08); + if (temp_f31 > 10.0f) { + PSVECNormalize(&var_r28->unk08, &var_r28->unk08); + PSVECScale(&var_r28->unk08, &var_r28->unk08, 10.0f); + } + } + PSVECAdd(var_r25, &var_r28->unk08, var_r25); + PSVECScale(&var_r28->unk08, &var_r28->unk08, 0.5f); + } + for (i = 0; i < 15; i++, var_r31++) { + if (var_r31->unk06 == 0 || var_r31->unk0C != 3) { + continue; + } + spC = 0; + PSVECSubtract(&var_r31->unk38, &var_r31->unk74, &sp30); + if (var_r31->unk38.x > -225.0f && var_r31->unk38.x < 225.0f + && var_r31->unk38.y > 0.0f && var_r31->unk38.y < 200.0f + && var_r31->unk38.z > -1150.0f && var_r31->unk38.z < -950.0f) + { + var_f27 = 0.005f * var_r31->unk38.y; + var_f29 = -900.0f - (150.0f + var_f27 * 50.0f); + if (var_r31->unk38.z - 20.0 < var_f29) { + if (var_r31->unk38.z < 20.0 + (var_f29 - 75.0f)) { + var_r31->unk38.z = 20.0 + (var_f29 - 75.0f); + } + spC = 1; + } + } + if (spC != 0) { + if (var_r31->unk0A == 0 && var_r31->unk08 == 0) { + fn_1_AEE8(i); + } + if (var_r31->unk10 == 0) { + var_r31->unk5C = var_r31->unk50; + var_r31->unk10 = 1; + } + sp1C = &Hu3DData[var_r31->unk00]; + sp24.x = var_r31->unk5C.z; + sp24.z = -var_r31->unk5C.x; + sp24.y = 0.0f; + temp_f31 = 0.05 * PSVECMag(&sp24); + if (temp_f31 > 0.00001f) { + PSMTXRotAxisRad(sp48, &sp24, temp_f31); + PSMTXConcat(sp48, sp1C->unk_F0, sp1C->unk_F0); + } + temp_f31 = 0.0133333336f * fabs(var_f29 - (var_r31->unk38.z - 20.0)); + var_r31->unk50.z += temp_f31 * 0.4f; + PSVECScale(&var_r31->unk50, &var_r31->unk50, 0.95f); + var_r31->unk50.y *= 0.0f; + var_r31->unk50.x *= 0.75f; + sp14 = (var_r31->unk38.x - -225.0f) / 22.5f; + sp10 = var_r31->unk38.y / 20.0f; + var_r20 = sp14 + sp10 * temp_r30->unk02; + var_r25 = &temp_r30->unk14[var_r20]; + var_r24 = &temp_r30->unk18[var_r20]; + var_r28 = &temp_r30->unk20[var_r20]; + temp_f28 = var_r24->z - (var_r31->unk38.z - 20.0); + sp3C = var_r31->unk38; + if (temp_f28 < 0.0f) { + continue; + } + for (j = -19; j < 20; j++) { + for (k = -19; k < 20; k++) { + temp_r19 = sp14 + k; + temp_r18 = sp10 + j; + temp_r21 = temp_r19 + temp_r18 * temp_r30->unk02; + if (temp_r19 < 0 || temp_r19 >= temp_r30->unk02 || temp_r18 < 0 || temp_r18 >= temp_r30->unk04 || temp_r21 >= temp_r30->unk00) { + continue; + } + sp18 = &temp_r30->unk20[temp_r21]; + if (sp18->unk04 != 0) { + continue; + } + temp_r29 = &temp_r30->unk14[temp_r21]; + temp_r27 = &temp_r30->unk18[temp_r21]; + PSVECSubtract(&sp3C, temp_r29, &sp30); + sp30.z = 0.0f; + temp_f31 = PSVECMag(&sp30); + if (temp_f31 > 400.0f) { + continue; + } + if (temp_f31 > 20.0) { + temp_f30 = 0.0025f * (400.0f - temp_f31); + temp_f30 = temp_f30 * temp_f30; + PSVECNormalize(&sp30, &sp30); + PSVECScale(&sp30, &sp30, 20.0f * (temp_f30 * temp_f30)); + temp_r29->x += 0.5f * (temp_r27->x + sp30.x - temp_r29->x); + temp_r29->y += 0.5f * (temp_r27->y + sp30.y - temp_r29->y); + temp_r29->z += 0.5f * (temp_r27->z - temp_f30 * temp_f28 - temp_r29->z); + } else { + temp_f30 = cosd(0.0025f * temp_f31 * 90.0f); + if (temp_f31 != 0.0f) { + PSVECNormalize(&sp30, &sp30); + } else { + sp30.x = sp30.y = sp30.z = 0.0f; + } + PSVECScale(&sp30, &sp30, temp_f30 * temp_f30 * 20.0f); + temp_r29->z += 0.5f * (temp_r27->z - temp_f30 * temp_f28 - temp_r29->z); + } + } + } + } else { + var_r31->unk10 = 0; + } + } + DCFlushRangeNoSync(temp_r30->unk14, temp_r30->unk00 * sizeof(*temp_r30->unk14)); + PPCSync(); +} + +void fn_1_34D8(void) { + lbl_1_bss_CC = omAddObjEx(lbl_1_bss_120, 0x81, 20, 6, -1, fn_1_3528); +} + +Vec lbl_1_data_3B8[] = { + -1300.0f, 300.0f, -2350.0f, + -800.0f, 200.0f, -2250.0f, + 800.0f, 200.0f, -2250.0f, + 1300.0f, 300.0f, -2350.0f, + -1000.0f, 300.0f, -2350.0f, + 1000.0f, 300.0f, -2350.0f, + -1200.0f, 400.0f, -2450.0f, + -800.0f, 400.0f, -2450.0f, + 800.0f, 400.0f, -2450.0f, + 1200.0f, 400.0f, -2450.0f, + -1400.0f, 200.0f, -2250.0f, + 1400.0f, 200.0f, -2250.0f, + -1400.0f, 400.0f, -2450.0f, + 1400.0f, 400.0f, -2450.0f, + -900.0f, 500.0f, -2550.0f, + 900.0f, 500.0f, -2550.0f, + -1200.0f, 500.0f, -2550.0f, + 1200.0f, 500.0f, -2550.0f, + -1100.0f, 200.0f, -2250.0f, + 1100.0f, 200.0f, -2250.0f +}; + +s32 lbl_1_data_4A8[] = { + 0, 1, 0, 1, 2, 2, 1, 0, + 1, 2, 0, 1, 2, 0, 1, 2, + 0, 1, 2, 1, 0 +}; + +s32 lbl_1_data_4FC[] = { + DATA_MAKE_NUM(DATADIR_M423, 12), + DATA_MAKE_NUM(DATADIR_M423, 15), + DATA_MAKE_NUM(DATADIR_M423, 18) +}; + +s32 lbl_1_data_508[] = { + DATA_MAKE_NUM(DATADIR_M423, 13), + DATA_MAKE_NUM(DATADIR_M423, 14), + DATA_MAKE_NUM(DATADIR_M423, 16), + DATA_MAKE_NUM(DATADIR_M423, 17), + DATA_MAKE_NUM(DATADIR_M423, 19), + DATA_MAKE_NUM(DATADIR_M423, 20) +}; + +s16 lbl_1_data_520[] = { 0, 2, 4 }; + +void fn_1_3528(omObjData* arg0) { + float var_f30; + float var_f29; + float temp_f31; + StructBssCCData* var_r30; + s32 temp_r27; + s32 var_r28; + s32 i; + + var_r30 = arg0->data = HuMemDirectMallocNum(HEAP_SYSTEM, 20 * sizeof(*var_r30), MEMORY_DEFAULT_NUM); + memset(var_r30, 0, 20 * sizeof(*var_r30)); + for (i = 0; i < 6; i++) { + arg0->motion[i] = Hu3DMotionCreateFile(lbl_1_data_508[i]); + } + for (i = 0; i < 20; i++, var_r30++) { + temp_r27 = lbl_1_data_4A8[i]; + var_r30->unk00 = temp_r27; + var_r30->unk02 = 0; + var_r30->unk04 = 0; + var_r30->unk08 = 0; + var_r30->unk0A = 0; + var_r30->unk06 = 210.0f + (1.0f / 127) * frand7() * 60.0f; + var_f30 = -lbl_1_data_3B8[i].x; + var_f29 = -lbl_1_data_3B8[i].z; + temp_f31 = atan2d(var_f30, var_f29); + var_r28 = Hu3DModelCreateFile(lbl_1_data_4FC[temp_r27]); + arg0->model[i] = var_r28; + Hu3DModelCameraSet(var_r28, 4); + Hu3DModelPosSet(var_r28, lbl_1_data_3B8[i].x, lbl_1_data_3B8[i].y, lbl_1_data_3B8[i].z); + if (var_r30->unk00 != 1) { + Hu3DModelRotSet(var_r28, 0.0f, temp_f31, 0.0f); + } else { + Hu3DModelRotSet(var_r28, 10.0f, temp_f31, 0.0f); + } + Hu3DModelScaleSet(var_r28, 1.8f, 1.8f, 1.8f); + Hu3DMotionSet(arg0->model[i], arg0->motion[lbl_1_data_520[var_r30->unk00]]); + if ((i >= 14 && i <= 17) || i == 11 || i == 10) { + Hu3DModelAttrSet(var_r28, 1); + } + } + arg0->stat |= 0x100; + arg0->func = fn_1_3898; +} + +s16 lbl_1_data_526[] = { 0, 2, 4 }; +s16 lbl_1_data_52C[] = { 1, 3, 5, 0 }; + +void fn_1_3898(omObjData* arg0) { + StructBssCCData* var_r31; + s32 var_r28; + s32 i; + + var_r31 = arg0->data; + for (i = 0; i < 20; i++, var_r31++) { + var_r28 = 0; + if (var_r31->unk06 > 0) { + var_r28 = 1; + var_r31->unk06--; + } else if (var_r31->unk0A > 0) { + if (var_r31->unk08 > 0) { + var_r31->unk08--; + } else if (var_r31->unk0A > 0) { + var_r28 = 1; + var_r31->unk0A--; + } else { + var_r31->unk08 = 0; + var_r31->unk0A = 0; + } + } + if (var_r28 != var_r31->unk02 && Hu3DMotionShiftIDGet(arg0->model[i]) == -1) { + var_r31->unk02 = var_r28; + if (var_r31->unk02 == 0) { + Hu3DMotionShiftSet(arg0->model[i], arg0->motion[lbl_1_data_526[var_r31->unk00]], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + } else { + Hu3DMotionShiftSet(arg0->model[i], arg0->motion[lbl_1_data_52C[var_r31->unk00]], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + } + } + } +} + +void fn_1_3A58(omObjData* arg0) { + arg0->func = NULL; +} + +void fn_1_3A64(void) { + fn_1_3A58(lbl_1_bss_CC); +} + +void fn_1_3A8C(void) { + omObjData* var_r29; + StructBssCCData* var_r31; + s32 i; + + if (lbl_1_bss_CC == NULL) { + return; + } + var_r29 = lbl_1_bss_CC; + var_r31 = var_r29->data; + for (i = 0; i < 20; i++, var_r31++) { + if (var_r31->unk06 > 0 || var_r31->unk0A > 0) { + var_r31->unk08 = 0; + } else { + var_r31->unk08 = (1.0f / 127) * frand7() * 0.25f * 60.0f; + } + var_r31->unk0A = ((1.0f / 127) * frand7() + 2.0f) * 60.0f; + } +} + +void fn_1_3BFC(void) { + s32 sp8[4]; + s32 temp_r28; + s32 temp_r27; + s32 var_r25; + s32 var_r26; + s32 var_r29; + s32 i; + s32 j; + + for (i = 0; i < 4; i++) { + sp8[i] = -1; + } + for (i = 0, var_r29 = 0; i < 4; i++) { + if (GWPlayerCfgGroupGet(i) == 0) { + sp8[3] = i; + } else { + sp8[var_r29] = i; + var_r29++; + } + } + for (i = 0; i < 4; i++) { + if (sp8[i] == -1) { + break; + } + } + if (i < 4) { + sp8[0] = 1; + sp8[1] = 2; + sp8[2] = 3; + sp8[3] = 0; + } else { + for (i = 0; i < 32; i++) { + temp_r28 = (s16) (frand() & 0xFFF) % 3; + temp_r27 = (s16) (frand() & 0xFFF) % 3; + if (temp_r28 != temp_r27) { + var_r29 = sp8[temp_r27]; + sp8[temp_r27] = sp8[temp_r28]; + sp8[temp_r28] = var_r29; + } + } + } + var_r25 = 1; + for (i = 0, var_r26 = 0; i < 4; i++) { + lbl_1_bss_BC[i] = omAddObjEx(lbl_1_bss_120, 0x40, 4, 11, -1, fn_1_3FE0); + lbl_1_bss_BC[i]->work[0] = i; + if (i == sp8[3]) { + lbl_1_bss_EC[3] = GWPlayerCfg[lbl_1_bss_BC[i]->work[0]].character; + lbl_1_bss_BC[i]->work[1] = 0; + lbl_1_bss_BC[i]->work[2] = 0; + if (GWPlayerCfg[lbl_1_bss_BC[i]->work[0]].iscom) { + lbl_1_bss_FC = 1; + } + } else { + lbl_1_bss_EC[var_r26] = GWPlayerCfg[lbl_1_bss_BC[i]->work[0]].character; + var_r26++; + lbl_1_bss_BC[i]->work[1] = 1; + for (j = 0; j < 3; j++) { + if (i == sp8[j]) { + break; + } + } + if (j >= 3) { + j = i - 1; + } + lbl_1_bss_BC[i]->work[2] = j; + lbl_1_bss_AC[j] = lbl_1_bss_BC[i]; + if (!GWPlayerCfg[lbl_1_bss_BC[i]->work[0]].iscom) { + var_r25 = 0; + } + } + } + if (var_r25 != 0) { + lbl_1_bss_FC = 0; + } +} + +u32 lbl_1_data_534[][2] = { + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 0), -1 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 2), -1 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 3), -1 }, + { 0, 0 }, + { 0, 1 }, + { 0, 2 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 23), -1 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 24), -1 } +}; + +s32 lbl_1_data_574[] = { + DATA_MAKE_NUM(DATADIR_M423, 58), + DATA_MAKE_NUM(DATADIR_M423, 26), + DATA_MAKE_NUM(DATADIR_M423, 34) +}; + +u32 lbl_1_data_580[][2] = { + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 0), -1 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 2), -1 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 3), -1 }, + { 0, 0 }, + { 0, 1 }, + { 0, 2 }, + { 0, 3 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 11), -1 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 6), -1 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 23), -1 }, + { DATA_MAKE_NUM(DATADIR_MARIOMOT, 24), -1 } +}; + +s32 lbl_1_data_5D8[] = { + DATA_MAKE_NUM(DATADIR_M423, 42), + DATA_MAKE_NUM(DATADIR_M423, 66), + DATA_MAKE_NUM(DATADIR_M423, 50), + DATA_MAKE_NUM(DATADIR_M423, 74) +}; + +void fn_1_3FE0(omObjData* arg0) { + float var_f31; + StructBssBCData* temp_r31; + s32 i; + + temp_r31 = arg0->data = HuMemDirectMallocNum(HEAP_SYSTEM, sizeof(*temp_r31), MEMORY_DEFAULT_NUM); + memset(temp_r31, 0, sizeof(*temp_r31)); + temp_r31->unk00 = arg0->work[0]; + temp_r31->unk02 = GWPlayerCfg[arg0->work[0]].character; + temp_r31->unk04 = GWPlayerCfg[arg0->work[0]].pad_idx; + temp_r31->unk06 = GWPlayerCfg[arg0->work[0]].iscom; + temp_r31->unk08 = GWPlayerCfg[arg0->work[0]].diff; + temp_r31->unk0A = arg0->work[1]; + temp_r31->unk0C = arg0->work[2]; + memset(&temp_r31->unk1C, 0, sizeof(temp_r31->unk1C)); + temp_r31->unk58 = 0; + temp_r31->unk5C = -1; + temp_r31->unk60 = 0.0f; + temp_r31->unk64 = -1; + temp_r31->unk68 = 0; + temp_r31->unk6C = 0; + temp_r31->unk70 = 0; + temp_r31->unk74 = 0; + temp_r31->unk16 = -1; + temp_r31->unk88 = 0.0f; + temp_r31->unk8C = 0.0f; + temp_r31->unk90 = 0; + temp_r31->unk94 = 0; + temp_r31->unk98 = 0; + temp_r31->unk9C = 0; + temp_r31->unkA0 = 0; + temp_r31->unkA4 = 0; + temp_r31->unkA8 = 0.0f; + temp_r31->unkAC = 0; + arg0->model[0] = CharModelCreate(temp_r31->unk02, 4); + Hu3DModelCameraSet(arg0->model[0], 5); + Hu3DModelShadowSet(arg0->model[0]); + Hu3DModelAttrSet(arg0->model[0], HU3D_ATTR_CURVE_MOTOFF); + CharModelStepTypeSet(temp_r31->unk02, 2); + if (temp_r31->unk0A == 0) { + for (i = 0; i < 11; i++) { + if (lbl_1_data_580[i][1] == -1) { + arg0->motion[i] = CharModelMotionCreate(temp_r31->unk02, lbl_1_data_580[i][0]); + } else { + arg0->motion[i] = Hu3DJointMotionFile(arg0->model[0], lbl_1_data_5D8[lbl_1_data_580[i][1]] + temp_r31->unk02); + } + } + temp_r31->unk16 = 0; + temp_r31->unk18 = 0; + CharModelMotionSet(temp_r31->unk02, arg0->motion[temp_r31->unk16]); + Hu3DModelAttrSet(arg0->model[0], HU3D_MOTATTR_LOOP); + temp_r31->unkB0 = arg0->trans.x = lbl_1_data_150[0].x; + temp_r31->unkB4 = arg0->trans.y = lbl_1_data_150[0].y; + temp_r31->unkB8 = arg0->trans.z = lbl_1_data_150[0].z; + temp_r31->unkBC = lbl_1_data_180[0].x; + temp_r31->unkC0 = lbl_1_data_180[0].y; + temp_r31->unkC4 = lbl_1_data_180[0].z; + temp_r31->unk78 = 0.0f; + temp_r31->unk7C = 0.0f; + temp_r31->unkE0 = temp_r31->unkE4 = temp_r31->unkE8 = 0.0f; + temp_r31->unkEC = temp_r31->unkF0 = temp_r31->unkF4 = 0.0f; + temp_r31->unk7C = 6.5f; + var_f31 = 0.0f; + for (i = 0; i < 1000; i++) { + var_f31 += temp_r31->unk7C; + temp_r31->unk7C -= 0.49f; + if (var_f31 <= 0.0f) { + break; + } + } + temp_r31->unk80 = i; + temp_r31->unk7C = 10.5f; + var_f31 = 0.0f; + for (i = 0; i < 1000; i++) { + var_f31 += temp_r31->unk7C; + temp_r31->unk7C -= 0.65333337f; + if (var_f31 <= 0.0f) { + break; + } + } + temp_r31->unk84 = i; + arg0->func = fn_1_5D18; + } else { + for (i = 0; i < 8; i++) { + if (lbl_1_data_534[i][1] == -1) { + arg0->motion[i] = CharModelMotionCreate(temp_r31->unk02, lbl_1_data_534[i][0]); + } else { + arg0->motion[i] = Hu3DJointMotionFile(arg0->model[0], lbl_1_data_574[lbl_1_data_534[i][1]] + temp_r31->unk02); + } + } + temp_r31->unk16 = 0; + temp_r31->unk18 = 0; + CharModelMotionSet(temp_r31->unk02, arg0->motion[temp_r31->unk16]); + Hu3DModelAttrSet(arg0->model[0], HU3D_MOTATTR_LOOP); + temp_r31->unkB0 = lbl_1_data_150[temp_r31->unk0C + 1].x; + temp_r31->unkB4 = lbl_1_data_150[temp_r31->unk0C + 1].y; + temp_r31->unkB8 = lbl_1_data_150[temp_r31->unk0C + 1].z; + temp_r31->unkBC = arg0->trans.x = lbl_1_data_180[temp_r31->unk0C + 1].x; + temp_r31->unkC0 = arg0->trans.y = lbl_1_data_180[temp_r31->unk0C + 1].y; + temp_r31->unkC4 = arg0->trans.z = lbl_1_data_180[temp_r31->unk0C + 1].z; + temp_r31->unk78 = atan2d(lbl_1_data_150[0].x - temp_r31->unkB0, lbl_1_data_150[0].z - temp_r31->unkB8); + temp_r31->unk7C = 0.0f; + temp_r31->unk98 = 0; + temp_r31->unk9C = 300.0f + (1.0f / 127) * frand7() * 60.0f * 15.0f; + if (lbl_1_bss_FC != 0) { + temp_r31->unk08 = 3; + } + arg0->func = fn_1_4778; + } + CharModelMotionDataClose(temp_r31->unk02); +} + +Vec lbl_1_data_5E8 = { 0.0f, 20.0f, 50.0f }; +GXColor lbl_1_data_5F4 = { 0xFF, 0xFF, 0xFF, 0x10 }; +GXColor lbl_1_data_5F8 = { 0xFF, 0xFF, 0xFF, 0x40 }; + +void fn_1_4778(omObjData* arg0) { + Mtx sp11C; + Vec sp110; + Vec sp104; + Vec spF8; + float temp_f27; + float temp_f29; + float temp_f30; + float var_f25; + StructBssBCData* temp_r31; + ModelData* temp_r27; + s32 temp_r26; + s16 var_r25; + s16 var_r24; + s16 var_r29; + s16 var_r28; + + temp_r31 = arg0->data; + temp_r27 = &Hu3DData[arg0->model[0]]; + temp_r31->unk0E = HuPadBtn[temp_r31->unk04]; + temp_r31->unk10 = HuPadBtnDown[temp_r31->unk04]; + temp_r31->unk12 = HuPadStkX[temp_r31->unk04]; + temp_r31->unk14 = HuPadStkY[temp_r31->unk04]; + if (fn_1_F00() == 6) { + if (temp_r31->unk06 != 0) { + temp_r31->unk0E &= ~PAD_BUTTON_A; + temp_r31->unk10 &= ~PAD_BUTTON_A; + temp_r31->unk12 = 0; + temp_r31->unk14 = 0; + fn_1_8338(arg0); + } + var_r25 = temp_r31->unk0E; + var_r24 = temp_r31->unk10; + var_r29 = temp_r31->unk12; + var_r28 = temp_r31->unk14; + } + if (fabs(var_r29) < 8.0) { + var_r29 = 0; + } + if (fabs(var_r29) > 80.0) { + var_r29 = 80; + } + if (fabs(var_r28) < 8.0) { + var_r28 = 0; + } + if (fabs(var_r28) > 80.0) { + var_r28 = 80; + } + if (fn_1_F00() != 6) { + var_r29 = var_r28 = 0; + var_r25 = var_r24 = 0; + } + switch (temp_r31->unk18) { + case 0: + if (fn_1_F00() < 3) { + break; + } + spF8.x = temp_r31->unkB0 - arg0->trans.x; + spF8.z = temp_r31->unkB8 - arg0->trans.z; + temp_f29 = VECMagXZ(&spF8); + if (temp_f29 > 25.0f) { + spF8.x = temp_r31->unkB0 - arg0->trans.x; + spF8.z = temp_r31->unkB8 - arg0->trans.z; + temp_f30 = atan2d(spF8.x, spF8.z); + arg0->rot.y = fn_1_122F4(temp_f30, arg0->rot.y, 15.0f); + arg0->trans.x += 25.0 * sind(arg0->rot.y) * 0.5; + arg0->trans.z += 25.0 * cosd(arg0->rot.y) * 0.5; + if (temp_r31->unk16 != 2) { + temp_r31->unk16 = 2; + CharModelMotionSet(temp_r31->unk02, arg0->motion[temp_r31->unk16]); + Hu3DModelAttrSet(arg0->model[0], HU3D_MOTATTR_LOOP); + } + break; + } + arg0->trans.x = temp_r31->unkB0; + arg0->trans.z = temp_r31->unkB8; + temp_r31->unk18 = 1; + if (temp_r31->unk16 != 0) { + temp_r31->unk16 = 0; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + } + break; + case 1: + arg0->rot.y = fn_1_122F4(0.0f, arg0->rot.y, 5.0f); + if (fabs(fn_1_121DC(arg0->rot.y, 0.0f)) < 1.0) { + arg0->rot.y = 0.0f; + temp_r31->unk18 = 2; + } + break; + case 2: + temp_r31->unk18 = 3; + break; + case 3: + arg0->rot.y = fn_1_122F4(0.0f, arg0->rot.y, 10.0f); + if (fn_1_F00() >= 7) { + temp_r31->unk18 = 10; + temp_r31->unk68 = 0; + break; + } + if (fabs(fn_1_121DC(arg0->rot.y, 0.0f)) < 1.0) { + arg0->rot.y = 0.0f; + sp104 = lbl_1_data_5E8; + mtxRot(sp11C, arg0->rot.x, arg0->rot.y, arg0->rot.z); + fn_1_1293C(sp11C, &sp104); + sp104.x += arg0->trans.x; + sp104.y += arg0->trans.y; + sp104.z += arg0->trans.z; + if (fn_1_F00() <= 6 && (temp_r31->unk5C = fn_1_A9D4(temp_r31->unk02, lbl_1_data_1B0[temp_r31->unk0C], sp104)) != -1) { + temp_r31->unk18 = 4; + temp_r31->unk68 = 0; + } + } + break; + case 4: + temp_r26 = fn_1_AE64(temp_r31->unk5C); + if (fn_1_F00() >= 7) { + temp_r31->unk18 = 10; + temp_r31->unk68 = 0; + break; + } + if (temp_r26 == -1 || temp_r31->unk5C == -1) { + temp_r31->unk18 = 3; + break; + } + if (temp_r26 == 2) { + if (++temp_r31->unk68 >= 6.0f) { + HuAudFXPlay(0x61A); + temp_r31->unk18 = 5; + temp_r31->unk68 = 0; + } + break; + } + if (++temp_r31->unk68 >= 54.0f && temp_r31->unk16 != 3) { + temp_r31->unk16 = 3; + CharModelMotionSet(temp_r31->unk02, arg0->motion[temp_r31->unk16]); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + } + break; + case 5: + temp_f30 = fabs(fn_1_121DC(arg0->rot.y, temp_r31->unk78)); + if (temp_f30 < 10.0f) { + arg0->rot.y += temp_f30; + } else { + arg0->rot.y += 10.0f; + } + sp104 = lbl_1_data_5E8; + mtxRot(sp11C, arg0->rot.x, arg0->rot.y, arg0->rot.z); + fn_1_1293C(sp11C, &sp104); + sp104.x += arg0->trans.x; + sp104.y += arg0->trans.y; + sp104.z += arg0->trans.z; + fn_1_AC0C(temp_r31->unk5C, sp104); + spF8.x = 0.0f; + spF8.y = 1.0f; + spF8.z = 1.0f; + sp104.y = 0.0f; + fn_1_DD70(sp104, spF8, 50.0f, -0.5f, 10.0f, 1.0f, lbl_1_data_5F4); + if (fn_1_F00() >= 7) { + temp_r31->unk18 = 10; + temp_r31->unk68 = 0; + break; + } + if (fabs(fn_1_121DC(arg0->rot.y, temp_r31->unk78)) < 1.0) { + temp_r31->unkC8 = sp104; + temp_r31->unk18 = 6; + temp_r31->unk68 = 0; + } + break; + case 6: + sp110.x = 0.0125f * var_r29 * 300.0f; + sp110.y = -900.0f; + sp110.z = -900.0f; + temp_f30 = atan2d(sp110.x - temp_r31->unkC8.x, sp110.z - temp_r31->unkC8.z); + arg0->rot.y = fn_1_122F4(temp_f30, arg0->rot.y, 5.0f); + if (fn_1_F00() >= 7) { + temp_r31->unk18 = 10; + temp_r31->unk68 = 0; + break; + } + if (var_r24 & PAD_BUTTON_A) { + temp_r31->unk16 = 4; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_NONE); + temp_r27->unk_88 = 0.5f; + temp_r31->unkD4 = sp110; + temp_r31->unk18 = 7; + temp_r31->unk68 = 0; + } + break; + case 7: + temp_r31->unk68++; + if (temp_r31->unk68 > 90.0f) { + temp_r31->unk68 = 90; + } + temp_f29 = 0.011111111f * temp_r31->unk68; + sp110.x = 0.0125f * var_r29 * 300.0f; + sp110.y = -900.0f; + sp110.z = -900.0f; + temp_f30 = atan2d(sp110.x - temp_r31->unkC8.x, sp110.z - temp_r31->unkC8.z); + arg0->rot.y = fn_1_122F4(temp_f30, arg0->rot.y, 5.0f); + temp_r31->unkD4 = sp110; + if (fn_1_F00() >= 7) { + temp_r31->unk18 = 10; + temp_r31->unk68 = 0; + break; + } + if (!(var_r25 & PAD_BUTTON_A)) { + var_f25 = 15.000001f + 30.0f * temp_f29; + temp_r31->unk60 = var_f25; + temp_r31->unk16 = 5; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_NONE); + temp_r27->unk_88 = 0.5f + 1.5f * temp_f29; + temp_r31->unk18 = 8; + temp_r31->unk68 = 0; + } + break; + case 8: + if (fn_1_F00() >= 7) { + temp_r31->unk18 = 10; + temp_r31->unk68 = 0; + break; + } + if (CharModelMotionTimeGet(temp_r31->unk02) >= 10.0f && CharModelMotionShiftIDGet(temp_r31->unk02) == -1) { + temp_r26 = fn_1_AE64(temp_r31->unk5C); + if (temp_r26 == -1 || temp_r31->unk5C == -1) { + temp_r31->unk18 = 3; + } + PSVECSubtract(&temp_r31->unkD4, &temp_r31->unkC8, &spF8); + PSVECNormalize(&spF8, &spF8); + temp_f27 = 15.0f; + spF8.x *= temp_r31->unk60 * cosd(temp_f27); + spF8.z *= temp_r31->unk60 * cosd(temp_f27); + spF8.y = temp_r31->unk60 * sind(temp_f27); + fn_1_AC80(temp_r31->unk5C, spF8); + temp_r31->unk5C = -1; + HuAudFXPlay(0x61F); + sp104 = temp_r31->unkC8; + sp104.y += 75.0f; + spF8.x = 0.0f; + spF8.y = 1.0f; + spF8.z = 1.0f; + sp104.y = 0.0f; + fn_1_DC24(sp104, spF8, 50.0f, -0.5f, 1.0f, lbl_1_data_5F8); + temp_f29 = (temp_r31->unk60 - 15.000001f) / 30.0f; + if (temp_f29 > 0.66f) { + HuAudFXPlay(0x61B); + } else if (temp_f29 > 0.33f) { + HuAudFXPlay(0x61C); + } else { + HuAudFXPlay(0x61D); + } + temp_r31->unk18 = 9; + temp_r31->unk68 = 0; + } + break; + case 9: + if (fn_1_F00() >= 7) { + temp_r31->unk18 = 10; + temp_r31->unk68 = 0; + break; + } + if (++temp_r31->unk68 >= 12.0f) { + temp_r31->unk16 = 0; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + temp_r31->unk18 = 3; + temp_r31->unk68 = 0; + } + break; + case 10: + arg0->rot.y = fn_1_122F4(0.0f, arg0->rot.y, 10.0f); + if (CharModelMotionShiftIDGet(temp_r31->unk02) == -1 && temp_r31->unk16 != 0) { + temp_r31->unk16 = 0; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + } + break; + case 11: + if (CharModelMotionShiftIDGet(temp_r31->unk02) == -1 && temp_r31->unk16 != 6) { + temp_r31->unk16 = 6; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_NONE); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + } + break; + case 12: + if (CharModelMotionShiftIDGet(temp_r31->unk02) == -1 && temp_r31->unk16 != 7) { + temp_r31->unk16 = 7; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_NONE); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + } + break; + } +} + +GXColor lbl_1_data_630 = { 0xFF, 0xFF, 0xFF, 0x14 }; + +void fn_1_5D18(omObjData* arg0) { + Vec sp60; + Vec sp54; + Vec sp48; + float var_f30; + float var_f31; + float var_f29; + StructBssBCData* temp_r31; + ModelData* temp_r27; + s16 var_r26; + s16 var_r25; + s16 var_r28; + s16 var_r24; + s16 i; + + temp_r31 = arg0->data; + temp_r27 = &Hu3DData[arg0->model[0]]; + temp_r31->unk0E = HuPadBtn[temp_r31->unk04]; + temp_r31->unk10 = HuPadBtnDown[temp_r31->unk04]; + temp_r31->unk12 = HuPadStkX[temp_r31->unk04]; + temp_r31->unk14 = HuPadStkY[temp_r31->unk04]; + if (fn_1_F00() == 6) { + if (temp_r31->unk06 != 0) { + temp_r31->unk0E &= ~PAD_BUTTON_A; + temp_r31->unk10 &= ~PAD_BUTTON_A; + temp_r31->unk12 = 0; + temp_r31->unk14 = 0; + fn_1_8CB4(arg0); + } + var_r28 = temp_r31->unk12; + var_r24 = temp_r31->unk14; + } + if (fabs(var_r28) < 8.0) { + var_r28 = 0; + } + if (fabs(var_r28) > 80.0) { + var_r28 = 80; + } + if (fabs(var_r24) < 8.0) { + var_r24 = 0; + } + if (fabs(var_r24) > 80.0) { + var_r24 = 80; + } + switch (temp_r31->unk18) { + case 0: + if (fn_1_F00() >= 6) { + temp_r31->unk18 = 1; + } + break; + case 1: + if (fabs(var_r28) > 8.0) { + var_f30 = 0.125f * var_r28; + } else { + var_f30 = 0.0f; + } + temp_r31->unk1C[temp_r31->unk58] = var_f30; + if (++temp_r31->unk58 >= 15) { + temp_r31->unk58 = 0; + } + for (i = 0, var_f30 = 0.0f; i < 15; i++) { + var_f30 += temp_r31->unk1C[i]; + } + var_f30 *= 0.06666667f; + if (var_f30 > 25.0f) { + var_f30 = 25.0f; + } else if (var_f30 < -25.0f) { + var_f30 = -25.0f; + } + if (0.0f == var_f30) { + var_r25 = 0; + } else if (fabs(var_f30) < 10.0) { + var_r25 = 1; + } else { + var_r25 = 2; + } + if (temp_r31->unk16 != var_r25 && CharModelMotionShiftIDGet(temp_r31->unk02) == -1) { + temp_r31->unk16 = var_r25; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + } + if (temp_r31->unk16 == 1 && CharModelMotionShiftIDGet(temp_r31->unk02) == -1) { + var_f31 = fabs(0.1f * var_f30); + if (var_f31 < 0.25f) { + var_f31 = 0.25f; + } + CharModelMotionSpeedSet(temp_r31->unk02, var_f31); + } + if (var_r28 == 0.0f) { + var_f29 = 0.0f; + } else if (var_r28 < 0.0f) { + var_f29 = -90.0f; + } else { + var_f29 = 90.0f; + } + if (arg0->rot.y < var_f29 && (arg0->rot.y += 20.0f) > var_f29) { + arg0->rot.y = var_f29; + } + if (arg0->rot.y > var_f29 && (arg0->rot.y -= 20.0f) < var_f29) { + arg0->rot.y = var_f29; + } + arg0->trans.x += var_f30; + arg0->trans.y = 0.0f; + arg0->trans.z = temp_r31->unkB8; + if (arg0->trans.x < -225.0f) { + arg0->trans.x = -225.0f; + } + if (arg0->trans.x > 225.0f) { + arg0->trans.x = 225.0f; + } + if (fn_1_F00() >= 7) { + temp_r31->unk18 = 9; + temp_r31->unk68 = 0; + } else if (temp_r31->unk10 & PAD_BUTTON_A) { + if (var_r28 > 0) { + temp_r27->unk_0C = -1; + temp_r31->unk16 = 3; + CharModelMotionSet(temp_r31->unk02, arg0->motion[temp_r31->unk16]); + CharModelMotionSpeedSet(temp_r31->unk02, 1.0f); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + temp_r31->unk7C = 6.5f; + temp_r31->unk68 = 0; + arg0->rot.y = 90.0f; + i = 99; + if ((var_r26 = fn_1_B304(lbl_1_bss_40)) != 0) { + for (i = 0; i < var_r26; i++) { + if (lbl_1_bss_40[0]->unk1C < lbl_1_bss_40[0]->unk14 || lbl_1_bss_40[0]->unk1C - lbl_1_bss_40[0]->unk14 > 6.0f) { + continue; + } + if (lbl_1_bss_40[0]->unk1C < 36.0f) { + var_f31 = lbl_1_bss_40[0]->unk68.z - arg0->trans.z; + } else { + var_f31 = lbl_1_bss_40[0]->unk38.z - arg0->trans.z; + } + if (var_f31 < -100.0f) { + continue; + } + var_f31 = fabs(var_f31); + if (var_f31 >= 300.0f) { + temp_r31->unk8C = 13.5f; + } else if (var_f31 <= 100.0f) { + temp_r31->unk8C = 6.5f; + } else { + temp_r31->unk8C = 10.0f; + } + } + } + if (i >= var_r26) { + temp_r31->unk8C = 10.0f; + } + temp_r31->unk18 = 2; + } else if (var_r28 < 0) { + temp_r27->unk_0C = -1; + temp_r31->unk16 = 5; + CharModelMotionSet(temp_r31->unk02, arg0->motion[temp_r31->unk16]); + CharModelMotionSpeedSet(temp_r31->unk02, 1.0f); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + temp_r31->unk7C = 6.5f; + temp_r31->unk68 = 0; + arg0->rot.y = -90.0f; + i = 99; + if ((var_r26 = fn_1_B304(lbl_1_bss_40)) != 0) { + for (i = 0; i < var_r26; i++) { + if (lbl_1_bss_40[0]->unk1C < lbl_1_bss_40[0]->unk14 || lbl_1_bss_40[0]->unk1C - lbl_1_bss_40[0]->unk14 > 6.0f) { + continue; + } + if (lbl_1_bss_40[0]->unk1C < 36.0f) { + var_f31 = lbl_1_bss_40[0]->unk68.z - arg0->trans.z; + } else { + var_f31 = lbl_1_bss_40[0]->unk38.z - arg0->trans.z; + } + if (var_f31 > 100.0f) { + continue; + } + var_f31 = fabs(var_f31); + if (var_f31 >= 300.0f) { + temp_r31->unk8C = 13.5f; + } else if (var_f31 <= 100.0f) { + temp_r31->unk8C = 6.5f; + } else { + temp_r31->unk8C = 10.0f; + } + } + } + if (i >= var_r26) { + temp_r31->unk8C = 10.0f; + } + temp_r31->unk18 = 4; + } else { + temp_r27->unk_0C = -1; + temp_r31->unk16 = 7; + CharModelMotionSet(temp_r31->unk02, arg0->motion[temp_r31->unk16]); + CharModelMotionSpeedSet(temp_r31->unk02, 1.0f); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + temp_r31->unk7C = 10.5f; + temp_r31->unk68 = 0; + arg0->rot.y = 0.0f; + temp_r31->unk18 = 7; + } + } + break; + case 2: + arg0->trans.x += temp_r31->unk8C; + if (arg0->trans.x > 225.0f) { + arg0->trans.x = 225.0f; + } + arg0->trans.y += temp_r31->unk7C; + temp_r31->unk7C -= 0.49f; + temp_r31->unk68++; + if (temp_r31->unk68 == temp_r31->unk80 - 12.0f) { + temp_r31->unk16 = 4; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_NONE); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + } + if (arg0->trans.y <= 0.0f) { + for (i = 0; i < 6; i++) { + sp48.x = sind(-90.0f + 30.0f * i); + sp48.z = cosd(-90.0f + 30.0f * i); + sp48.y = 0.0f; + sp54.x = 100.0f * sp48.x * 0.01f; + sp54.z = 100.0f * sp48.z * 0.01f; + sp54.y = 1.0f; + sp60.x = arg0->trans.x + 100.0f * sp48.x * 0.2; + sp60.z = arg0->trans.z + 100.0f * sp48.z * 0.2; + sp60.y = 0.0f; + fn_1_DD70(sp60, sp54, 50.0f, -0.25f, 20.0f, 0.5f, lbl_1_data_630); + } + arg0->trans.y = 0.0f; + temp_r31->unk18 = 3; + } + break; + case 3: + if (CharModelMotionEndCheck(temp_r31->unk02) && CharModelMotionShiftIDGet(temp_r31->unk02) == -1) { + memset(&temp_r31->unk1C, 0, sizeof(temp_r31->unk1C)); + temp_r31->unk58 = 0; + temp_r31->unk16 = 0; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + temp_r31->unk18 = 6; + temp_r31->unkAC = 0; + } + break; + case 4: + arg0->trans.x -= temp_r31->unk8C; + if (arg0->trans.x < -225.0f) { + arg0->trans.x = -225.0f; + } + arg0->trans.y += temp_r31->unk7C; + temp_r31->unk7C -= 0.49f; + temp_r31->unk68++; + if (temp_r31->unk68 == temp_r31->unk80 - 12.0f) { + temp_r31->unk16 = 6; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_NONE); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + } + if (arg0->trans.y <= 0.0f) { + for (i = 0; i < 6; i++) { + sp48.x = sind(-90.0f + 30.0f * i); + sp48.z = cosd(-90.0f + 30.0f * i); + sp48.y = 0.0f; + sp54.x = 100.0f * sp48.x * 0.01f; + sp54.z = 100.0f * sp48.z * 0.01f; + sp54.y = 1.0f; + sp60.x = arg0->trans.x + 100.0f * sp48.x * 0.2; + sp60.z = arg0->trans.z + 100.0f * sp48.z * 0.2; + sp60.y = 0.0f; + fn_1_DD70(sp60, sp54, 50.0f, -0.25f, 20.0f, 0.5f, lbl_1_data_630); + } + arg0->trans.y = 0.0f; + temp_r31->unk18 = 5; + } + break; + case 5: + if (CharModelMotionEndCheck(temp_r31->unk02) && CharModelMotionShiftIDGet(temp_r31->unk02) == -1) { + memset(&temp_r31->unk1C, 0, sizeof(temp_r31->unk1C)); + temp_r31->unk58 = 0; + temp_r31->unk16 = 0; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + temp_r31->unk18 = 6; + temp_r31->unkAC = 0; + } + break; + case 6: + if (++temp_r31->unkAC > 0.0f) { + temp_r31->unkAC = 0; + temp_r31->unk18 = 1; + } + break; + case 7: + arg0->trans.y += temp_r31->unk7C; + temp_r31->unk7C -= 0.65333337f; + temp_r31->unk68++; + if (arg0->trans.y <= 0.0f) { + temp_r31->unk16 = 0; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_NONE); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + arg0->trans.y = 0.0f; + temp_r31->unk68 = 0; + temp_r31->unk18 = 8; + } + break; + case 8: + if (++temp_r31->unk68 > 12.0f) { + memset(&temp_r31->unk1C, 0, sizeof(temp_r31->unk1C)); + temp_r31->unk58 = 0; + temp_r31->unk16 = 0; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + temp_r31->unk18 = 1; + } + break; + case 9: + arg0->rot.y = fn_1_122F4(0.0f, arg0->rot.y, 10.0f); + if (CharModelMotionShiftIDGet(temp_r31->unk02) == -1 && temp_r31->unk16 != 1) { + temp_r31->unk16 = 1; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + } + if (CharModelMotionShiftIDGet(temp_r31->unk02) == -1 && temp_r31->unk16 == 1) { + arg0->trans.z += 5.0f; + } + if (arg0->trans.z > lbl_1_data_150->z + 100.0f) { + temp_r31->unk18 = 10; + } + break; + case 10: + arg0->rot.y = fn_1_122F4(0.0f, arg0->rot.y, 10.0f); + if (CharModelMotionShiftIDGet(temp_r31->unk02) == -1 && temp_r31->unk16 != 0) { + temp_r31->unk16 = 0; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_LOOP); + } + break; + case 11: + if (CharModelMotionShiftIDGet(temp_r31->unk02) == -1 && temp_r31->unk16 != 9) { + temp_r31->unk16 = 9; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_NONE); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + } + break; + case 12: + if (CharModelMotionShiftIDGet(temp_r31->unk02) == -1 && temp_r31->unk16 != 10) { + temp_r31->unk16 = 10; + CharModelMotionShiftSet(temp_r31->unk02, arg0->motion[temp_r31->unk16], 0.0f, 8.0f, HU3D_MOTATTR_NONE); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_LOOP); + Hu3DModelAttrReset(arg0->model[0], HU3D_MOTATTR_SHIFT_LOOP); + } + break; + } + lbl_1_bss_B8 = arg0; + temp_r31->unkEC = arg0->trans.x - temp_r31->unkE0; + temp_r31->unkF0 = arg0->trans.y - temp_r31->unkE4; + temp_r31->unkF4 = arg0->trans.z - temp_r31->unkE8; + temp_r31->unkE0 = arg0->trans.x; + temp_r31->unkE4 = arg0->trans.y; + temp_r31->unkE8 = arg0->trans.z; +} + +void fn_1_77C4(omObjData* arg0) { + arg0->func = NULL; +} + +void fn_1_77D0(void) { + s32 i; + + for (i = 0; i < 4; i++) { + fn_1_77C4(lbl_1_bss_BC[i]); + } +} + +s32 fn_1_781C(void) { + omObjData* temp_r29; + StructBssBCData* temp_r31; + s32 i; + + for (i = 0; i < 4; i++) { + temp_r29 = lbl_1_bss_BC[i]; + temp_r31 = temp_r29->data; + if (temp_r31->unk0A == 0) { + if (temp_r31->unk18 != 0 || fabs(fn_1_121DC(temp_r29->rot.y, 0.0f)) > 1.0) { + break; + } + } else { + if (temp_r31->unk18 < 5) { + break; + } + } + } + if (i >= 4) { + return 1; + } + return 0; +} + +s32 fn_1_791C(void) { + omObjData* temp_r30; + StructBssBCData* temp_r31; + s32 i; + + for (i = 0; i < 4; i++) { + temp_r30 = lbl_1_bss_BC[i]; + temp_r31 = temp_r30->data; + if (temp_r31->unk0A == 0) { + if (temp_r31->unk18 != 10 || fabs(fn_1_121DC(temp_r30->rot.y, 0.0f)) > 1.0 || CharModelMotionShiftIDGet(temp_r31->unk02) != -1) { + break; + } + } else { + if (temp_r31->unk18 != 10 || fabs(fn_1_121DC(temp_r30->rot.y, 0.0f)) > 1.0 || CharModelMotionShiftIDGet(temp_r31->unk02) != -1) { + break; + } + } + } + if (i >= 4) { + return 1; + } + return 0; +} + +void fn_1_7AA8(s32 arg0) { + omObjData* var_r29; + StructBssBCData* temp_r31; + s32 i; + + for (i = 0; i < 4; i++) { + var_r29 = lbl_1_bss_BC[i]; + temp_r31 = var_r29->data; + if (temp_r31->unk0A == 0) { + if (temp_r31->unk0A == arg0) { + temp_r31->unk18 = 11; + } else { + temp_r31->unk18 = 12; + } + } else { + if (temp_r31->unk0A == arg0) { + temp_r31->unk18 = 11; + } else { + temp_r31->unk18 = 12; + } + } + } +} + +s32 fn_1_7B48(Vec* arg0, Vec* arg1, Vec* arg2, float arg3) { + Vec spA8[4]; + Vec sp78[4]; + Vec sp48[4]; + Vec sp3C; + Vec sp30; + Vec sp24; + Vec sp18; + Vec spC; + float var_f31; + float var_f28; + float var_f30; + float var_f27; + float var_f26; + omObjData* temp_r31; + StructBssBCData* temp_r28; + ModelData* sp8; + + if (lbl_1_bss_B8 == NULL) { + return 0; + } + temp_r31 = lbl_1_bss_B8; + temp_r28 = temp_r31->data; + sp8 = &Hu3DData[temp_r31->model[0]]; + *arg2 = *arg1; + switch (temp_r28->unk18) { + case 2: + case 4: + var_f31 = 150.0f; + var_f28 = 130.0f; + var_f30 = 60.000004f; + var_f27 = 130.0f; + break; + default: + var_f31 = 100.0f; + var_f28 = 130.0f; + var_f30 = 60.000004f; + var_f27 = 0.0f; + break; + } + sp78[0].x = temp_r31->trans.x - 0.5f * var_f31; + sp78[0].y = temp_r31->trans.y + var_f28; + sp78[0].z = temp_r31->trans.z + 0.5f * var_f30; + sp78[1].x = temp_r31->trans.x + 0.5f * var_f31; + sp78[1].y = temp_r31->trans.y + var_f28; + sp78[1].z = temp_r31->trans.z + 0.5f * var_f30; + sp78[2].x = temp_r31->trans.x + 0.5f * var_f31; + sp78[2].y = temp_r31->trans.y - var_f27; + sp78[2].z = temp_r31->trans.z + 0.5f * var_f30; + sp78[3].x = temp_r31->trans.x - 0.5f * var_f31; + sp78[3].y = temp_r31->trans.y - var_f27; + sp78[3].z = temp_r31->trans.z + 0.5f * var_f30; + spA8[0].x = temp_r31->trans.x + 0.5f * var_f31; + spA8[0].y = temp_r31->trans.y + var_f28; + spA8[0].z = temp_r31->trans.z - 0.5f * var_f30; + spA8[1].x = temp_r31->trans.x - 0.5f * var_f31; + spA8[1].y = temp_r31->trans.y + var_f28; + spA8[1].z = temp_r31->trans.z - 0.5f * var_f30; + spA8[2].x = temp_r31->trans.x - 0.5f * var_f31; + spA8[2].y = temp_r31->trans.y - var_f27; + spA8[2].z = temp_r31->trans.z - 0.5f * var_f30; + spA8[3].x = temp_r31->trans.x + 0.5f * var_f31; + spA8[3].y = temp_r31->trans.y - var_f27; + spA8[3].z = temp_r31->trans.z - 0.5f * var_f30; + PSVECNormalize(arg1, &spC); + PSVECScale(&spC, &spC, arg3); + PSVECAdd(arg0, arg1, &sp30); + PSVECAdd(arg0, arg1, &sp24); + PSVECAdd(arg0, &spC, &sp3C); + PSVECAdd(&sp30, &spC, &sp30); + sp48[0] = sp78[0]; + sp48[1] = sp78[1]; + sp48[2] = sp78[2]; + sp48[3] = sp78[3]; + if (fn_1_137C4(sp48, arg0, arg1, &sp18, arg3, 4) != 0) { + arg2->x *= 0.5f; + arg2->z *= -0.5f; + fn_1_82C8(15, 1, 0); + return 1; + } + if (sp24.x >= sp78[0].x - arg3 && sp24.x <= sp78[2].x + arg3 + && sp24.y <= sp78[0].y + arg3 && sp24.y >= sp78[2].y - arg3 + && sp24.z <= sp78[0].z + arg3 && sp24.z >= spA8[3].z - arg3) + { + if (temp_r28->unkEC > 0.0f && sp24.x > temp_r31->trans.x) { + spC = *arg1; + spC.y = 0.0f; + var_f26 = PSVECMag(&spC); + arg2->x = 0.5f * var_f26 + temp_r28->unkEC; + arg2->z = 0.0f; + } else if (temp_r28->unkEC < 0.0f && sp24.x < temp_r31->trans.x) { + spC = *arg1; + spC.y = 0.0f; + var_f26 = PSVECMag(&spC); + arg2->x = -(0.5f * var_f26) + temp_r28->unkEC; + arg2->z = 0.0f; + } else { + if (fabs(arg1->x) > fabs(arg1->z)) { + arg2->x *= -1.0f; + } else { + arg2->z *= -1.0f; + } + arg2->x *= 0.5f; + arg2->z *= 0.5f; + } + fn_1_82C8(15, 1, 0); + return 1; + } + return 0; +} + +void fn_1_82C8(s32 arg0, s32 arg1, s32 arg2) { + omObjData* var_r31; + StructBssBCData* var_r30; + + if (lbl_1_bss_B8 != NULL) { + var_r31 = lbl_1_bss_B8; + var_r30 = var_r31->data; + omVibrate(var_r30->unk00, 12, 6, 6); + HuAudFXPlay(0x61A); + } +} + +s32 lbl_1_data_668[] = { 3, 4, 5, 6 }; +float lbl_1_data_678[] = { 0.6f, 0.65f, 0.7f, 0.7f }; + +s32 lbl_1_data_688[][2] = { + { 30, 60 }, { 24, 48 }, { 12, 24 }, { 0, 12 } +}; + +s32 lbl_1_data_6A8[][2] = { + { 36, 84 }, { 36, 78 }, { 33, 72 }, { 33, 66 } +}; + +void fn_1_8338(omObjData* arg0) { + float var_f31; + float temp_f30; + StructBssBCData* temp_r31; + ModelData* sp8; + s32 var_r29; + + temp_r31 = arg0->data; + sp8 = &Hu3DData[arg0->model[0]]; + var_r29 = temp_r31->unk18; + if (temp_r31->unkA0 == 0) { + temp_r31->unkA0 = 1; + temp_r31->unk70 = 0; + var_r29 = 5; + } + switch (var_r29) { + case 5: + if (temp_r31->unk70 != 0) { + break; + } + if (temp_r31->unk9C > lbl_1_bss_108 && lbl_1_data_668[temp_r31->unk08] > temp_r31->unk98 && lbl_1_bss_B8 != NULL) { + temp_r31->unkA4 = 1; + temp_r31->unkA8 = (1.0f / 127) * frand7(); + if (lbl_1_bss_B8->trans.x >= 270.0f) { + temp_r31->unk88 = -(0.4f + 0.3f * temp_r31->unkA8); + } else if (lbl_1_bss_B8->trans.x <= -270.0f) { + temp_r31->unk88 = 0.4f + 0.3f * temp_r31->unkA8; + } else if (frand() & 1) { + temp_r31->unk88 = -(0.3f + 0.1f * temp_r31->unkA8); + } else { + temp_r31->unk88 = 0.3f + 0.1f * temp_r31->unkA8; + } + var_f31 = lbl_1_data_6A8[3][0]; + temp_f30 = lbl_1_data_6A8[3][1]; + temp_r31->unk70 = var_f31 + (1.0f / 127) * frand7() * (temp_f30 - var_f31); + var_f31 = lbl_1_data_688[temp_r31->unk08][0]; + temp_f30 = lbl_1_data_688[temp_r31->unk08][1]; + temp_r31->unk74 = var_f31 + (1.0f / 127) * frand7() * (temp_f30 - var_f31); + temp_r31->unk98++; + } else { + if (frand() & 1) { + temp_r31->unk88 = (1.0f / 127) * frand7() * lbl_1_data_678[temp_r31->unk08]; + } else { + temp_r31->unk88 = -((1.0f / 127) * frand7()) * lbl_1_data_678[temp_r31->unk08]; + } + var_f31 = lbl_1_data_6A8[temp_r31->unk08][0]; + temp_f30 = lbl_1_data_6A8[temp_r31->unk08][1]; + temp_r31->unk70 = var_f31 + (1.0f / 127) * frand7() * (temp_f30 - var_f31); + var_f31 = lbl_1_data_688[temp_r31->unk08][0]; + temp_f30 = lbl_1_data_688[temp_r31->unk08][1]; + temp_r31->unk74 = var_f31 + (1.0f / 127) * frand7() * (temp_f30 - var_f31); + } + temp_r31->unk6C = 0; + break; + case 6: + if (++temp_r31->unk6C >= temp_r31->unk74) { + temp_r31->unk12 = 80.0f * temp_r31->unk88; + temp_r31->unk10 |= PAD_BUTTON_A; + temp_r31->unk0E |= PAD_BUTTON_A; + temp_r31->unk6C = 0; + return; + } + var_f31 = sind(180.0f * ((temp_r31->unk74 - temp_r31->unk6C) / 60.0f)); + if (temp_r31->unk74 & 1) { + var_f31 *= -1.0f; + } + temp_r31->unk12 = 80.0f * (temp_r31->unk88 + var_f31); + return; + case 7: + if (temp_r31->unkA4 != 0) { + if (lbl_1_bss_B8->trans.x >= 148.5f) { + temp_r31->unk88 = -(0.4f + 0.3f * temp_r31->unkA8); + } else if (lbl_1_bss_B8->trans.x <= -148.5f) { + temp_r31->unk88 = 0.4f + 0.3f * temp_r31->unkA8; + } else if (lbl_1_bss_B8->trans.x > 0.0f) { + temp_r31->unk88 = -(0.5f + 0.2f * temp_r31->unkA8); + } else { + temp_r31->unk88 = 0.5f + 0.2f * temp_r31->unkA8; + } + } + temp_r31->unk12 = 80.0f * temp_r31->unk88; + if (++temp_r31->unk6C > temp_r31->unk70) { + temp_r31->unk88 = 0.0f; + temp_r31->unk6C = 0; + temp_r31->unk70 = 0; + temp_r31->unk74 = 0; + temp_r31->unkA4 = 0; + } else { + temp_r31->unk0E |= PAD_BUTTON_A; + } + break; + default: + temp_r31->unk6C = 0; + break; + } +} + +s32 lbl_1_data_6C8[] = { 60, 45, 30, 15 }; + +float lbl_1_data_6D8[][2] = { + { 200.0f, 150.0f }, { 125.0f, 100.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f } +}; + +s32 lbl_1_data_6F8[][2] = { + { 48, 150 }, { 39, 114 }, { 33, 90 }, { 21, 42 } +}; + +s32 lbl_1_data_718[][2] = { + { 27, 39 }, { 15, 27 }, { 9, 15 }, { 0, 3 } +}; + +void fn_1_8CB4(omObjData* arg0) { + Vec spC; + float temp_f29; + float temp_f28; + float var_f30; + float var_f31; + float var_f26; + float temp_f27; + StructBssBCData* temp_r31; + ModelData* sp8; + StructBssA8Data* temp_r30; + s32 var_r28; + s32 var_r24; + s32 i, j; + s32 var_r25; + + var_r25 = 0; + temp_r31 = arg0->data; + sp8 = &Hu3DData[arg0->model[0]]; + if (temp_r31->unk64 != -1) { + temp_r30 = fn_1_B13C(temp_r31->unk64); + if (temp_r30 != NULL) { + if (temp_r30->unk0C != 3 || temp_r30->unk08 != 0 || temp_r30->unk38.z <= -900.0f) { + var_r25 = 1; + } + } else { + var_r25 = 1; + } + } else { + var_r25 = 1; + } + if (var_r25 != 0) { + temp_r31->unk64 = -1; + temp_r31->unk6C = 0; + temp_f29 = lbl_1_data_6F8[temp_r31->unk08][0]; + temp_f28 = lbl_1_data_6F8[temp_r31->unk08][1]; + temp_r31->unk90 = temp_f29 + (1.0f / 127) * frand7() * (temp_f28 - temp_f29); + temp_f29 = lbl_1_data_718[temp_r31->unk08][0]; + temp_f28 = lbl_1_data_718[temp_r31->unk08][1]; + temp_r31->unk94 = temp_f29 + (1.0f / 127) * frand7() * (temp_f28 - temp_f29); + temp_r31->unkD4.x = lbl_1_data_6D8[temp_r31->unk08][0] * (0.5f - (1.0f / 127) * frand7()); + temp_r31->unkD4.y = lbl_1_data_6D8[temp_r31->unk08][1] * (0.5f - (1.0f / 127) * frand7()); + if (lbl_1_bss_104 >= 5) { + temp_r31->unkD4.x *= 1.5f; + } + var_r24 = fn_1_B304(lbl_1_bss_4); + if (var_r24 != 0) { + for (i = 0; i < var_r24; i++) { + temp_r30 = lbl_1_bss_4[i]; + if (temp_r30 == NULL || temp_r30->unk06 == 0 + || 0.0f == temp_r30->unk50.z + || fabs(temp_r30->unk38.x) >= 325.0 + || temp_r30->unk14 < temp_r31->unk94) + { + continue; + } + var_r28 = (var_f26 - temp_r30->unk38.z) / temp_r30->unk50.z; + if (var_r28 > 300.0f) { + continue; + } + spC = temp_r30->unk50; + var_f30 = temp_r30->unk38.x; + var_f31 = temp_r30->unk38.y; + for (j = 0; j < var_r28; j++) { + var_f30 += spC.x; + var_f31 += spC.y; + spC.x *= temp_r30->unk8C; + spC.z *= temp_r30->unk8C; + spC.y -= 0.32666668f; + if (var_f31 < 20.0) { + var_f31 = 0.32666668f; + spC.y *= temp_r30->unk90; + } + } + var_f30 += temp_r31->unkD4.x; + var_f31 += temp_r31->unkD4.y; + if (temp_r31->unk08 <= 2 || !(fabs(var_f30) >= 225.0 || var_f31 >= 200.0f)) { + temp_r31->unk64 = temp_r30->unk02; + break; + } + } + } + } + if (temp_r31->unk64 != -1 && (temp_r30 = fn_1_B13C(temp_r31->unk64)) != NULL) { + if (temp_r30->unk38.z > 60.000004f + arg0->trans.z) { + var_f26 = 60.000004f + arg0->trans.z; + var_r28 = (var_f26 - temp_r30->unk38.z) / temp_r30->unk50.z; + if (var_r28 > 300.0f) { + temp_r31->unk64 = -1; + return; + } + spC = temp_r30->unk50; + var_f30 = temp_r30->unk38.x; + var_f31 = temp_r30->unk38.y; + for (j = 0; j < var_r28; j++) { + var_f30 += spC.x; + var_f31 += spC.y; + spC.x *= temp_r30->unk8C; + spC.z *= temp_r30->unk8C; + spC.y -= 0.32666668f; + if (var_f31 < 20.0) { + var_f31 = 0.32666668f; + spC.y *= temp_r30->unk90; + } + } + var_r28 += temp_r31->unk90; + var_f30 += temp_r31->unkD4.x; + var_f31 += temp_r31->unkD4.y; + } else { + var_r28 = 0; + var_f30 = temp_r30->unk38.x; + var_f31 = temp_r30->unk38.y; + } + if (arg0->trans.x - 25.0f > var_f30) { + temp_r31->unk12 = -64; + } + if (arg0->trans.x + 25.0f < var_f30) { + temp_r31->unk12 = 64; + } + temp_f27 = fabs(var_f30 - arg0->trans.x); + if (var_r28 < 10 && temp_f27 > 120.00001f) { + temp_r31->unk10 |= 0x100; + } else if (var_r28 < 5 && temp_f27 < 25.0f && var_f31 > 100.0f) { + temp_r31->unk10 |= 0x100; + } else if (var_r28 > 20 && temp_f27 < 50.0) { + temp_r31->unk10 /= 2; + } + if (++temp_r31->unk6C > lbl_1_data_6C8[temp_r31->unk08]) { + temp_r31->unk64 = -1; + } + } +} + +void fn_1_95C4(void) { + lbl_1_bss_A8 = omAddObjEx(lbl_1_bss_120, 0x50, 0, 0, -1, fn_1_9614); +} + +s32 lbl_1_data_738[] = { + DATA_MAKE_NUM(DATADIR_M423, 4), + DATA_MAKE_NUM(DATADIR_M423, 5), + DATA_MAKE_NUM(DATADIR_M423, 6), + DATA_MAKE_NUM(DATADIR_M423, 7), + DATA_MAKE_NUM(DATADIR_M423, 8), + DATA_MAKE_NUM(DATADIR_M423, 9), + DATA_MAKE_NUM(DATADIR_M423, 10), + DATA_MAKE_NUM(DATADIR_M423, 11) +}; + +void fn_1_9614(omObjData* arg0) { + StructBssA8Data* var_r28; + StructBssA8Data* var_r31; + ModelData* var_r27; + s32 i; + + if (lbl_1_bss_EC[0] == -1) { + return; + } + var_r31 = var_r28 = arg0->data = HuMemDirectMallocNum(HEAP_SYSTEM, 15 * sizeof(*var_r31), MEMORY_DEFAULT_NUM); + memset(var_r31, 0, 15 * sizeof(*var_r31)); + for (i = 0; i < 15; i++, var_r31++) { + var_r31->unk04 = i % 3; + var_r31->unk02 = i; + var_r31->unk06 = 0; + var_r31->unk0A = 0; + var_r31->unk08 = 0; + var_r31->unk0C = 0; + var_r31->unk0E = 0; + var_r31->unk10 = 0; + var_r31->unk12 = 0; + var_r31->unk14 = 0; + var_r31->unk18 = 0; + var_r31->unk1C = 0; + var_r31->unk38.x = var_r31->unk38.y = var_r31->unk38.z = 0.0f; + var_r31->unk44 = var_r31->unk48 = var_r31->unk4C = 0.0f; + var_r31->unk50.x = var_r31->unk50.y = var_r31->unk50.z = 0.0f; + var_r31->unk74 = var_r31->unk38; + var_r31->unk80 = var_r31->unk50; + var_r31->unk8C = 0.995f; + var_r31->unk90 = -0.5f; + var_r31->unk68.x = var_r31->unk68.y = var_r31->unk68.z = 0.0f; + if (i < 3) { + var_r31->unk00 = Hu3DModelCreateFile(lbl_1_data_738[lbl_1_bss_EC[var_r31->unk04]]); + } else { + var_r31->unk00 = Hu3DModelLink(var_r28[var_r31->unk04].unk00); + } + Hu3DModelScaleSet(var_r31->unk00, 0.8f, 0.8f, 0.8f); + Hu3DModelAttrSet(var_r31->unk00, HU3D_ATTR_DISPOFF); + Hu3DModelCameraSet(var_r31->unk00, 5); + Hu3DModelShadowSet(var_r31->unk00); + var_r27 = &Hu3DData[var_r31->unk00]; + PSMTXIdentity(var_r27->unk_F0); + } + fn_1_B430(); + arg0->func = fn_1_98A0; +} + +void fn_1_98A0(omObjData* arg0) { + Mtx spC4; + Vec spB8; + Vec spAC; + Vec spA0; + Vec sp94; + Vec sp88; + float temp_f30; + float var_f25; + float var_f31; + float var_f22; + StructBssA8Data* var_r31; + StructBssA8Data* var_r30; + ModelData* temp_r27; + s32 i, j; + s32 var_r25; + s32 var_r23; + s32 var_r28; + + var_r31 = arg0->data; + for (i = 0; i < 15; i++, var_r31++) { + if (var_r31->unk06 == 0) { + continue; + } + temp_r27 = &Hu3DData[var_r31->unk00]; + var_r25 = 0; + switch (var_r31->unk0C) { + case 0: + break; + case 1: + temp_f30 = var_r31->unk14 / 60.0f; + var_r31->unk14++; + if (temp_f30 > 1.0f) { + var_f31 = 1.0f; + } else { + var_f31 = temp_f30; + } + var_r31->unk38.x = var_r31->unk20.x + var_f31 * (var_r31->unk2C.x - var_r31->unk20.x); + var_r31->unk38.z = var_r31->unk20.z + var_f31 * (var_r31->unk2C.z - var_r31->unk20.z); + if (temp_f30 < 0.6f) { + var_f31 = temp_f30 / 0.6f; + var_f25 = 100.0f; + } else if (temp_f30 < 1.0f) { + var_f31 = (temp_f30 - 0.6f) / 0.4f; + var_f25 = 50.0f; + } else { + var_f31 = (temp_f30 - 1.0f) / 0.25f; + var_f25 = 10.0f; + } + var_r31->unk38.y = 20.0 + var_f25 * sind(180.0f * var_f31); + if (var_r31->unk14 >= 75.0f) { + var_r31->unk0C = 2; + var_r31->unk14 = 0; + var_r31->unk38.y = 20.0f; + var_r31->unk50.y = 0.0f; + } + if (var_r31->unk14 < 73.2f) { + spAC.x = var_r31->unk50.z; + spAC.z = -var_r31->unk50.x; + spAC.y = 0.0f; + var_f31 = 0.05 * PSVECMag(&spAC); + if (var_f31 > 0.00001f) { + PSMTXRotAxisRad(spC4, &spAC, var_f31); + PSMTXConcat(spC4, temp_r27->unk_F0, temp_r27->unk_F0); + } + } + Hu3DModelPosSet(var_r31->unk00, var_r31->unk38.x, var_r31->unk38.y, var_r31->unk38.z); + Hu3DModelRotSet(var_r31->unk00, var_r31->unk44, var_r31->unk48, var_r31->unk4C); + break; + case 2: + Hu3DModelPosSet(var_r31->unk00, var_r31->unk38.x, var_r31->unk38.y, var_r31->unk38.z); + Hu3DModelRotSet(var_r31->unk00, var_r31->unk44, var_r31->unk48, var_r31->unk4C); + break; + case 3: + var_r31->unk74 = var_r31->unk38; + var_r31->unk80 = var_r31->unk50; + var_r23 = 0; + if (var_r28 = fn_1_C498(&var_r31->unk38, &var_r31->unk50, &spB8, &sp88, 20.0f, 3)) { + if (var_r28 & 0x8000) { + var_r25 = 1; + } + if (var_r28 & 0x2000) { + } + if ((var_r28 & 0x4000) && var_r31->unk12 == 0 && var_r31->unk08 == 0) { + var_f31 = VECMagXZ(&var_r31->unk50); + sp94.x = 0.0f; + sp94.y = 0.0f; + sp94.z = (1.0f / 127) * frand7() * 360.0f; + fn_1_E334(spB8, sp94, 0.5f); + HuAudFXPlay(0x620); + var_r31->unk12 = 1; + } + var_r31->unk38 = spB8; + var_r31->unk50 = sp88; + var_r31->unk8C = 0.975f; + var_r31->unk90 = -0.5f; + } else { + if (fabs(var_r31->unk38.x) > 1000.0) { + Hu3DModelAttrSet(var_r31->unk00, HU3D_ATTR_DISPOFF); + var_r31->unk0C = 0; + var_r31->unk06 = 0; + var_r31->unk14 = 0; + } else { + var_r31->unk38.x += var_r31->unk50.x; + var_r31->unk38.y += var_r31->unk50.y; + var_r31->unk38.z += var_r31->unk50.z; + } + } + if (var_r31->unk08 == 0) { + for (j = 0, var_r30 = arg0->data; j < 15; j++, var_r30++) { + if (i == j || var_r30->unk06 == 0 || var_r30->unk08 != 0 || var_r30->unk0C != 3) { + continue; + } + PSVECSubtract(&var_r31->unk38, &var_r30->unk38, &spAC); + var_f31 = PSVECMag(&spAC); + if (var_f31 < 40.0) { + spA0 = var_r31->unk38; + if (var_f31 != 0.0f) { + temp_f30 = 40.0 - var_f31; + PSVECNormalize(&spAC, &spAC); + PSVECScale(&spAC, &spAC, temp_f30); + PSVECAdd(&var_r31->unk38, &spAC, &var_r31->unk38); + } else { + var_r31->unk38.x += 40.0; + } + temp_f30 = PSVECMag(&var_r31->unk50); + var_f22 = PSVECMag(&var_r30->unk50); + var_f31 = 0.5f * (temp_f30 + var_f22); + if (PSVECMag(&var_r31->unk50) == 0.0f) { + var_r31->unk50.x = 1.0f; + } + PSVECNormalize(&var_r31->unk50, &var_r31->unk50); + PSVECSubtract(&var_r31->unk38, &var_r30->unk38, &spAC); + if (PSVECMag(&spAC) == 0.0f) { + spAC.x = 1.0f; + } + PSVECNormalize(&spAC, &spAC); + PSVECAdd(&var_r31->unk50, &spAC, &var_r31->unk50); + if (PSVECMag(&var_r31->unk50) == 0.0f) { + var_r31->unk50.x = 1.0f; + } + PSVECNormalize(&var_r31->unk50, &var_r31->unk50); + PSVECScale(&var_r31->unk50, &var_r31->unk50, var_f31); + if (PSVECMag(&var_r30->unk50) == 0.0f) { + var_r30->unk50.x = -1.0f; + } + PSVECNormalize(&var_r30->unk50, &var_r30->unk50); + PSVECSubtract(&var_r30->unk38, &var_r31->unk38, &spAC); + if (PSVECMag(&spAC) == 0.0f) { + spAC.x = 1.0f; + } + PSVECNormalize(&spAC, &spAC); + PSVECAdd(&var_r30->unk50, &spAC, &var_r30->unk50); + if (PSVECMag(&var_r30->unk50) == 0.0f) { + var_r30->unk50.x = -1.0f; + } + PSVECNormalize(&var_r30->unk50, &var_r30->unk50); + PSVECScale(&var_r30->unk50, &var_r30->unk50, var_f31); + if (var_r28 = fn_1_C498(&spA0, &spAC, &spB8, &sp88, 20.0f, 1)) { + if (var_r28 & 0x8000) { + var_r25 = 1; + } + var_r31->unk38 = spB8; + var_r31->unk50 = sp88; + } + } + } + } + if (var_r31->unk38.y < 20.0) { + var_r31->unk38.y = 20.0f; + var_r31->unk50.y *= var_r31->unk90; + var_r23 = 1; + if (var_r31->unk38.x >= -225.0f && var_r31->unk38.x <= 225.0f + && var_r31->unk38.z >= -1100.0f && var_r31->unk38.z <= -900.0f) + { + var_r25 = 1; + } + if (fabs(var_r31->unk50.y) < 0.05f) { + var_r31->unk50.y = 0.0f; + } + } + if (var_r31->unk08 == 0) { + PSVECSubtract(&var_r31->unk38, &var_r31->unk74, &spAC); + if (fn_1_7B48(&var_r31->unk38, &var_r31->unk50, &sp88, 20.0f) != 0) { + var_r31->unk50 = sp88; + var_r31->unk08 = 1; + var_r31->unk8C = 0.975f; + var_r31->unk90 = -0.5f; + } + } + if (var_r31->unk50.z > 0.0f) { + var_r31->unk08 = 1; + } + var_r31->unk50.y -= 0.32666668f; + if (var_r23 == 0) { + var_r31->unk50.x *= var_r31->unk8C; + var_r31->unk50.z *= var_r31->unk8C; + } else { + var_r31->unk50.x *= 0.995f * var_r31->unk8C; + var_r31->unk50.z *= 0.995f * var_r31->unk8C; + } + if (var_r25 != 0 && var_r31->unk0A == 0 && var_r31->unk08 == 0) { + fn_1_AEE8(i); + } + if (var_r31->unk08 != 0) { + var_r31->unk18++; + if (var_r31->unk18 & 1) { + Hu3DModelAttrReset(var_r31->unk00, HU3D_ATTR_DISPOFF); + } else { + Hu3DModelAttrSet(var_r31->unk00, HU3D_ATTR_DISPOFF); + } + if (var_r31->unk18 >= 120.0f) { + Hu3DModelAttrSet(var_r31->unk00, HU3D_ATTR_DISPOFF); + var_r31->unk0C = 0; + var_r31->unk06 = 0; + var_r31->unk14 = 0; + var_r31->unk18 = 0; + } + } + temp_f30 = VECMagXZ(&var_r31->unk50); + if (fabs(temp_f30) < 0.1f && var_r31->unk38.y <= 20.0 && var_r31->unk08 == 0) { + var_r31->unk0C = 4; + var_r31->unk14 = 0; + var_r31->unk18 = 0; + } + if (fabs(var_r31->unk38.x) > 2000.0 || fabs(var_r31->unk38.y) > 2000.0 || fabs(var_r31->unk38.z) > 2000.0) { + var_r31->unk0C = 4; + var_r31->unk14 = 0; + var_r31->unk18 = 120; + } + var_r31->unk14++; + spAC.x = var_r31->unk50.z; + spAC.z = -var_r31->unk50.x; + spAC.y = 0.0f; + var_f31 = 0.05 * PSVECMag(&spAC); + if (var_f31 > 0.00001f) { + PSMTXRotAxisRad(spC4, &spAC, var_f31); + PSMTXConcat(spC4, temp_r27->unk_F0, temp_r27->unk_F0); + } + Hu3DModelPosSet(var_r31->unk00, var_r31->unk38.x, var_r31->unk38.y, var_r31->unk38.z); + break; + case 4: + var_r31->unk18++; + if (var_r31->unk18 & 1) { + Hu3DModelAttrReset(var_r31->unk00, HU3D_ATTR_DISPOFF); + } else { + Hu3DModelAttrSet(var_r31->unk00, HU3D_ATTR_DISPOFF); + } + if (var_r31->unk18 >= 120.0f) { + Hu3DModelAttrSet(var_r31->unk00, HU3D_ATTR_DISPOFF); + var_r31->unk0C = 0; + var_r31->unk06 = 0; + var_r31->unk14 = 0; + var_r31->unk18 = 0; + } + break; + } + } +} + +void fn_1_A9A0(omObjData* arg0) { + arg0->func = NULL; +} + +void fn_1_A9AC(void) { + fn_1_A9A0(lbl_1_bss_A8); +} + +s32 fn_1_A9D4(s32 arg0, Vec arg1, Vec arg2) { + StructBssA8Data* var_r31; + ModelData* temp_r26; + s32 var_r27; + s32 i; + + if (lbl_1_bss_A8 == NULL) { + return -1; + } + var_r31 = lbl_1_bss_A8->data; + for (i = 0, var_r27 = -1; i < 3; i++) { + if (arg0 == lbl_1_bss_EC[i]) { + var_r27 = i; + } + } + if (var_r27 == -1) { + return -1; + } + for (i = 0; i < 15; i++, var_r31++) { + if (var_r31->unk04 == var_r27 && var_r31->unk06 == 0) { + break; + } + } + if (i >= 15) { + return -1; + } + temp_r26 = &Hu3DData[var_r31->unk00]; + var_r31->unk06 = 1; + var_r31->unk0A = 0; + var_r31->unk08 = 0; + var_r31->unk10 = 0; + var_r31->unk12 = 0; + var_r31->unk0C = 1; + var_r31->unk14 = 0; + var_r31->unk18 = 0; + var_r31->unk20 = arg1; + var_r31->unk2C = arg2; + var_r31->unk38 = arg1; + var_r31->unk44 = var_r31->unk48 = var_r31->unk4C = 0.0f; + var_r31->unk50.x = 0.016666668f * (arg2.x - arg1.x); + var_r31->unk50.z = 0.016666668f * (arg2.z - arg1.z); + var_r31->unk50.y = 5.0f; + Hu3DModelPosSet(var_r31->unk00, var_r31->unk38.x, var_r31->unk38.y, var_r31->unk38.z); + Hu3DModelRotSet(var_r31->unk00, var_r31->unk44, var_r31->unk48, var_r31->unk4C); + Hu3DModelAttrReset(var_r31->unk00, HU3D_ATTR_DISPOFF); + PSMTXIdentity(temp_r26->unk_F0); + return i; +} + +void fn_1_AC0C(s32 arg0, Vec arg1) { + StructBssA8Data* var_r31; + + if (lbl_1_bss_A8 != NULL) { + var_r31 = lbl_1_bss_A8->data; + if (arg0 < 0 || arg0 >= 15) { + return; + } + var_r31[arg0].unk38 = arg1; + } +} + +void fn_1_AC80(s32 arg0, Vec arg1) { + Vec sp14; + Vec sp8; + float var_f31; + StructBssA8Data* var_r28; + StructBssA8Data* temp_r31; + + if (lbl_1_bss_A8 == NULL) { + return; + } + var_r28 = lbl_1_bss_A8->data; + if (arg0 < 0 || arg0 >= 15) { + return; + } + temp_r31 = &var_r28[arg0]; + temp_r31->unk0C = 3; + temp_r31->unk14 = 0; + temp_r31->unk18 = 0; + temp_r31->unk50 = arg1; + temp_r31->unk74 = temp_r31->unk38; + temp_r31->unk8C = 0.995f; + temp_r31->unk90 = -0.5f; + if (temp_r31->unk50.z < 0.0f) { + sp14 = temp_r31->unk38; + var_f31 = -800.0f - sp14.z; + temp_r31->unk1C = fabs(var_f31 / temp_r31->unk50.z); + PSVECScale(&arg1, &sp8, temp_r31->unk1C); + PSVECAdd(&sp14, &sp8, &temp_r31->unk68); + } else { + temp_r31->unk1C = 1000; + } +} + +s32 fn_1_AE64(s32 arg0) { + StructBssA8Data* temp_r31; + + if (lbl_1_bss_A8 == NULL) { + return -1; + } + temp_r31 = lbl_1_bss_A8->data; + if (arg0 < 0 || arg0 >= 15) { + return -1; + } + if (temp_r31[arg0].unk06 == 0) { + return -1; + } + return temp_r31[arg0].unk0C; +} + +void fn_1_AEE8(s32 arg0) { + StructBssA8Data* var_r26; + StructBssA8Data* temp_r31; + + if (lbl_1_bss_A8 == NULL) { + return; + } + var_r26 = lbl_1_bss_A8->data; + if (arg0 < 0 || arg0 >= 15) { + return; + } + temp_r31 = &var_r26[arg0]; + temp_r31->unk0A = 1; + temp_r31->unk08 = 1; + temp_r31->unk14 = 0; + fn_1_F574(temp_r31->unk38, 0.75f, lbl_1_bss_EC[temp_r31->unk04]); + HuAudFXPlay(9); + fn_1_3A8C(); + lbl_1_bss_DC[temp_r31->unk04]++; + lbl_1_bss_104--; +} + +StructBssA8Data* fn_1_B13C(s32 arg0) { + StructBssA8Data* temp_r31; + StructBssA8Data* sp8; + + if (lbl_1_bss_A8 == NULL) { + return NULL; + } + temp_r31 = lbl_1_bss_A8->data; + sp8 = temp_r31; + if (arg0 < 0 || arg0 >= 15) { + return NULL; + } + return &temp_r31[arg0]; +} + +GXColor lbl_1_data_758 = { 0xFF, 0xFF, 0xFF, 0xFF }; + +void fn_1_B1A4(void) { + Vec sp2C; + StructBssA8Data* sp10; + StructBssA8Data* var_r31; + s32 spC; + s32 i; + + if (lbl_1_bss_A8 == NULL) { + return; + } + var_r31 = sp10 = lbl_1_bss_A8->data; + for (i = 0, spC = 0; i < 15; i++, var_r31++) { + if (var_r31->unk06 == 0) { + continue; + } + sp2C.x = sp2C.y = sp2C.z = 0.0f; + fn_1_DC24(var_r31->unk38, sp2C, 100.0f, 0.0f, 1.0f, lbl_1_data_758); + Hu3DModelAttrSet(var_r31->unk00, HU3D_ATTR_DISPOFF); + var_r31->unk0C = 0; + var_r31->unk06 = 0; + var_r31->unk14 = 0; + var_r31->unk18 = 0; + } +} + +s32 fn_1_B304(StructBssA8Data** arg0) { + s32 var_r29; + s32 i; + StructBssA8Data* var_r30; + StructBssA8Data* var_r28; + StructBssA8Data* var_r27; + + if (lbl_1_bss_A8 == NULL) { + return; + } + var_r30 = lbl_1_bss_A8->data; + var_r28 = var_r30; + for (i = 0, var_r29 = 0; i < 15; i++, var_r30++) { + if (var_r30->unk06 == 0 || var_r30->unk0C != 3 || var_r30->unk08 != 0 || var_r30->unk38.z <= -900.0f) { + continue; + } + arg0[var_r29] = var_r30; + var_r29++; + } + var_r28 = var_r30; + for (i = 0; i < var_r29 - 1; i++) { + if (arg0[i]->unk38.z > arg0[i + 1]->unk38.z) { + var_r27 = arg0[i]; + arg0[i] = arg0[i + 1]; + arg0[i + 1] = var_r27; + } + } + return var_r29; +} + +void fn_1_B430(void) { + Vec sp2C[8]; + Vec sp20; + Vec sp14; + Vec sp8; + StructBss94Data* var_r31; + s32 i; + + var_r31 = lbl_1_bss_94 = HuMemDirectMallocNum(HEAP_SYSTEM, 16 * sizeof(*lbl_1_bss_94), MEMORY_DEFAULT_NUM); + memset(var_r31, 0, 16 * sizeof(*var_r31)); + for (i = 0; i < 16; i++, var_r31++) { + var_r31->unk02 = 0; + } + sp20.x = sp20.y = 0.0f; + sp20.z = -1400.0f; + fn_1_BCD8(&sp20, NULL, NULL, 0.8f, 0, 0x2003); + sp2C[0].x = 1000.0f; + sp2C[0].y = 1000.0f; + sp2C[0].z = -200.0f; + sp2C[1].x = -1000.0f; + sp2C[1].y = 1000.0f; + sp2C[1].z = -200.0f; + sp2C[2].x = -1000.0f; + sp2C[2].y = 0.0f; + sp2C[2].z = -200.0f; + sp2C[3].x = 1000.0f; + sp2C[3].y = 0.0f; + sp2C[3].z = -200.0f; + fn_1_BCD8(sp2C, NULL, NULL, 1.0f, 0, 6); + sp20.x = -650.0f; + sp20.y = 75.0f; + sp20.z = -1300.0f; + sp14.x = 370.0f; + sp14.y = 1095.0f; + sp14.z = 120.0f; + fn_1_BCD8(&sp20, &sp14, NULL, 0.8f, 25, 0x2004); + sp20.x = 650.0f; + sp20.y = 75.0f; + sp20.z = -1300.0f; + sp14.x = 370.0f; + sp14.y = 1095.0f; + sp14.z = 120.0f; + fn_1_BCD8(&sp20, &sp14, NULL, 0.8f, 21, 0x2004); + sp20.x = 0.0f; + sp20.y = 100.0f; + sp20.z = -1070.0f; + sp14.x = 245.0f; + sp14.y = 130.0f; + sp14.z = 170.0f; + fn_1_BCD8(&sp20, &sp14, NULL, 1.0f, 45, 4); + sp20.x = -235.0f; + sp20.y = 0.0f; + sp20.z = -900.0f; + sp14.x = -235.0f; + sp14.y = 200.0f; + sp14.z = -900.0f; + sp8.x = 30.000002f; + sp8.y = sp8.z = 0.0f; + fn_1_BCD8(&sp20, &sp14, &sp8, 0.5f, 0, 0x4007); + sp20.x = 235.0f; + sp20.y = 0.0f; + sp20.z = -900.0f; + sp14.x = 235.0f; + sp14.y = 200.0f; + sp14.z = -900.0f; + sp8.x = 30.000002f; + sp8.y = sp8.z = 0.0f; + fn_1_BCD8(&sp20, &sp14, &sp8, 0.5f, 0, 0x4007); + sp20.x = 0.0f; + sp20.y = 200.0f; + sp20.z = -900.0f; + sp14.x = 245.0f; + sp14.y = 30.0f; + sp14.z = 30.0f; + fn_1_BCD8(&sp20, &sp14, NULL, 0.5f, 29, 0x4004); + sp2C[0].x = -225.0f; + sp2C[0].y = 200.0f; + sp2C[0].z = -900.0f; + sp2C[1].x = -225.0f; + sp2C[1].y = 200.0f; + sp2C[1].z = -1150.0f; + sp2C[2].x = -225.0f; + sp2C[2].y = 0.0f; + sp2C[2].z = -1150.0f; + sp2C[3].x = -225.0f; + sp2C[3].y = 0.0f; + sp2C[3].z = -900.0f; + fn_1_BCD8(sp2C, NULL, NULL, 0.5f, 0, 0x8006); + sp2C[0].x = 225.0f; + sp2C[0].y = 200.0f; + sp2C[0].z = -1150.0f; + sp2C[1].x = 225.0f; + sp2C[1].y = 200.0f; + sp2C[1].z = -900.0f; + sp2C[2].x = 225.0f; + sp2C[2].y = 0.0f; + sp2C[2].z = -900.0f; + sp2C[3].x = 225.0f; + sp2C[3].y = 0.0f; + sp2C[3].z = -1150.0f; + fn_1_BCD8(sp2C, NULL, NULL, 0.5f, 0, 0x8006); + sp2C[0].x = -225.0f; + sp2C[0].y = 200.0f; + sp2C[0].z = -1150.0f; + sp2C[1].x = 225.0f; + sp2C[1].y = 200.0f; + sp2C[1].z = -1150.0f; + sp2C[2].x = 225.0f; + sp2C[2].y = 0.0f; + sp2C[2].z = -1150.0f; + sp2C[3].x = -225.0f; + sp2C[3].y = 0.0f; + sp2C[3].z = -1150.0f; + fn_1_BCD8(sp2C, NULL, NULL, 0.1f, 0, 0x8006); + sp2C[0].x = -225.0f; + sp2C[0].y = 200.0f; + sp2C[0].z = -900.0f; + sp2C[1].x = 225.0f; + sp2C[1].y = 200.0f; + sp2C[1].z = -900.0f; + sp2C[2].x = 225.0f; + sp2C[2].y = 200.0f; + sp2C[2].z = -1150.0f; + sp2C[3].x = -225.0f; + sp2C[3].y = 200.0f; + sp2C[3].z = -1150.0f; + fn_1_BCD8(sp2C, NULL, NULL, 0.1f, 0, 0x8006); +} + +s16 lbl_1_data_75C[][3] = { + { 0, 1, 2 }, { 1, 3, 2 }, { 6, 5, 4 }, { 5, 6, 7 }, + { 0, 2, 4 }, { 2, 6, 4 }, { 3, 1, 7 }, { 7, 1, 5 }, + { 2, 3, 6 }, { 3, 7, 6 }, { 1, 0, 4 }, { 1, 4, 5 } +}; + +void fn_1_BCD8(Vec* arg0, Vec* arg1, Vec* arg2, float arg3, s32 arg4, s32 arg5) { + Vec sp24[8]; + Vec sp18; + float var_f29; + StructBss94Data* var_r30; + s32 i; + s32 j; + + var_r30 = lbl_1_bss_94; + for (i = 0; i < 16; i++, var_r30++) { + if (var_r30->unk02 == 0) { + break; + } + } + if (i >= 16) { + return; + } + var_r30->unk00 = i; + var_r30->unk02 = arg5; + var_r30->unk3C = arg3; + switch (var_r30->unk02 & 0xFFF) { + case 1: + var_r30->unk34 = arg0[0].x; + break; + case 2: + var_r30->unk34 = arg0[0].y; + break; + case 3: + var_r30->unk34 = arg0[0].z; + break; + case 4: + var_r30->unk04 = arg0[0]; + var_r30->unk10 = *arg1; + sp24[0].x = arg0[0].x - arg1->x; + sp24[0].y = arg0[0].y + arg1->y; + sp24[0].z = arg0[0].z - arg1->z; + sp24[1].x = arg0[0].x + arg1->x; + sp24[1].y = arg0[0].y + arg1->y; + sp24[1].z = arg0[0].z - arg1->z; + sp24[2].x = arg0[0].x - arg1->x; + sp24[2].y = arg0[0].y + arg1->y; + sp24[2].z = arg0[0].z + arg1->z; + sp24[3].x = arg0[0].x + arg1->x; + sp24[3].y = arg0[0].y + arg1->y; + sp24[3].z = arg0[0].z + arg1->z; + sp24[4].x = arg0[0].x - arg1->x; + sp24[4].y = arg0[0].y - arg1->y; + sp24[4].z = arg0[0].z - arg1->z; + sp24[5].x = arg0[0].x + arg1->x; + sp24[5].y = arg0[0].y - arg1->y; + sp24[5].z = arg0[0].z - arg1->z; + sp24[6].x = arg0[0].x - arg1->x; + sp24[6].y = arg0[0].y - arg1->y; + sp24[6].z = arg0[0].z + arg1->z; + sp24[7].x = arg0[0].x + arg1->x; + sp24[7].y = arg0[0].y - arg1->y; + sp24[7].z = arg0[0].z + arg1->z; + for (j = 0; j < 12; j++) { + fn_1_129F0(&sp24[lbl_1_data_75C[j][0]], + &sp24[lbl_1_data_75C[j][1]], + &sp24[lbl_1_data_75C[j][2]], + var_r30->unk44[j]); + var_r30->unk104[j][0] = sp24[lbl_1_data_75C[j][0]]; + var_r30->unk104[j][1] = sp24[lbl_1_data_75C[j][1]]; + var_r30->unk104[j][2] = sp24[lbl_1_data_75C[j][2]]; + } + var_r30->unk40 = arg4; + break; + case 5: + var_r30->unk104[0][0] = arg0[0]; + var_r30->unk104[1][0] = arg0[1]; + var_r30->unk104[2][0] = arg0[2]; + var_r30->unk104[3][0] = arg0[3]; + fn_1_129F0(&arg0[0], &arg0[1], &arg0[3], var_r30->unk44[0]); + fn_1_129F0(&arg0[1], &arg0[2], &arg0[3], var_r30->unk44[1]); + break; + case 6: + var_r30->unk104[0][0] = arg0[0]; + var_r30->unk104[1][0] = arg0[1]; + var_r30->unk104[2][0] = arg0[2]; + var_r30->unk104[3][0] = arg0[3]; + fn_1_129F0(&arg0[0], &arg0[1], &arg0[3], var_r30->unk44[0]); + fn_1_129F0(&arg0[1], &arg0[2], &arg0[3], var_r30->unk44[1]); + if (var_r30->unk44[0][1] < -0.5f) { + var_r30->unk40 = 0; + } + if (var_r30->unk44[0][1] > 0.5f) { + var_r30->unk40 = 1; + } + if (var_r30->unk44[0][0] > 0.5f) { + var_r30->unk40 = 2; + } + if (var_r30->unk44[0][0] < -0.5f) { + var_r30->unk40 = 3; + } + if (var_r30->unk44[0][2] < -0.5f) { + var_r30->unk40 = 4; + } + if (var_r30->unk44[0][2] > 0.5f) { + var_r30->unk40 = 5; + } + break; + case 7: + var_r30->unk04 = arg0[0]; + var_r30->unk10 = *arg1; + var_r30->unk34 = arg2->x; + sp18.x = arg1->x - arg0[0].x; + sp18.y = arg1->y - arg0[0].y; + sp18.z = arg1->z - arg0[0].z; + var_f29 = VECMagXZ(&sp18); + var_r30->unk28 = -atan2d(sp18.y, var_f29); + var_r30->unk2C = atan2d(sp18.x, sp18.z); + var_r30->unk30 = 0.0f; + break; + } +} + +s32 lbl_1_data_7C4[] = { 1, 1, 0, 0, 2, 2 }; + +s32 fn_1_C498(Vec* arg0, Vec* arg1, Vec* arg2, Vec* arg3, float arg4, s32 arg5) { + StructBss94Data* var_r31; + Vec sp140[6]; + Vec sp134; + Vec sp128; + Vec sp11C; + Vec sp110; + Vec sp104; + Vec spF8; + Vec spEC; + Vec spE0; + Vec spD4; + Vec spC8; + float var_f30; + float var_f19; + float sp34; + float sp30; + float sp2C; + s32 var_r26; + s32 var_r24; + s32 var_r23; + s32 i; + s32 j; + + var_r31 = lbl_1_bss_94; + var_r26 = -1; + sp134.x = arg0->x + arg1->x; + sp134.y = arg0->y + arg1->y; + sp134.z = arg0->z + arg1->z; + for (i = 0; i < 16; i++, var_r31++) { + if (var_r31->unk02 == 0) { + continue; + } + switch (var_r31->unk02 & 0xFFF) { + case 1: + if (arg1->x < 0.0f) { + if (arg0->x > var_r31->unk34 + arg4 && sp134.x <= var_r31->unk34 + arg4 + 1.0f) { + sp134.x = var_r31->unk34 + arg4; + *arg2 = sp134; + var_r26 = 0; + } + } else { + if (arg0->x < var_r31->unk34 - arg4 && sp134.x >= var_r31->unk34 - arg4 - 1.0f) { + sp134.x = var_r31->unk34 - arg4; + *arg2 = sp134; + var_r26 = 0; + } + } + break; + case 2: + if (arg1->y < 0.0f) { + if (arg0->y > var_r31->unk34 + arg4 && sp134.y <= var_r31->unk34 + arg4 + 1.0f) { + sp134.y = var_r31->unk34 + arg4; + *arg2 = sp134; + var_r26 = 1; + } + } else { + if (arg0->y < var_r31->unk34 - arg4 && sp134.y >= var_r31->unk34 - arg4 - 1.0f) { + sp134.y = var_r31->unk34 - arg4; + *arg2 = sp134; + var_r26 = 1; + } + } + break; + case 3: + if (arg1->z < 0.0f) { + if (arg0->z > var_r31->unk34 + arg4 && sp134.z <= var_r31->unk34 + arg4 + 1.0f) { + sp134.z = var_r31->unk34 + arg4; + *arg2 = sp134; + var_r26 = 2; + } + } else { + if (arg0->z < var_r31->unk34 - arg4 && sp134.z >= var_r31->unk34 - arg4 - 1.0f) { + sp134.z = var_r31->unk34 - arg4; + *arg2 = sp134; + var_r26 = 2; + } + } + break; + case 4: + arg4 = 0.0f; + PSVECSubtract(&sp134, &var_r31->unk04, &sp128); + if (fabs(sp128.x) < var_r31->unk10.x + arg4 + && fabs(sp128.y) < var_r31->unk10.y + arg4 + && fabs(sp128.z) < var_r31->unk10.z + arg4) + { + for (j = 0; j < 6; j++) { + if (var_r31->unk40 & (1 << j)) { + var_r24 = fn_1_12C6C(arg0, &sp134, var_r31->unk44[j * 2]); + if (var_r24 != 0) { + break; + } + } + } + switch (j) { + case 0: + sp134.y = var_r31->unk04.y + var_r31->unk10.y + arg4 + 1.0f; + break; + case 1: + sp134.y = var_r31->unk04.y - var_r31->unk10.y - arg4 - 1.0f; + break; + case 2: + sp134.x = var_r31->unk04.x - var_r31->unk10.x - arg4 - 1.0f; + break; + case 3: + sp134.x = var_r31->unk04.x + var_r31->unk10.x + arg4 + 1.0f; + break; + case 4: + sp134.z = var_r31->unk04.z + var_r31->unk10.z + arg4 + 1.0f; + break; + case 5: + sp134.z = var_r31->unk04.z - var_r31->unk10.z - arg4 - 1.0f; + break; + } + if (j < 6) { + *arg2 = sp134; + var_r26 = lbl_1_data_7C4[j]; + } + } + break; + case 5: + if (fn_1_12C6C(arg0, &sp134, var_r31->unk44[0]) != 1) { + break; + } + fn_1_1334C(var_r31->unk44[0], arg0, arg1, var_r31->unk104[0], &sp104); + sp110.x = fabs(var_r31->unk44[0][0]); + sp110.y = fabs(var_r31->unk44[0][1]); + sp110.z = fabs(var_r31->unk44[0][2]); + if (sp110.x > sp110.y && sp110.x > sp110.z) { + var_r24 = 0; + } else if (sp110.y > sp110.x && sp110.y > sp110.z) { + var_r24 = 1; + } else { + var_r24 = 2; + } + sp140[0] = var_r31->unk104[0][0]; + sp140[1] = var_r31->unk104[1][0]; + sp140[2] = var_r31->unk104[3][0]; + sp140[3] = var_r31->unk104[1][0]; + sp140[4] = var_r31->unk104[2][0]; + sp140[5] = var_r31->unk104[3][0]; + sp34 = fn_1_12E68(&sp140[0], &sp104, var_r24); + sp30 = fn_1_12E68(&sp140[3], &sp104, var_r24); + if (sp34 != 0.0f || sp30 != 0.0f) { + arg2->x = sp104.x + var_r31->unk44[0][0] * (arg4 + 1.0f); + arg2->y = sp104.y + var_r31->unk44[0][1] * (arg4 + 1.0f); + arg2->z = sp104.z + var_r31->unk44[0][2] * (arg4 + 1.0f); + var_r26 = var_r24; + } + break; + case 6: + sp140[0] = var_r31->unk104[0][0]; + sp140[1] = var_r31->unk104[1][0]; + sp140[2] = var_r31->unk104[2][0]; + sp140[3] = var_r31->unk104[3][0]; + if (fn_1_137C4(&sp140[0], arg0, arg1, &sp104, arg4, var_r31->unk40) != 0) { + *arg2 = sp104; + var_r26 = lbl_1_data_7C4[var_r31->unk40]; + } + break; + case 7: + spEC.x = arg0->x; + spEC.y = arg0->z; + spEC.z = 0.0f; + spE0.x = sp134.x; + spE0.y = sp134.z; + spE0.z = 0.0f; + spD4.x = var_r31->unk04.x; + spD4.y = var_r31->unk04.z; + spD4.z = 0.0f; + var_f30 = fn_1_1367C(&spEC, &spE0, &spD4, &spC8, &sp2C); + if (sp2C >= 0.0f && sp2C <= 1.0f && var_f30 < var_r31->unk34 + arg4) { + var_f19 = arg0->y + arg1->y * sp2C; + if (var_f19 >= var_r31->unk04.y && var_f19 <= var_r31->unk10.y) { + spC8.z = spC8.y; + spC8.y = 0.0f; + PSVECSubtract(&spC8, &var_r31->unk04, &sp128); + sp128.y = 0.0f; + if (PSVECMag(&sp128) == 0.0f) { + sp128.z = 1.0f; + } else { + PSVECNormalize(&sp128, &sp128); + } + PSVECScale(&sp128, &sp128, var_r31->unk34 + arg4 + 1.0f); + arg2->x = sp128.x + var_r31->unk04.x; + arg2->z = sp128.z + var_r31->unk04.z; + arg2->y = var_f19; + sp2C = var_f30; + var_r26 = 99; + } + } else { + sp2C = var_f30; + PSVECSubtract(&sp134, &var_r31->unk04, &sp128); + var_f30 = VECMagXZ(&sp128); + if (var_f30 < var_r31->unk34 + arg4 && sp134.y >= var_r31->unk04.y && sp134.y <= var_r31->unk10.y) { + PSVECSubtract(&sp134, &var_r31->unk04, &sp128); + sp128.y = 0.0f; + if (PSVECMag(&sp128) == 0.0f) { + sp128.z = 1.0f; + } else { + PSVECNormalize(&sp128, &sp128); + } + PSVECScale(&sp128, &sp128, var_r31->unk34 + arg4 + 1.0f); + arg2->x = var_r31->unk04.x + sp128.x; + arg2->z = var_r31->unk04.z + sp128.z; + arg2->y = sp134.y; + var_r26 = 99; + } + } + if (var_r26 == -1) { + break; + } + sp128.x = spC8.x - var_r31->unk04.x; + sp128.z = spC8.y - var_r31->unk04.z; + var_f30 = VECMagXZ(&sp128); + if (var_f30 == 0.0f) { + var_f30 = 1.0f; + sp128.x = 0.0f; + sp128.z = 1.0f; + } else { + var_f30 = 1.0f / var_f30; + } + spC8.x = sp128.x * var_f30; + spC8.z = sp128.z * var_f30; + var_f30 = VECMagXZ(arg1); + if (var_f30 != 0.0f) { + var_f30 = 1.0f / var_f30; + } + spD4.x = -(arg1->x * var_f30); + spD4.z = -(arg1->z * var_f30); + sp2C = var_f30 / (var_r31->unk34 + arg4); + sp128.x = spD4.x + sp2C * (spC8.x - spD4.x); + sp128.z = spD4.z + sp2C * (spC8.z - spD4.z); + var_f30 = VECMagXZ(&sp128); + if (var_f30 == 0.0f) { + var_f30 = 1.0f; + sp128.x = 0.0f; + sp128.z = 1.0f; + } else { + var_f30 = 1.0f / var_f30; + } + sp128.x = sp128.x * var_f30 - spD4.x; + sp128.z = sp128.z * var_f30 - spD4.z; + sp128.y = 0.0f; + if (PSVECMag(&sp128) == 0.0f) { + sp128.z = 1.0f; + } else { + PSVECNormalize(&sp128, &sp128); + } + var_f30 = VECMagXZ(arg1); + arg3->x = sp128.x * var_f30 * var_r31->unk3C; + arg3->z = sp128.z * var_f30 * var_r31->unk3C; + arg3->y = arg1->y; + break; + } + if (var_r26 != -1) { + break; + } + } + if (i < 16) { + switch (var_r26) { + case 0: + arg3->x = -arg1->x * var_r31->unk3C; + arg3->y = arg1->y; + arg3->z = arg1->z * var_r31->unk3C; + var_r23 = var_r31->unk02; + break; + case 1: + arg3->x = arg1->x * var_r31->unk3C; + arg3->y = arg1->y * -0.5f; + arg3->z = arg1->z * var_r31->unk3C; + var_r23 = var_r31->unk02; + break; + case 2: + arg3->x = arg1->x * var_r31->unk3C; + arg3->y = arg1->y; + arg3->z = -arg1->z * var_r31->unk3C; + var_r23 = var_r31->unk02; + break; + default: + var_r23 = var_r31->unk02; + break; + } + arg5--; + if (arg5 > 0) { + sp11C = *arg0; + sp110.x = arg2->x - arg0->x; + sp110.y = arg2->y - arg0->y; + sp110.z = arg2->z - arg0->z; + var_r26 = fn_1_C498(&sp11C, &sp110, &sp104, &spF8, arg4, arg5); + if (var_r26 != 0) { + *arg2 = sp104; + *arg3 = spF8; + if (var_r23 & 0x4000) { + var_r26 |= 0x4000; + } + if (var_r23 & 0x8000) { + var_r26 |= 0x8000; + } + var_r23 = var_r26; + } + } + return var_r23; + } + return 0; +} + +void fn_1_D930(void) { + omObjData* var_r30; + StructBssA4Data* var_r31; + AnimData* var_r27; + StructM423_05* var_r29; + ModelData* var_r28; + s32 sp8; + + var_r30 = lbl_1_bss_A4 = omAddObjEx(lbl_1_bss_120, 0xBF, 0, 0, -1, fn_1_DA38); + var_r31 = var_r30->data = HuMemDirectMallocNum(HEAP_SYSTEM, sizeof(*var_r31), MEMORY_DEFAULT_NUM); + memset(var_r31, 0, sizeof(*var_r31)); + var_r31->unk08 = var_r27 = HuSprAnimRead(HuDataReadNum(DATA_MAKE_NUM(DATADIR_M423, 22), MEMORY_DEFAULT_NUM)); + var_r31->unk00 = sp8 = fn_1_11114(var_r27, 0x100); + Hu3DModelCameraSet(var_r31->unk00, 4); + Hu3DModelLayerSet(var_r31->unk00, 1); + var_r31->unk04 = 0; + var_r28 = &Hu3DData[var_r31->unk00]; + var_r29 = var_r28->unk_120; + var_r29->unk20 = 0; +} + +void fn_1_DA38(omObjData* arg0) { + StructBssA4Data* temp_r30; + ModelData* var_r27; + StructM423_05* temp_r29; + StructM423_04* var_r31; + s32 i; + + temp_r30 = arg0->data; + if (temp_r30->unk04 <= 0) { + Hu3DModelAttrSet(temp_r30->unk00, HU3D_ATTR_DISPOFF); + return; + } + Hu3DModelAttrReset(temp_r30->unk00, HU3D_ATTR_DISPOFF); + var_r27 = &Hu3DData[temp_r30->unk00]; + temp_r29 = var_r27->unk_120; + var_r31 = temp_r29->unk3C; + temp_r29->unk23 = 0; + for (i = 0; i < temp_r29->unk26; i++, var_r31++) { + if (var_r31->unk30 <= 0.0f) { + continue; + } + var_r31->unk38.x += var_r31->unk04.x; + var_r31->unk38.y += var_r31->unk04.y; + var_r31->unk38.z += var_r31->unk04.z; + var_r31->unk34 += var_r31->unk18; + if (var_r31->unk34 >= 360.0f) { + var_r31->unk34 -= 360.0f; + } + var_r31->unk48 = var_r31->unk28; + var_r31->unk28 += var_r31->unk2C; + if (var_r31->unk48 >= 16) { + var_r31->unk48 = 0; + var_r31->unk00 = 0; + var_r31->unk30 = 0.0f; + temp_r30->unk04--; + } + } +} + +void fn_1_DBC8(void) { + omObjData* temp_r31; + StructBssA4Data* temp_r30; + + temp_r31 = lbl_1_bss_A4; + temp_r30 = temp_r31->data; + Hu3DModelAttrSet(temp_r30->unk00, HU3D_ATTR_DISPOFF); + HuSprAnimKill(temp_r30->unk08); + temp_r31->func = NULL; +} + +inline s32 fn_1_DC24(Vec arg0, Vec arg1, float arg2, float arg3, float arg4, GXColor arg5) { + omObjData* var_r27; + StructBssA4Data* temp_r28; + ModelData* var_r26; + StructM423_05* temp_r30; + StructM423_04* var_r31; + s32 i; + + var_r27 = lbl_1_bss_A4; + temp_r28 = var_r27->data; + var_r26 = &Hu3DData[temp_r28->unk00]; + temp_r30 = var_r26->unk_120; + var_r31 = temp_r30->unk3C; + for (i = 0; i < temp_r30->unk26; i++, var_r31++) { + if (var_r31->unk30 <= 0.0f) { + break; + } + } + if (i >= temp_r30->unk26) { + return -1; + } + var_r31->unk00 = var_r31->unk02 = 0; + var_r31->unk38.x = arg0.x; + var_r31->unk38.y = arg0.y; + var_r31->unk38.z = arg0.z; + var_r31->unk04.x = arg1.x; + var_r31->unk04.y = arg1.y; + var_r31->unk04.z = arg1.z; + var_r31->unk18 = arg3; + var_r31->unk30 = arg2; + var_r31->unk44.r = arg5.r; + var_r31->unk44.g = arg5.g; + var_r31->unk44.b = arg5.b; + var_r31->unk44.a = arg5.a; + var_r31->unk34 = 0.0f; + var_r31->unk48 = 0; + var_r31->unk00 = 0; + var_r31->unk28 = 0.0f; + var_r31->unk2C = arg4; + temp_r28->unk04++; + return i; +} + +s32 fn_1_DD70(Vec arg0, Vec arg1, float arg2, float arg3, float arg4, float arg5, GXColor arg6) { + Vec sp60; + Vec sp54; + float temp_f31; + s32 sp20; + s32 sp1C; + + sp54.x = arg1.z; + sp54.z = arg1.x; + sp54.y = 0.0f; + PSVECNormalize(&sp54, &sp54); + temp_f31 = 0.5f * arg4; + sp60.x = arg0.x + sp54.x * temp_f31; + sp60.y = arg0.y + sp54.y * temp_f31; + sp60.z = arg0.z + sp54.z * temp_f31; + sp20 = fn_1_DC24(sp60, arg1, arg2, arg3, arg5, arg6); + sp60.x = arg0.x - sp54.x * temp_f31; + sp60.y = arg0.y - sp54.y * temp_f31; + sp60.z = arg0.z - sp54.z * temp_f31; + sp1C = fn_1_DC24(sp60, arg1, arg2, -arg3, arg5, arg6); + return (sp20 << 16) | sp1C; +} + +void fn_1_E1BC(void) { + omObjData* var_r31; + s32 var_r29; + s32 i; + + var_r31 = lbl_1_bss_A0 = omAddObjEx(lbl_1_bss_120, 0xBF, 16, 0, -1, fn_1_E290); + for (i = 0; i < var_r31->mdlcnt; i++) { + var_r29 = var_r31->model[i] = Hu3DModelCreateFile(DATA_MAKE_NUM(DATADIR_M423, 3)); + Hu3DModelAttrSet(var_r29, HU3D_ATTR_DISPOFF); + Hu3DModelCameraSet(var_r29, 4); + } + var_r31->stat |= 0x100; +} + +void fn_1_E290(omObjData* arg0) { + ModelData* var_r28; + s32 temp_r30; + s32 i; + + for (i = 0; i < arg0->mdlcnt; i++) { + temp_r30 = arg0->model[i]; + var_r28 = &Hu3DData[temp_r30]; + if (!(var_r28->attr & 1) && Hu3DMotionEndCheck(temp_r30)) { + Hu3DModelAttrSet(temp_r30, HU3D_ATTR_DISPOFF); + } + } +} + +void fn_1_E330(void) { +} + +s32 fn_1_E334(Vec arg0, Vec arg1, float arg2) { + omObjData* var_r31; + ModelData* var_r26; + s32 temp_r29; + s32 i; + + var_r31 = lbl_1_bss_A0; + for (i = 0; i < var_r31->mdlcnt; i++) { + var_r26 = &Hu3DData[var_r31->model[i]]; + if (var_r26->attr & 1) { + break; + } + } + if (i >= var_r31->mdlcnt) { + return -1; + } + temp_r29 = var_r31->model[i]; + Hu3DModelPosSet(temp_r29, arg0.x, arg0.y, arg0.z); + Hu3DModelRotSet(temp_r29, arg1.x, arg1.y, arg1.z); + Hu3DModelScaleSet(temp_r29, arg2, arg2, arg2); + Hu3DMotionTimeSet(temp_r29, 0.0f); + Hu3DMotionSpeedSet(temp_r29, 2.0f); + Hu3DModelAttrReset(temp_r29, HU3D_ATTR_DISPOFF); + return i; +} + +void fn_1_E460(void) { + omObjData* temp_r3; + + temp_r3 = lbl_1_bss_9C = omAddObjEx(lbl_1_bss_120, 0xBF, 1, 0, -1, fn_1_E4EC); + temp_r3->model[0] = fn_1_E678(); + Hu3DModelCameraSet(temp_r3->model[0], 4); + Hu3DModelLayerSet(temp_r3->model[0], 2); +} + +void fn_1_E4EC(omObjData* arg0) { + ModelData* var_r29; + StructM423_0B* var_r28; + StructM423_0A* var_r31; + s32 i; + + var_r29 = &Hu3DData[arg0->model[0]]; + var_r28 = var_r29->unk_120; + var_r31 = var_r28->unk00; + for (i = 0; i < 16; i++, var_r31++) { + if (var_r31->unk00 == 0) { + continue; + } + var_r31->unk00++; + if (var_r31->unk00 < 12.0f) { + var_r31->unk04 += 0.058333337f; + } else { + var_r31->unk04 += 0.025000002f; + var_r31->unk10 -= 0.050000004f; + } + if (var_r31->unk10 < 0.0f) { + var_r31->unk00 = 0; + } + } +} + +void fn_1_E60C(void) { + omObjData* temp_r31; + ModelData* var_r30; + StructM423_0B* var_r29; + + temp_r31 = lbl_1_bss_9C; + var_r30 = &Hu3DData[temp_r31->model[0]]; + var_r29 = var_r30->unk_120; + HuSprAnimKill(var_r29->unk200); + temp_r31->func = NULL; +} + +s32 fn_1_E678(void) { + float sp88[32][2]; + float sp8[32]; + float temp_f28; + float temp_f30; + float temp_f29; + float var_f31; + ModelData* temp_r27; + StructM423_0B* var_r30; + StructM423_09* var_r29; + StructM423_08* var_r28; + s32 var_r26; + s32 i; + + var_r26 = Hu3DHookFuncCreate(fn_1_EF44); + temp_r27 = &Hu3DData[var_r26]; + var_r30 = temp_r27->unk_120 = HuMemDirectMallocNum(HEAP_DATA, sizeof(*var_r30), temp_r27->unk_48); + memset(var_r30, 0, sizeof(*var_r30)); + var_r30->unk20C = HuMemDirectMallocNum(HEAP_DATA, 32 * sizeof(*var_r30->unk20C), temp_r27->unk_48); + memset(var_r30->unk20C, 0, 32 * sizeof(*var_r30->unk20C)); + var_r30->unk210 = HuMemDirectMallocNum(HEAP_DATA, 32 * sizeof(*var_r30->unk210), temp_r27->unk_48); + memset(var_r30->unk210, 0, 32 * sizeof(*var_r30->unk210)); + var_r30->unk214 = HuMemDirectMallocNum(HEAP_DATA, 5 * sizeof(*var_r30->unk214), temp_r27->unk_48); + memset(var_r30->unk214, 0, 5 * sizeof(*var_r30->unk214)); + var_r30->unk204 = GXGetTexBufferSize(640, 480, GX_TF_RGB5A3, GX_FALSE, 0); + var_r30->unk208 = HuMemDirectMallocNum(HEAP_DATA, var_r30->unk204, temp_r27->unk_48); + DCFlushRange(var_r30->unk208, var_r30->unk204); + var_r30->unk200 = HuSprAnimRead(HuDataReadNum(DATA_MAKE_NUM(DATADIR_M423, 23), MEMORY_DEFAULT_NUM)); + var_f31 = 0.0f; + for (i = 0; i < 32; i++) { + temp_f28 = 1.0f + 0.001f * frandmod(1000); + sp8[i] = temp_f28; + var_f31 += temp_f28; + sp88[i][1] = 80.0f * temp_f28; + sp88[i][0] = 10.0f + 0.02f * frandmod(1000); + } + var_f31 = 360.0f / var_f31; + for (i = 0; i < 32; i++) { + sp8[i] *= var_f31; + } + var_f31 = frandmod(90); + var_r28 = var_r30->unk20C; + var_r29 = var_r30->unk210; + for (i = 0; i < 32; var_r28++, var_r29++, i++) { + temp_f29 = -cosd(var_f31); + temp_f30 = sind(var_f31); + var_r28->unk24 = temp_f29 * sp88[i][0]; + var_r28->unk28 = temp_f30 * sp88[i][0]; + var_r28->unk0C = temp_f29 * (sp88[i][0] + sp88[i][1]); + var_r28->unk10 = temp_f30 * (sp88[i][0] + sp88[i][1]); + var_r28->unk00 = temp_f29 * (sp88[i][0] + 0.85f * sp88[i][1]); + var_r28->unk04 = temp_f30 * (sp88[i][0] + 0.85f * sp88[i][1]); + var_r29->unk00 = -0.3f * -temp_f29; + var_r29->unk04 = -0.3f * temp_f30; + temp_f29 = -cosd(var_f31 - 0.4f * sp8[i]); + temp_f30 = sind(var_f31 - 0.4f * sp8[i]); + var_r28->unk30 = temp_f29 * (sp88[i][0] + 0.7f * sp88[i][1]); + var_r28->unk34 = temp_f30 * (sp88[i][0] + 0.7f * sp88[i][1]); + temp_f29 = -cosd(var_f31 + 0.4f * sp8[i]); + temp_f30 = sind(var_f31 + 0.4f * sp8[i]); + var_r28->unk18 = temp_f29 * (sp88[i][0] + 0.7f * sp88[i][1]); + var_r28->unk1C = temp_f30 * (sp88[i][0] + 0.7f * sp88[i][1]); + var_r29->unk08 = var_r29->unk0C = var_r29->unk10 = var_r29->unk14 = 0.0f; + var_r29->unk18 = var_r29->unk1C = var_r29->unk20 = var_r29->unk24 = 0.0f; + var_f31 += sp8[i]; + } + for (i = 0; i < 5; i++) { + var_r30->unk214[i].r = var_r30->unk214[i].g = var_r30->unk214[i].b = 0xFF; + var_r30->unk214[i].a = 0xFF; + } + var_r30->unk218 = 32 * 54; + var_r30->unk220 = HuMemDirectMallocNum(HEAP_SYSTEM, var_r30->unk218, MEMORY_DEFAULT_NUM); + GXBeginDisplayList(var_r30->unk220, var_r30->unk218); + for (i = 0; i < 32; i++) { + GXBegin(GX_TRIANGLEFAN, GX_VTXFMT0, 6); + + GXPosition1x16(i * 5); + GXColor1x16(0); + GXTexCoord1x16(i * 5); + + GXPosition1x16(i * 5 + 1); + GXColor1x16(1); + GXTexCoord1x16(i * 5 + 1); + + GXPosition1x16(i * 5 + 2); + GXColor1x16(2); + GXTexCoord1x16(i * 5 + 2); + + GXPosition1x16(i * 5 + 3); + GXColor1x16(3); + GXTexCoord1x16(i * 5 + 3); + + GXPosition1x16(i * 5 + 4); + GXColor1x16(4); + GXTexCoord1x16(i * 5 + 4); + + GXPosition1x16(i * 5 + 1); + GXColor1x16(1); + GXTexCoord1x16(i * 5 + 1); + + GXEnd(); + } + var_r30->unk21C = GXEndDisplayList(); + DCFlushRangeNoSync(var_r30->unk20C, 32 * sizeof(*var_r30->unk20C)); + DCFlushRangeNoSync(var_r30->unk210, 32 * sizeof(*var_r30->unk210)); + DCFlushRangeNoSync(var_r30->unk214, 5 * sizeof(*var_r30->unk214)); + DCFlushRangeNoSync(var_r30->unk220, var_r30->unk218); + DCStoreRangeNoSync(var_r30, sizeof(*var_r30)); + PPCSync(); + return var_r26; +} + +GXColor lbl_1_data_7FC[] = { + { 0x66, 0x00, 0x00, 0xFF }, + { 0x00, 0x00, 0x66, 0xFF }, + { 0x66, 0x00, 0x5B, 0xFF }, + { 0x00, 0x66, 0x00, 0xFF }, + { 0x42, 0x00, 0x4C, 0xFF }, + { 0x47, 0x28, 0x00, 0xFF }, + { 0x66, 0x66, 0x00, 0xFF }, + { 0x00, 0x00, 0x00, 0xFF } +}; + +void fn_1_EF44(ModelData* arg0, Mtx arg1) { + Mtx sp124; + Mtx spF4; + Mtx spC4; + Mtx sp94; + Mtx sp64; + Mtx sp34; + GXTexObj sp14; + GXColor sp10 = { 0xCC, 0xCC, 0xCC, 0x7F }; + StructM423_0B* temp_r30; + StructM423_0A* var_r31; + s32 i; + + temp_r30 = arg0->unk_120; + GXSetTexCopySrc(0, 0, 640, 480); + GXSetTexCopyDst(640, 480, GX_TF_RGB5A3, GX_FALSE); + GXCopyTex(temp_r30->unk208, GX_FALSE); + GXPixModeSync(); + PSMTXTrans(spF4, -400.0f, 400.0f, -700.0f); + PSMTXConcat(Hu3DCameraMtx, spF4, sp64); + GXLoadPosMtxImm(sp64, GX_PNMTX0); + GXSetNumChans(1); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE); + GXInitTexObj(&sp14, temp_r30->unk208, 640, 480, GX_TF_RGB5A3, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObjLOD(&sp14, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); + GXLoadTexObj(&sp14, GX_TEXMAP0); + HuSprTexLoad(temp_r30->unk200, 0, 1, GX_REPEAT, GX_REPEAT, GX_LINEAR); + GXSetNumTexGens(2); + C_MTXLightPerspective(sp94, 41.5f, 1.2f, 0.5555555f, -0.5f, 0.5555555f, 0.5f); + PSMTXConcat(sp94, Hu3DCameraMtx, sp94); + PSMTXInverse(Hu3DCameraMtx, sp34); + PSMTXConcat(sp34, sp64, sp124); + PSMTXConcat(sp94, sp124, spF4); + GXLoadTexMtxImm(spF4, GX_TEXMTX0, GX_MTX3x4); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEXCOORD0, GX_TEXMTX1, GX_FALSE, GX_PTIDENTITY); + GXSetNumIndStages(1); + GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD1, GX_TEXMAP1); + GXSetTevIndWarp(GX_TEVSTAGE0, GX_INDTEXSTAGE0, GX_TRUE, GX_FALSE, GX_ITM_0); + GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1); + PSMTXScale(spF4, -0.5f, -0.5f, 0.5f); + GXSetIndTexMtx(GX_ITM_0, (float(*)[3]) spF4, -1); + GXSetNumTevStages(1); + GXSetTevColor(GX_TEVREG1, sp10); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C1, GX_CC_C0); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_RASA, GX_CA_A0, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_FALSE, GX_TEVPREV); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET); + GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXSetArray(GX_VA_POS, temp_r30->unk20C, 12); + GXSetArray(GX_VA_CLR0, temp_r30->unk214, 4); + GXSetArray(GX_VA_TEX0, temp_r30->unk210, 8); + var_r31 = temp_r30->unk00; + for (i = 0; i < 16; i++, var_r31++) { + if (var_r31->unk00 == 0) { + continue; + } + lbl_1_data_7FC[var_r31->unk02].a = 255.0f * var_r31->unk10; + GXSetTevColor(GX_TEVREG0, lbl_1_data_7FC[var_r31->unk02]); + PSMTXTrans(spF4, var_r31->unk14.x, var_r31->unk14.y, var_r31->unk14.z); + PSMTXRotRad(sp124, 'Z', MTXDegToRad(var_r31->unk0C)); + PSMTXConcat(spF4, sp124, spF4); + PSMTXScale(spC4, var_r31->unk04 * var_r31->unk08, var_r31->unk04 * var_r31->unk08, var_r31->unk04 * var_r31->unk08); + PSMTXConcat(spF4, spC4, spF4); + PSMTXConcat(Hu3DCameraMtx, spF4, sp64); + GXLoadPosMtxImm(sp64, GX_PNMTX0); + PSMTXConcat(sp34, sp64, sp124); + PSMTXConcat(sp94, sp124, spF4); + GXLoadTexMtxImm(spF4, GX_TEXMTX0, GX_MTX3x4); + PSMTXRotRad(sp124, 'Z', MTXDegToRad(-var_r31->unk0C)); + GXLoadTexMtxImm(sp124, GX_TEXMTX1, GX_MTX2x4); + GXCallDisplayList(temp_r30->unk220, temp_r30->unk21C); + } + GXSetNumIndStages(0); + GXSetTevDirect(GX_TEVSTAGE0); +} + +s32 fn_1_F574(Vec arg0, float arg1, s32 arg2) { + omObjData* var_r29; + ModelData* var_r28; + StructM423_0B* var_r26; + StructM423_0A* var_r31; + s32 var_r27; + s32 i; + + var_r29 = lbl_1_bss_9C; + var_r28 = &Hu3DData[var_r29->model[0]]; + var_r26 = var_r28->unk_120; + var_r31 = var_r26->unk00; + for (i = 0; i < 16; i++, var_r31++) { + if (var_r31->unk00 == 0) { + break; + } + } + if (i < 16) { + if (arg2 < 0) { + arg2 = 0; + } + var_r31->unk00 = 1; + var_r31->unk02 = arg2; + var_r31->unk10 = 1.0f; + var_r31->unk08 = arg1; + var_r31->unk04 = 0.25f; + var_r31->unk0C = frandmod(360); + var_r31->unk14 = arg0; + } +} + +void fn_1_F690(void) { + lbl_1_bss_98 = omAddObjEx(lbl_1_bss_120, 0xFE, 0, 0, -1, fn_1_F6E0); +} + +s32 lbl_1_data_81C[] = { + DATA_MAKE_NUM(DATADIR_MGCONST, 12), + DATA_MAKE_NUM(DATADIR_MGCONST, 13), + DATA_MAKE_NUM(DATADIR_MGCONST, 14), + DATA_MAKE_NUM(DATADIR_MGCONST, 15), + DATA_MAKE_NUM(DATADIR_MGCONST, 16), + DATA_MAKE_NUM(DATADIR_MGCONST, 17), + DATA_MAKE_NUM(DATADIR_MGCONST, 18), + DATA_MAKE_NUM(DATADIR_MGCONST, 19) +}; + +s16 lbl_1_data_83C[] = { 0x7F, 0x7F, 0x7F, 0x100 }; + +s16 lbl_1_data_844[][2] = { + { -75, 10 }, { -61, -14 }, { -47, 10 }, { 0, 0 }, + { -12, -8 }, { -12, -8 }, { 6, -8 }, { 6, -8 }, + { 24, -8 }, { 24, -8 }, { 42, -8 }, { 42, -8 }, + { 60, -8 }, { 60, -8 }, { -12, 10 }, { -12, 10 }, + { 6, 10 }, { 6, 10 }, { 24, 10 }, { 24, 10 }, + { 42, 10 }, { 42, 10 }, { 60, 10 }, { 60, 10 } +}; + +void fn_1_F6E0(omObjData* arg0) { + StructM423_0C* var_r31; + s32 sp8; + s32 var_r29; + s32 i; + + if ((sp8 = lbl_1_bss_EC[3]) != -1) { + var_r31 = arg0->data = HuMemDirectMallocNum(HEAP_SYSTEM, sizeof(*var_r31), MEMORY_DEFAULT_NUM); + memset(var_r31, 0, sizeof(*var_r31)); + var_r31->unk00 = 480; + var_r31->unk04 = 70; + var_r31->unk08 = 0; + var_r31->unk0C = 0; + for (i = 0; i < 24; i++) { + switch (i) { + case 0: + case 1: + case 2: + var_r29 = espEntry(lbl_1_data_81C[lbl_1_bss_EC[i]], lbl_1_data_83C[i], 0); + var_r31->unk10[i] = var_r29; + var_r31->unk70[i][0] = lbl_1_data_844[i][0]; + var_r31->unk70[i][1] = lbl_1_data_844[i][1]; + break; + case 3: + var_r29 = espEntry(DATA_MAKE_NUM(DATADIR_MGCONST, 38), lbl_1_data_83C[i], 0); + var_r31->unk10[i] = var_r29; + var_r31->unk70[i][0] = lbl_1_data_844[i][0]; + var_r31->unk70[i][1] = lbl_1_data_844[i][1]; + break; + default: + if (!(i & 1)) { + var_r29 = espEntry(DATA_MAKE_NUM(DATADIR_M423, 24), 0x40, 0); + var_r31->unk10[i] = var_r29; + } else { + var_r29 = espEntry(DATA_MAKE_NUM(DATADIR_M423, 25), 0x20, 0); + var_r31->unk10[i] = var_r29; + } + var_r31->unk70[i][0] = lbl_1_data_844[i][0]; + var_r31->unk70[i][1] = lbl_1_data_844[i][1]; + break; + } + espDispOn(var_r29); + espDrawNoSet(var_r29, 0); + espAttrSet(var_r29, 1); + espPosSet(var_r29, var_r31->unk00 + var_r31->unk70[i][0], var_r31->unk04 + var_r31->unk70[i][1]); + espBankSet(var_r29, 0); + } + for (i = 0; i < 10; i++) { + var_r31->unk190[i][0] = 0; + var_r31->unk190[i][1] = 0; + } + fn_1_10028(0); + arg0->func = fn_1_FA40; + } +} + +void fn_1_FA40(omObjData* arg0) { + float var_f31; + float var_f28; + float temp_f30; + float temp_f29; + StructM423_0C* temp_r31; + s32 temp_r28; + s32 temp_r29; + s32 i; + + temp_r31 = arg0->data; + if (lbl_1_bss_104 != temp_r31->unk08) { + temp_r31->unk08 = lbl_1_bss_104; + temp_r31->unk0C = 20; + } + if (temp_r31->unk0C != 0) { + var_f31 = 1.0 + 0.8f * sind(180.0f * (temp_r31->unk0C / 20.0f)); + temp_r31->unk0C--; + } else { + var_f31 = 1.0f; + } + var_f31 = 1.0f; + temp_r28 = 10 - lbl_1_bss_104; + for (i = 0; i < 4; i++) { + temp_f30 = temp_r31->unk00 + temp_r31->unk70[i][0]; + temp_f29 = temp_r31->unk04 + temp_r31->unk70[i][1]; + espPosSet(temp_r31->unk10[i], temp_f30, temp_f29); + espScaleSet(temp_r31->unk10[i], 1.0f, 1.0f); + } + for (i = 4; i < 24; i++) { + temp_f30 = temp_r31->unk00 + temp_r31->unk70[i][0]; + temp_f29 = temp_r31->unk04 + temp_r31->unk70[i][1]; + if (!(i & 1)) { + espPosSet(temp_r31->unk10[i], temp_f30, temp_f29); + espScaleSet(temp_r31->unk10[i], 1.0f, 1.0f); + } else { + temp_r29 = (i - 4) / 2; + if (temp_r28 > temp_r29) { + temp_r31->unk190[temp_r29][0] = 1; + } else { + temp_r31->unk190[temp_r29][0] = 0; + } + if (temp_r31->unk190[temp_r29][0] != 0) { + if (temp_r31->unk190[temp_r29][1] < 15) { + temp_r31->unk190[temp_r29][1]++; + var_f31 = 3.0f - 2.0f * (temp_r31->unk190[temp_r29][1] / 15.0f); + var_f28 = temp_r31->unk190[temp_r29][1] / 15.0f; + } else { + var_f31 = 1.0f; + var_f28 = 1.0f; + } + espDispOn(temp_r31->unk10[i]); + espPosSet(temp_r31->unk10[i], temp_f30, temp_f29); + espTPLvlSet(temp_r31->unk10[i], var_f28); + espScaleSet(temp_r31->unk10[i], var_f31, var_f31); + } else { + espDispOff(temp_r31->unk10[i]); + } + } + } +} + +void fn_1_FF10(omObjData* arg0) { + StructM423_0C* temp_r29; + s32 i; + + if (arg0 && arg0->data) { + temp_r29 = arg0->data; + for (i = 0; i < 24; i++) { + espKill(temp_r29->unk10[i]); + } + arg0->data = NULL; + arg0->func = NULL; + } +} + +void fn_1_FF98(void) { + fn_1_FF10(lbl_1_bss_98); +} + +void fn_1_10028(s32 arg0) { + StructM423_0C* temp_r30; + s32 i; + + temp_r30 = lbl_1_bss_98->data; + for (i = 0; i < 24; i++) { + if (arg0 != 0) { + espDispOn(temp_r30->unk10[i]); + } else { + espDispOff(temp_r30->unk10[i]); + } + if (i >= 4 && (i & 1)) { + espDispOff(temp_r30->unk10[i]); + } + } +} + +void fn_1_100DC(void) { + omObjData* temp_r3; + s32 i; + + Hu3DCameraCreate(1); + Hu3DCameraPerspectiveSet(1, 45.0f, 50.0f, 50000.0f, 1.2f); + Hu3DCameraViewportSet(1, 0.0f, 0.0f, 320.0f, 240.0f, 0.0f, 1.0f); + Hu3DCameraScissorSet(1, 0, 0, 320, 240); + Hu3DCameraCreate(2); + Hu3DCameraPerspectiveSet(2, 45.0f, 50.0f, 50000.0f, 1.2f); + Hu3DCameraViewportSet(2, 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1.0f); + Hu3DCameraScissorSet(2, 0, 0, 640, 480); + Hu3DCameraCreate(4); + Hu3DCameraPerspectiveSet(4, 45.0f, 100.0f, 50000.0f, 1.2f); + Hu3DCameraViewportSet(4, 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1.0f); + Hu3DCameraScissorSet(4, 0, 0, 640, 480); + temp_r3 = lbl_1_bss_8C = omAddObjEx(lbl_1_bss_120, 0x7FDA, 0, 0, -1, omOutViewMulti); + temp_r3->work[0] = 3; + for (i = 0; i < temp_r3->work[0]; i++) { + CRotM[i].x = lbl_1_data_0[0].unk00.x; + CRotM[i].y = lbl_1_data_0[0].unk00.y; + CRotM[i].z = lbl_1_data_0[0].unk00.z; + CenterM[i].x = lbl_1_data_0[0].unk0C.x; + CenterM[i].y = lbl_1_data_0[0].unk0C.y; + CenterM[i].z = lbl_1_data_0[0].unk0C.z; + CZoomM[i] = lbl_1_data_0[0].unk18; + } + lbl_1_bss_84 = 0; + lbl_1_bss_88 = -1; + omAddObjEx(lbl_1_bss_120, 0xFF, 0, 0, -1, fn_1_10480); +} + +void fn_1_10480(omObjData* arg0) { + CRotM[1].x = CRotM[0].x; + CRotM[1].y = CRotM[0].y; + CRotM[1].z = CRotM[0].z; + CenterM[1].x = CenterM[0].x; + CenterM[1].y = CenterM[0].y; + CenterM[1].z = CenterM[0].z; + CZoomM[1] = CZoomM[0]; +} + +void fn_1_1052C(void) { +} + +s32 fn_1_10530(void) { + return lbl_1_bss_84; +} + +void fn_1_10540(s32 arg0, s32 arg1, s32 arg2, f32 arg3) { + StructData0* temp_r31; + StructData0* temp_r30; + + temp_r31 = &lbl_1_data_0[arg1]; + temp_r30 = &lbl_1_data_0[arg2]; + CRotM[arg0].x = fn_1_12544(arg3, temp_r31->unk00.x, temp_r30->unk00.x); + CRotM[arg0].y = fn_1_12544(arg3, temp_r31->unk00.y, temp_r30->unk00.y); + CRotM[arg0].z = fn_1_12544(arg3, temp_r31->unk00.z, temp_r30->unk00.z); + CenterM[arg0].x = temp_r31->unk0C.x + arg3 * (temp_r30->unk0C.x - temp_r31->unk0C.x); + CenterM[arg0].y = temp_r31->unk0C.y + arg3 * (temp_r30->unk0C.y - temp_r31->unk0C.y); + CenterM[arg0].z = temp_r31->unk0C.z + arg3 * (temp_r30->unk0C.z - temp_r31->unk0C.z); + CZoomM[arg0] = temp_r31->unk18 + arg3 * (temp_r30->unk18 - temp_r31->unk18); +} + +float lbl_1_data_8A4[] = { + 95.0f, 95.0f, 135.0f, 95.0f, 95.0f, 125.0f, 135.0f, 125.0f +}; + +void fn_1_106D8(s32 arg0) { + float var_f31; + StructBssBCData* var_r30; + s32 var_r29; + + if (lbl_1_bss_90 != arg0) { + CRotM->x = lbl_1_data_38[arg0].unk00.x; + CRotM->y = lbl_1_data_38[arg0].unk00.y; + CRotM->z = lbl_1_data_38[arg0].unk00.z; + CenterM->x = lbl_1_data_38[arg0].unk0C.x; + CenterM->y = lbl_1_data_38[arg0].unk0C.y; + CenterM->z = lbl_1_data_38[arg0].unk0C.z; + CZoomM[0] = lbl_1_data_38[arg0].unk18; + lbl_1_bss_80 = 0; + if (arg0 != 0) { + lbl_1_bss_7C = frand(); + } else { + lbl_1_bss_7C = 0; + } + lbl_1_bss_90 = arg0; + } + var_r29 = lbl_1_bss_90; + switch (var_r29) { + case 0: + case 1: + case 2: + lbl_1_bss_80++; + if (lbl_1_bss_7C & 1) { + var_f31 = cosd((float) lbl_1_bss_80); + } else { + var_f31 = -cosd((float) lbl_1_bss_80); + } + CRotM->y = 23.0f * var_f31 + lbl_1_data_38[arg0].unk00.y; + break; + case 3: + case 4: + case 5: + lbl_1_bss_80++; + if (lbl_1_bss_7C & 1) { + CRotM->y = lbl_1_data_38[arg0].unk00.y - 45.0f + 0.5f * lbl_1_bss_80; + } else { + CRotM->y = lbl_1_data_38[arg0].unk00.y + 45.0f - 0.5f * lbl_1_bss_80; + } + break; + case 6: + case 7: + case 8: + if (lbl_1_bss_AC[var_r29 - 6] != NULL) { + var_r30 = lbl_1_bss_AC[var_r29 - 6]->data; + CenterM->y = lbl_1_data_8A4[var_r30->unk02]; + } + break; + case 9: + if (lbl_1_bss_B8 != NULL) { + var_r30 = lbl_1_bss_B8->data; + CenterM->x = lbl_1_bss_B8->trans.x; + CenterM->z = lbl_1_bss_B8->trans.z; + CenterM->y = lbl_1_data_8A4[var_r30->unk02]; + } + break; + } +} + +void fn_1_10BC8(void) { + Mtx44 sp64; + Mtx sp34; + Vec sp28; + Vec sp1C; + Vec sp10; + GXColor spC; + CameraData* var_r31; + + var_r31 = &Hu3DCamera[0]; + if (var_r31->fov <= 0.0f) { + return; + } + C_MTXPerspective(sp64, var_r31->fov, var_r31->aspect, var_r31->near, var_r31->far); + GXSetProjection(sp64, GX_PERSPECTIVE); + GXSetViewport(0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1.0f); + GXSetScissor(0, 0, 640, 480); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + spC.r = spC.g = spC.b = 0; + spC.a = 0xFF; + GXSetTevColor(GX_TEVREG0, spC); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetNumTexGens(0); + GXSetNumTevStages(1); + GXSetCullMode(GX_CULL_NONE); + GXSetZMode(GX_TRUE, GX_ALWAYS, GX_TRUE); + sp28.x = sp28.y = sp28.z = 0.0f; + sp1C.x = sp1C.y = 0.0f; + sp1C.z = -100.0f; + sp10.x = sp10.z = 0.0f; + sp10.y = 1.0f; + C_MTXLookAt(sp34, &sp28, &sp10, &sp1C); + GXLoadPosMtxImm(sp34, GX_PNMTX0); + sp28.x = 10000.0 * -sin(var_r31->fov / 2.0f) * 1.2f; + sp28.y = 10000.0 * -sin(var_r31->fov / 2.0f) * 0.8333333f; + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + GXPosition3f32(-sp28.x, -sp28.y, -10000.0f); + GXPosition3f32(sp28.x, -sp28.y, -10000.0f); + GXPosition3f32(sp28.x, sp28.y, -10000.0f); + GXPosition3f32(-sp28.x, sp28.y, -10000.0f); + GXEnd(); +} + +void fn_1_11008(StructBssD0Data* arg0, void* arg1, s16 arg2, GXTexWrapMode arg3, s32 arg4, s32 arg5) { + GXTexObj sp18; + StructBssD0Data* var_r31; + + var_r31 = arg0; + GXInitTexObj(&sp18, arg1, var_r31->unk00, var_r31->unk04, GX_TF_RGB5A3, arg3, arg3, GX_FALSE); + if (arg5 != 0) { + GXInitTexObjLOD(&sp18, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); + } else { + GXInitTexObjLOD(&sp18, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); + } + GXLoadTexObj(&sp18, arg2); +} + +s16 fn_1_11114(AnimData* arg0, s16 arg1) { + s16 var_r23; + s16 i; + ModelData* temp_r27; + StructM423_05* var_r31; + StructM423_04* var_r29; + Vec* var_r25; + float (*var_r28)[2]; + void* var_r24; + void* var_r22; + + var_r23 = Hu3DHookFuncCreate(fn_1_11900); + temp_r27 = &Hu3DData[var_r23]; + temp_r27->unk_120 = var_r31 = HuMemDirectMallocNum(HEAP_DATA, sizeof(*var_r31), temp_r27->unk_48); + var_r31->unk38 = arg0; + var_r31->unk26 = arg1; + var_r31->unk20 = 0; + var_r31->unk22 = 0; + var_r31->unk4C = NULL; + var_r31->unk50 = NULL; + var_r31->unk28 = 0; + var_r31->unk21 = 0; + var_r31->unk23 = 0; + var_r31->unk30 = 0; + var_r31->unk00 = var_r31->unk02 = 0; + var_r31->unk3C = var_r29 = HuMemDirectMallocNum(HEAP_DATA, arg1 * sizeof(*var_r29), temp_r27->unk_48); + memset(var_r29, 0, arg1 * sizeof(*var_r29)); + for (i = 0; i < arg1; i++, var_r29++) { + var_r29->unk30 = 0.0f; + var_r29->unk34 = 0.0f; + var_r29->unk28 = 0.0f; + var_r29->unk2C = 1.0f; + var_r29->unk38.x = (frand7() - 64) * 20; + var_r29->unk38.y = (frand7() - 64) * 30; + var_r29->unk38.z = (frand7() - 64) * 20; + var_r29->unk44.r = var_r29->unk44.g = var_r29->unk44.b = var_r29->unk44.a = 0xFF; + var_r29->unk48 = 0; + } + var_r31->unk40 = var_r25 = HuMemDirectMallocNum(HEAP_DATA, arg1 * sizeof(*var_r25) * 4, temp_r27->unk_48); + for (i = 0; i < arg1 * 4; i++, var_r25++) { + var_r25->x = var_r25->y = var_r25->z = 0.0f; + } + var_r31->unk44 = var_r28 = HuMemDirectMallocNum(HEAP_DATA, arg1 * sizeof(*var_r28) * 4, temp_r27->unk_48); + for (i = 0; i < arg1; i++) { + (*var_r28)[0] = 0.0f; + (*var_r28)[1] = 0.0f; + var_r28++; + (*var_r28)[0] = 1.0f; + (*var_r28)[1] = 0.0f; + var_r28++; + (*var_r28)[0] = 1.0f; + (*var_r28)[1] = 1.0f; + var_r28++; + (*var_r28)[0] = 0.0f; + (*var_r28)[1] = 1.0f; + var_r28++; + } + var_r22 = var_r24 = HuMemDirectMallocNum(HEAP_DATA, 0x10000, temp_r27->unk_48); + DCFlushRange(var_r24, 0x10000); + GXBeginDisplayList(var_r22, 0x10000); + GXBegin(GX_QUADS, GX_VTXFMT0, arg1 * 4); + for (i = 0; i < arg1; i++) { + GXPosition1x16(i * 4); + GXColor1x16(i); + GXTexCoord1x16(i * 4); + + GXPosition1x16(i * 4 + 1); + GXColor1x16(i); + GXTexCoord1x16(i * 4 + 1); + + GXPosition1x16(i * 4 + 2); + GXColor1x16(i); + GXTexCoord1x16(i * 4 + 2); + + GXPosition1x16(i * 4 + 3); + GXColor1x16(i); + GXTexCoord1x16(i * 4 + 3); + } + GXEnd(); + var_r31->unk34 = GXEndDisplayList(); + var_r31->unk48 = HuMemDirectMallocNum(HEAP_DATA, var_r31->unk34, temp_r27->unk_48); + memcpy(var_r31->unk48, var_r24, var_r31->unk34); + DCFlushRange(var_r31->unk48, var_r31->unk34); + HuMemDirectFree(var_r24); + return var_r23; +} + +s16 fn_1_115C4(s16 arg0) { + s32 temp_r24; + s16 var_r22; + s16 i; + ModelData* temp_r23; + ModelData* temp_r27; + StructM423_05* temp_r26; + StructM423_05* var_r31; + StructM423_04* var_r30; + Vec* var_r25; + float (*var_r29)[2]; + + temp_r23 = &Hu3DData[arg0]; + temp_r26 = temp_r23->unk_120; + var_r22 = Hu3DHookFuncCreate(temp_r23->hook); + temp_r27 = &Hu3DData[var_r22]; + temp_r27->unk_120 = var_r31 = HuMemDirectMallocNum(HEAP_DATA, sizeof(*var_r31), temp_r27->unk_48); + var_r31->unk38 = temp_r26->unk38; + var_r31->unk26 = temp_r26->unk26; + temp_r24 = var_r31->unk26; + var_r31->unk20 = 0; + var_r31->unk22 = temp_r26->unk22; + var_r31->unk4C = NULL; + var_r31->unk50 = NULL; + var_r31->unk28 = 0; + var_r31->unk21 = 0; + var_r31->unk30 = 0; + var_r31->unk00 = var_r31->unk02 = 0; + var_r31->unk3C = var_r30 = HuMemDirectMallocNum(HEAP_DATA, temp_r24 * sizeof(*var_r30), temp_r27->unk_48); + for (i = 0; i < temp_r24; i++, var_r30++) { + var_r30->unk30 = 0.0f; + var_r30->unk34 = 0.0f; + var_r30->unk28 = 0.0f; + var_r30->unk2C = 1.0f; + var_r30->unk38.x = (frand7() - 64) * 20; + var_r30->unk38.y = (frand7() - 64) * 30; + var_r30->unk38.z = (frand7() - 64) * 20; + var_r30->unk44.r = var_r30->unk44.g = var_r30->unk44.b = var_r30->unk44.a = 0xFF; + var_r30->unk48 = 0; + } + var_r31->unk40 = var_r25 = HuMemDirectMallocNum(HEAP_DATA, temp_r24 * sizeof(*var_r25) * 4, temp_r27->unk_48); + for (i = 0; i < (temp_r24 * 4); i++, var_r25++) { + var_r25->x = var_r25->y = var_r25->z = 0.0f; + } + var_r31->unk44 = var_r29 = HuMemDirectMallocNum(HEAP_DATA, temp_r24 * sizeof(*var_r29) * 4, temp_r27->unk_48); + for (i = 0; i < temp_r24; i++) { + (*var_r29)[0] = 0.0f; + (*var_r29)[1] = 0.0f; + var_r29++; + (*var_r29)[0] = 1.0f; + (*var_r29)[1] = 0.0f; + var_r29++; + (*var_r29)[0] = 1.0f; + (*var_r29)[1] = 1.0f; + var_r29++; + (*var_r29)[0] = 0.0f; + (*var_r29)[1] = 1.0f; + var_r29++; + } + var_r31->unk34 = temp_r26->unk34; + var_r31->unk48 = temp_r26->unk48; + return var_r22; +} + +Vec lbl_1_data_8C4[] = { + { -0.5f, 0.5f, 0.0f }, + { 0.5f, 0.5f, 0.0f }, + { 0.5f, -0.5f, 0.0f }, + { -0.5f, -0.5f, 0.0f } +}; + +float lbl_1_data_8F4[][2] = { + { 0.0f, 0.0f }, + { 0.25f, 0.0f }, + { 0.25f, 0.25f }, + { 0.0f, 0.25f } +}; + +void fn_1_11900(ModelData* arg0, Mtx arg1) { + Mtx sp128; + Mtx spF8; + Mtx spC8; + Vec sp98[4]; + Vec sp68[4]; + Vec sp38[4]; + ROMtx sp8; + StructM423_05* temp_r31; + StructM423_04* var_r29; + Vec* var_r30; + float (*var_r28)[2]; + Vec* temp_r27; + Vec* temp_r24; + s16 var_r21; + s16 var_r20; + s16 var_r19; + void (*var_r18)(ModelData*, struct struct_m423_05*, Mtx); + s16 i; + s16 j; + + temp_r31 = arg0->unk_120; + if (temp_r31->unk2C == GlobalCounter && shadowModelDrawF == 0) { + return; + } + if (temp_r31->unk50 && temp_r31->unk50 != arg0) { + fn_1_11900(temp_r31->unk50, arg1); + } + GXLoadPosMtxImm(arg1, GX_PNMTX0); + GXSetNumTevStages(1); + GXSetNumTexGens(1); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + if (shadowModelDrawF != 0) { + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ONE, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO); + GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE); + } else { + var_r21 = temp_r31->unk38->bmp->dataFmt & 0xF; + if (var_r21 == 7 || var_r21 == 8) { + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ONE, GX_CC_RASC, GX_CC_ZERO); + } else { + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO); + } + if (temp_r31->unk22 & 1) { + GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE); + } else if (arg0->attr & 2) { + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + } else { + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE); + } + } + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetNumChans(1); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE); + HuSprTexLoad(temp_r31->unk38, 0, 0, GX_REPEAT, GX_REPEAT, GX_LINEAR); + GXSetAlphaCompare(GX_GEQUAL, 1, GX_AOP_AND, GX_GEQUAL, 1); + GXSetZCompLoc(GX_FALSE); + switch (temp_r31->unk20) { + case 0: + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); + break; + case 1: + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_NOOP); + break; + case 2: + GXSetBlendMode(GX_BM_BLEND, GX_BL_ZERO, GX_BL_INVDSTCLR, GX_LO_NOOP); + break; + } + if (HmfInverseMtxF3X3(arg1, sp128) == 0) { + PSMTXIdentity(sp128); + } + PSMTXReorder(sp128, sp8); + if (temp_r31->unk4C) { + var_r18 = temp_r31->unk4C; + var_r18(arg0, temp_r31, arg1); + } + var_r29 = temp_r31->unk3C; + var_r30 = temp_r31->unk40; + var_r28 = temp_r31->unk44; + PSMTXROMultVecArray(sp8, lbl_1_data_8C4, sp38, 4); + for (i = 0; i < temp_r31->unk26; i++, var_r29++) { + if (!var_r29->unk30) { + var_r30->x = var_r30->y = var_r30->z = 0.0f; + var_r30++; + var_r30->x = var_r30->y = var_r30->z = 0.0f; + var_r30++; + var_r30->x = var_r30->y = var_r30->z = 0.0f; + var_r30++; + var_r30->x = var_r30->y = var_r30->z = 0.0f; + var_r30++; + } else if (!var_r29->unk34) { + temp_r27 = sp98; + temp_r24 = sp38; + PSVECScale(temp_r24++, temp_r27, var_r29->unk30); + PSVECAdd(temp_r27++, &var_r29->unk38, var_r30++); + PSVECScale(temp_r24++, temp_r27, var_r29->unk30); + PSVECAdd(temp_r27++, &var_r29->unk38, var_r30++); + PSVECScale(temp_r24++, temp_r27, var_r29->unk30); + PSVECAdd(temp_r27++, &var_r29->unk38, var_r30++); + PSVECScale(temp_r24++, temp_r27, var_r29->unk30); + PSVECAdd(temp_r27++, &var_r29->unk38, var_r30++); + } else { + PSVECScale(&lbl_1_data_8C4[0], &sp98[0], var_r29->unk30); + PSVECScale(&lbl_1_data_8C4[1], &sp98[1], var_r29->unk30); + PSVECScale(&lbl_1_data_8C4[2], &sp98[2], var_r29->unk30); + PSVECScale(&lbl_1_data_8C4[3], &sp98[3], var_r29->unk30); + PSMTXRotRad(spC8, 'Z', var_r29->unk34); + PSMTXConcat(sp128, spC8, spF8); + PSMTXMultVecArray(spF8, sp98, sp68, 4); + PSVECAdd(&sp68[0], &var_r29->unk38, var_r30++); + PSVECAdd(&sp68[1], &var_r29->unk38, var_r30++); + PSVECAdd(&sp68[2], &var_r29->unk38, var_r30++); + PSVECAdd(&sp68[3], &var_r29->unk38, var_r30++); + } + } + var_r29 = temp_r31->unk3C; + var_r28 = temp_r31->unk44; + if (!(temp_r31->unk22 & 2)) { + for (i = 0; i < temp_r31->unk26; i++, var_r29++) { + var_r20 = var_r29->unk48 & 3; + var_r19 = (var_r29->unk48 >> 2) & 3; + for (j = 0; j < 4; j++, var_r28++) { + (*var_r28)[0] = 0.25f * var_r20 + lbl_1_data_8F4[j][0]; + (*var_r28)[1] = 0.25f * var_r19 + lbl_1_data_8F4[j][1]; + } + } + } else { + for (i = 0; i < temp_r31->unk26; i++, var_r29++) { + for (j = 0; j < 4; j++, var_r28++) { + (*var_r28)[0] = 4.0f * lbl_1_data_8F4[j][0]; + (*var_r28)[1] = 4.0f * lbl_1_data_8F4[j][1]; + } + } + } + DCFlushRangeNoSync(temp_r31->unk40, temp_r31->unk26 * sizeof(*temp_r31->unk40) * 4); + DCFlushRangeNoSync(temp_r31->unk44, temp_r31->unk26 * sizeof(*temp_r31->unk44) * 4); + DCFlushRangeNoSync(temp_r31->unk3C, temp_r31->unk26 * sizeof(*temp_r31->unk3C)); + PPCSync(); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetArray(GX_VA_POS, temp_r31->unk40, 12); + GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetArray(GX_VA_CLR0, &temp_r31->unk3C->unk44, 76); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXSetArray(GX_VA_TEX0, temp_r31->unk44, 8); + GXCallDisplayList(temp_r31->unk48, temp_r31->unk34); + if (shadowModelDrawF == 0) { + if (!(temp_r31->unk21 & 2)) { + temp_r31->unk28++; + } + if (temp_r31->unk30 != 0 && temp_r31->unk30 <= temp_r31->unk28) { + if (temp_r31->unk21 & 1) { + temp_r31->unk28 = 0; + } + temp_r31->unk28 = temp_r31->unk30; + } + temp_r31->unk2C = GlobalCounter; + } +} + +float fn_1_121DC(float arg0, float arg1) { + float var_f31; + + if (arg0 >= 360.0f) { + arg0 -= 360.0f; + } else if (arg0 < 0.0f) { + arg0 += 360.0f; + } + if (arg1 >= 360.0f) { + arg1 -= 360.0f; + } else if (arg1 < 0.0f) { + arg1 += 360.0f; + } + var_f31 = arg0 - arg1; + if (var_f31 <= -180.0f) { + var_f31 += 360.0f; + } else if (var_f31 >= 180.0f) { + var_f31 -= 360.0f; + } + return var_f31; +} + +float fn_1_122F4(float arg0, float arg1, float arg2) { + float var_f30; + float var_f31; + + if (arg0 >= 360.0) { + arg0 -= 360.0; + } else if (arg0 < 0.0) { + arg0 += 360.0; + } + if (arg1 >= 360.0) { + arg1 -= 360.0; + } else if (arg1 < 0.0) { + arg1 += 360.0; + } + var_f30 = arg0 - arg1 + 360.0; + if (fabs(var_f30) >= 360.0) { + var_f30 = fmod(var_f30, 360.0); + } + if (var_f30 < 180.0) { + if (var_f30 <= arg2) { + var_f31 = var_f30; + } else { + var_f31 = arg2; + } + } else { + if (360.0 - var_f30 <= arg2) { + var_f31 = -(360.0 - var_f30); + } else { + var_f31 = -arg2; + } + } + var_f31 += arg1; + if (var_f31 >= 360.0) { + var_f31 -= 360.0; + } else if (var_f31 < 0.0) { + var_f31 += 360.0; + } + return var_f31; +} + +float fn_1_12544(float arg0, float arg1, float arg2) { + float var_f28; + + var_f28 = fn_1_121DC(arg2, arg1); + return fn_1_122F4(arg2, arg1, fabs(var_f28 * arg0)); +} + +void fn_1_1293C(Mtx arg0, Vec* arg1) { + Vec sp8; + + sp8.x = arg0[0][0] * arg1->x + arg0[0][1] * arg1->y + arg0[0][2] * arg1->z; + sp8.y = arg0[1][0] * arg1->x + arg0[1][1] * arg1->y + arg0[1][2] * arg1->z; + sp8.z = arg0[2][0] * arg1->x + arg0[2][1] * arg1->y + arg0[2][2] * arg1->z; + *arg1 = sp8; +} + +void fn_1_129F0(Vec* arg0, Vec* arg1, Vec* arg2, float* arg3) { + Vec sp18; + Vec spC; + float var_f30; + float var_f29; + + sp18.x = arg1->x - arg0->x; + sp18.y = arg1->y - arg0->y; + sp18.z = arg1->z - arg0->z; + spC.x = arg2->x - arg1->x; + spC.y = arg2->y - arg1->y; + spC.z = arg2->z - arg1->z; + arg3[0] = sp18.y * spC.z - sp18.z * spC.y; + arg3[1] = sp18.z * spC.x - sp18.x * spC.z; + arg3[2] = sp18.x * spC.y - sp18.y * spC.x; + var_f29 = arg3[0] * arg3[0] + arg3[1] * arg3[1] + arg3[2] * arg3[2]; + var_f30 = sqrtf(var_f29); + if (var_f30 != 0.0f) { + var_f30 = 1.0f / var_f30; + } else { + var_f30 = 0.0f; + } + arg3[0] *= var_f30; + arg3[1] *= var_f30; + arg3[2] *= var_f30; + arg3[3] = -(arg3[0] * arg0->x + arg3[1] * arg0->y + arg3[2] * arg0->z); +} + +s32 fn_1_12C6C(Vec* arg0, Vec* arg1, float* arg2) { + float temp_f31; + float temp_f30; + + temp_f31 = arg0->x * arg2[0] + arg0->y * arg2[1] + arg0->z * arg2[2] + arg2[3]; + temp_f30 = arg1->x * arg2[0] + arg1->y * arg2[1] + arg1->z * arg2[2] + arg2[3]; + if (temp_f31 <= 0.0f && temp_f30 > 0.0f) { + return 1; + } + if (temp_f31 >= 0.0f && temp_f30 < 0.0f) { + return -1; + } + return 0; +} + +float fn_1_12D6C(Vec* arg0, Vec* arg1, s32 arg2, float arg3, float arg4) { + float var_f31; + float var_f30; + float var_f29; + float var_f28; + float var_f27; + + switch (arg2) { + case 0: + var_f31 = arg0->y - arg3; + var_f30 = arg0->z - arg4; + var_f29 = arg1->y - arg3; + var_f28 = arg1->z - arg4; + break; + case 1: + var_f31 = arg0->x - arg3; + var_f30 = arg0->z - arg4; + var_f29 = arg1->x - arg3; + var_f28 = arg1->z - arg4; + break; + case 2: + var_f31 = arg0->x - arg3; + var_f30 = arg0->y - arg4; + var_f29 = arg1->x - arg3; + var_f28 = arg1->y - arg4; + break; + } + var_f27 = -(var_f30 * var_f29 - var_f31 * var_f28); + return var_f27; +} + +u8 lbl_1_data_914[][2] = { + { 0, 1 }, { 1, 2 }, { 2, 0 } +}; + +float fn_1_12E68(Vec* arg0, Vec* arg1, s32 arg2) { + float var_f31; + float var_f30; + float var_f29; + s32 i; + + switch (arg2) { + case 0: + var_f31 = arg1->y; + var_f30 = arg1->z; + break; + case 1: + var_f31 = arg1->x; + var_f30 = arg1->z; + break; + case 2: + var_f31 = arg1->x; + var_f30 = arg1->y; + break; + } + var_f29 = fn_1_12D6C(&arg0[lbl_1_data_914[0][0]], &arg0[lbl_1_data_914[0][1]], arg2, var_f31, var_f30); + if (var_f29 > 0.0f) { + for (i = 1; i < 3; i++) { + var_f29 = fn_1_12D6C(&arg0[lbl_1_data_914[i][0]], &arg0[lbl_1_data_914[i][1]], arg2, var_f31, var_f30); + if (var_f29 == 0.0f) { + return 1.0f; + } + if (var_f29 < 0.0f) { + return 0.0f; + } + } + return 1.0f; + } else { + for (i = 1; i < 3; i++) { + var_f29 = fn_1_12D6C(&arg0[lbl_1_data_914[i][0]], &arg0[lbl_1_data_914[i][1]], arg2, var_f31, var_f30); + if (var_f29 == 0.0f) { + return -1.0f; + } + if (var_f29 > 0.0f) { + return 0.0f; + } + } + return -1.0f; + } +} + +void fn_1_1334C(float* arg0, Vec* arg1, Vec* arg2, Vec* arg3, Vec* arg4) { + float temp_f26; + float temp_f25; + float temp_f24; + float temp_f31; + float temp_f30; + float temp_f29; + float var_f22; + float var_f21; + float var_f20; + float var_f19; + float var_f18; + float spC; + float var_f28; + + temp_f26 = arg0[0]; + temp_f25 = arg0[1]; + temp_f24 = arg0[2]; + var_f19 = arg3->x; + var_f18 = arg3->y; + spC = arg3->z; + temp_f31 = arg2->x; + temp_f30 = arg2->y; + temp_f29 = arg2->z; + var_f22 = arg1->x; + var_f21 = arg1->y; + var_f20 = arg1->z; + var_f28 = sqrtf(temp_f31 * temp_f31 + temp_f30 * temp_f30 + temp_f29 * temp_f29); + if (var_f28 != 0.0f) { + var_f28 = 1.0f / var_f28; + } + temp_f31 *= var_f28; + temp_f30 *= var_f28; + temp_f29 *= var_f28; + var_f28 = temp_f26 * temp_f31 + temp_f25 * temp_f30 + temp_f24 * temp_f29; + if (var_f28 != 0.0f) { + var_f28 = -(temp_f26 * (var_f22 - var_f19) + temp_f25 * (var_f21 - var_f18) + temp_f24 * (var_f20 - spC)) / var_f28; + } else { + var_f28 = 0.0f; + } + arg4->x = arg1->x + var_f28 * arg2->x; + arg4->y = arg1->y + var_f28 * arg2->y; + arg4->z = arg1->z + var_f28 * arg2->z; +} + +float fn_1_1367C(Vec* arg0, Vec* arg1, Vec* arg2, Vec* arg3, f32* arg4) { + Vec sp38; + Vec sp2C; + Vec sp20; + Vec sp14; + Vec sp8; + float temp_f31; + + arg0->z = 0.0f; + arg1->z = 0.0f; + arg2->z = 0.0f; + PSVECSubtract(arg1, arg0, &sp2C); + PSVECSubtract(arg2, arg0, &sp20); + temp_f31 = (sp2C.x * sp20.x + sp2C.y * sp20.y) / (sp2C.x * sp2C.x + sp2C.y * sp2C.y); + if (arg4 != NULL) { + *arg4 = temp_f31; + } + PSVECScale(&sp2C, &sp14, temp_f31); + PSVECAdd(&sp2C, &sp14, &sp38); + if (arg3 != NULL) { + *arg3 = sp38; + } + PSVECSubtract(arg2, &sp38, &sp8); + return PSVECMag(&sp8); +} + +s32 fn_1_137C4(Vec* arg0, Vec* arg1, Vec* arg2, Vec* arg3, float arg4, s32 arg5) { + Vec sp40; + Vec sp34; + Vec sp28; + Vec sp1C; + Vec sp10; + f32 temp_f30; + f32 temp_f29; + f32 temp_f28; + f32 var_f31; + + PSVECAdd(arg1, arg2, &sp28); + *arg3 = sp28; + PSVECNormalize(arg2, &sp1C); + PSVECScale(&sp1C, &sp1C, arg4); + PSVECAdd(arg1, &sp1C, &sp40); + PSVECAdd(&sp28, &sp1C, &sp34); + PSVECNormalize(arg2, &sp1C); + PSVECScale(&sp1C, &sp10, -arg4); + switch (arg5) { + case 0: + if (sp40.y >= arg0[0].y && sp34.y < arg0[0].y) { + if (sp1C.y == 0.0f) { + var_f31 = 0.0f; + } else { + var_f31 = (arg0[0].y - arg1->y) / sp1C.y; + } + temp_f30 = arg1->x + var_f31 * sp1C.x; + temp_f28 = arg1->z + var_f31 * sp1C.z; + if (temp_f30 >= arg0[0].x && temp_f30 <= arg0[2].x + && temp_f28 >= arg0[0].z && temp_f28 <= arg0[2].z) + { + arg3->x = temp_f30; + arg3->y = arg0[0].y + arg4 + 1.0f; + arg3->z = temp_f28; + PSVECAdd((Vec*) &arg3, &sp10, (Vec*) &arg3); + return 1; + } + } + break; + case 1: + if (sp40.y <= arg0[0].y && sp34.y > arg0[0].y) { + if (sp1C.y == 0.0f) { + var_f31 = 0.0f; + } else { + var_f31 = (arg0[0].y - arg1->y) / sp1C.y; + } + temp_f30 = arg1->x + var_f31 * sp1C.x; + temp_f28 = arg1->z + var_f31 * sp1C.z; + if (temp_f30 >= arg0[0].x && temp_f30 <= arg0[2].x + && temp_f28 <= arg0[0].z && temp_f28 >= arg0[2].z) + { + arg3->x = temp_f30; + arg3->y = arg0[0].y - arg4 - 1.0f; + arg3->z = temp_f28; + PSVECAdd((Vec*) &arg3, &sp10, (Vec*) &arg3); + return 1; + } + } + break; + case 2: + if (sp40.x <= arg0[0].x && sp34.x > arg0[0].x) { + if (sp1C.x == 0.0f) { + var_f31 = 0.0f; + } else { + var_f31 = (arg0[0].x - arg1->x) / sp1C.x; + } + temp_f29 = arg1->y + var_f31 * sp1C.y; + temp_f28 = arg1->z + var_f31 * sp1C.z; + if (temp_f29 <= arg0[0].y && temp_f29 >= arg0[2].y + && temp_f28 >= arg0[0].z && temp_f28 <= arg0[2].z) + { + arg3->x = arg0[0].x - arg4 - 1.0f; + arg3->y = temp_f29; + arg3->z = temp_f28; + PSVECAdd((Vec*) &arg3, &sp10, (Vec*) &arg3); + return 1; + } + } + break; + case 3: + if (sp40.x >= arg0[0].x && sp34.x < arg0[0].x) { + if (sp1C.x == 0.0f) { + var_f31 = 0.0f; + } else { + var_f31 = (arg0[0].x - arg1->x) / sp1C.x; + } + temp_f29 = arg1->y + var_f31 * sp1C.y; + temp_f28 = arg1->z + var_f31 * sp1C.z; + if (temp_f29 <= arg0[0].y && temp_f29 >= arg0[2].y + && temp_f28 <= arg0[0].z && temp_f28 >= arg0[2].z) + { + arg3->x = arg0[0].x + arg4 + 1.0f; + arg3->y = temp_f29; + arg3->z = temp_f28; + PSVECAdd((Vec*) &arg3, &sp10, (Vec*) &arg3); + return 1; + } + } + break; + case 4: + if (sp40.z >= arg0[0].z && sp34.z < arg0[0].z) { + if (sp1C.z == 0.0f) { + var_f31 = 0.0f; + } else { + var_f31 = (arg0[0].z - arg1->z) / sp1C.z; + } + temp_f30 = arg1->x + var_f31 * sp1C.x; + temp_f29 = arg1->y + var_f31 * sp1C.y; + if (temp_f30 >= arg0[0].x && temp_f30 <= arg0[2].x + && temp_f29 <= arg0[0].y && temp_f29 >= arg0[2].y) + { + arg3->x = temp_f30; + arg3->y = temp_f29; + arg3->z = arg0[0].z + arg4 + 1.0f; + PSVECAdd((Vec*) &arg3, &sp10, (Vec*) &arg3); + return 1; + } + } + break; + case 5: + if (sp40.z <= arg0[0].z && sp34.z > arg0[0].z) { + if (sp1C.z == 0.0f) { + var_f31 = 0.0f; + } else { + var_f31 = (arg0[0].z - arg1->z) / sp1C.z; + } + temp_f30 = arg1->x + var_f31 * sp1C.x; + temp_f29 = arg1->y + var_f31 * sp1C.y; + if (temp_f30 <= arg0[0].x && temp_f30 >= arg0[2].x + && temp_f29 <= arg0[0].y && temp_f29 >= arg0[2].y) + { + arg3->x = temp_f30; + arg3->y = temp_f29; + arg3->z = arg0[0].z - arg4 - 1.0f; + PSVECAdd((Vec*) &arg3, &sp10, (Vec*) &arg3); + return 1; + } + } + break; + } + return 0; +} diff --git a/src/REL/m426Dll/main.c b/src/REL/m426Dll/main.c index ae15dbe3..7066b831 100644 --- a/src/REL/m426Dll/main.c +++ b/src/REL/m426Dll/main.c @@ -3170,7 +3170,7 @@ void fn_1_88B4(ModelData *arg0, Mtx arg1) GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXSetArray(GX_VA_POS, lbl_1_data_27C, 12); GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); diff --git a/src/REL/m440Dll/main.c b/src/REL/m440Dll/main.c index 1ec95168..e6c29642 100644 --- a/src/REL/m440Dll/main.c +++ b/src/REL/m440Dll/main.c @@ -1875,11 +1875,11 @@ void fn_1_806C(ModelData *arg0, Mtx arg1) GXSetChanMatColor(GX_COLOR0A0, sp10); GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_RGBA6, 0); - GXSetArray(GX_VA_POS, temp_r31->unkC, 0xC); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetArray(GX_VA_POS, temp_r31->unkC, 12); GXSetVtxDesc(GX_VA_NRM, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_TEX_S, GX_RGBA6, 0); - GXSetArray(GX_VA_NRM, temp_r31->unk14, 0xC); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); + GXSetArray(GX_VA_NRM, temp_r31->unk14, 12); lbl_1_bss_C = temp_r31->unk3C; if (temp_r31->unk28->unk34 == 0) { GXSetNumTevStages(1); @@ -1893,7 +1893,7 @@ void fn_1_806C(ModelData *arg0, Mtx arg1) } else { GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GXSetArray(GX_VA_TEX0, temp_r31->unk1C, 8); temp_r29 = &temp_r31->unk2C[temp_r31->unk28->unk38[0]]; fn_1_7D60(temp_r29->unk80, temp_r29, 0); @@ -2600,7 +2600,7 @@ void fn_1_A390(ModelData *arg0, Mtx arg1) GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_TEX_ST, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); GXSetNumTevStages(1); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO); diff --git a/src/REL/m448Dll/main.c b/src/REL/m448Dll/main.c index fce3e974..1ee1eb09 100755 --- a/src/REL/m448Dll/main.c +++ b/src/REL/m448Dll/main.c @@ -220,11 +220,11 @@ void fn_1_4FC(ModelData *model, Mtx matrix) GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_RGBA6, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); for (i = 0; i < 0; i++) { s32 sp84[5] = { 0, 1, 1, 0, 1 }; float sp70[5] = { 1.0f, 2.0f, 2.5f, 0.0f, 0.0f }; diff --git a/src/REL/modeltestDll/main.c b/src/REL/modeltestDll/main.c index a871df64..7c8dc93a 100644 --- a/src/REL/modeltestDll/main.c +++ b/src/REL/modeltestDll/main.c @@ -775,13 +775,13 @@ void fn_1_2B68(ModelData *mdl, Mtx arg1) GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetVtxDesc(GX_VA_NRM, GX_DIRECT); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0U); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0U); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0U); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); GXSetCullMode(GX_CULL_NONE); GXSetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE); GXSetNumTexGens(1); - GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3CU, 0U, 0x7DU); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); GXSetNumTevStages(1); sp17.r = sp17.g = sp17.b = sp17.a = 255; From dd04a5faff8005e05ec1ce966f5ad4194d066863 Mon Sep 17 00:00:00 2001 From: dbalatoni13 Date: Mon, 30 Dec 2024 20:54:58 +0100 Subject: [PATCH 2/4] Match ar/ar.c --- configure.py | 2 +- src/dolphin/ar/ar.c | 418 +++++++++++++++++++++++++++++--------------- 2 files changed, 277 insertions(+), 143 deletions(-) diff --git a/configure.py b/configure.py index 08fc269a..88e5c103 100644 --- a/configure.py +++ b/configure.py @@ -567,7 +567,7 @@ config.libs = [ DolphinLib( "ar", [ - Object(NonMatching, "dolphin/ar/ar.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/ar/ar.c"), Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/ar/arq.c"), ], ), diff --git a/src/dolphin/ar/ar.c b/src/dolphin/ar/ar.c index 7f43c1a7..529a6000 100644 --- a/src/dolphin/ar/ar.c +++ b/src/dolphin/ar/ar.c @@ -2,6 +2,7 @@ #include "dolphin/hw_regs.h" #include "dolphin/os.h" +#include "dolphin/os/OSCache.h" static ARCallback __AR_Callback; static u32 __AR_Size; @@ -10,82 +11,89 @@ static u32 __AR_ExpansionSize; static u32 __AR_StackPointer; static u32 __AR_FreeBlocks; -static u32* __AR_BlockLength; +static u32 *__AR_BlockLength; static volatile BOOL __AR_init_flag = FALSE; -static void __ARHandler(__OSInterrupt interrupt, OSContext* context); +static void __ARHandler(__OSInterrupt interrupt, OSContext *context); static void __ARChecksize(void); static void __ARClearArea(u32 start_addr, u32 length); -ARCallback ARRegisterDMACallback(ARCallback callback) { - ARCallback oldCb; - BOOL enabled; - oldCb = __AR_Callback; - enabled = OSDisableInterrupts(); - __AR_Callback = callback; - OSRestoreInterrupts(enabled); - return oldCb; +// TODO import defines for magic numbers from other repos + +ARCallback ARRegisterDMACallback(ARCallback callback) +{ + ARCallback oldCb; + BOOL enabled; + oldCb = __AR_Callback; + enabled = OSDisableInterrupts(); + __AR_Callback = callback; + OSRestoreInterrupts(enabled); + return oldCb; } -u32 ARGetDMAStatus() { - BOOL enabled; - u32 val; - enabled = OSDisableInterrupts(); - val = __DSPRegs[5] & 0x0200; - OSRestoreInterrupts(enabled); - return val; +u32 ARGetDMAStatus() +{ + BOOL enabled; + u32 val; + enabled = OSDisableInterrupts(); + val = __DSPRegs[5] & 0x0200; + OSRestoreInterrupts(enabled); + return val; } -void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length) { - BOOL enabled; +void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length) +{ + BOOL enabled; - enabled = OSDisableInterrupts(); + enabled = OSDisableInterrupts(); - __DSPRegs[16] = (u16)(__DSPRegs[16] & ~0x3ff) | (u16)(mainmem_addr >> 16); - __DSPRegs[17] = (u16)(__DSPRegs[17] & ~0xffe0) | (u16)(mainmem_addr & 0xffff); - __DSPRegs[18] = (u16)(__DSPRegs[18] & ~0x3ff) | (u16)(aram_addr >> 16); - __DSPRegs[19] = (u16)(__DSPRegs[19] & ~0xffe0) | (u16)(aram_addr & 0xffff); - __DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x8000) | (type << 15)); - __DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x3ff) | (u16)(length >> 16); - __DSPRegs[21] = (u16)(__DSPRegs[21] & ~0xffe0) | (u16)(length & 0xffff); - OSRestoreInterrupts(enabled); + __DSPRegs[16] = (u16)(__DSPRegs[16] & ~0x3ff) | (u16)(mainmem_addr >> 16); + __DSPRegs[17] = (u16)(__DSPRegs[17] & ~0xffe0) | (u16)(mainmem_addr & 0xffff); + __DSPRegs[18] = (u16)(__DSPRegs[18] & ~0x3ff) | (u16)(aram_addr >> 16); + __DSPRegs[19] = (u16)(__DSPRegs[19] & ~0xffe0) | (u16)(aram_addr & 0xffff); + __DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x8000) | (type << 15)); + __DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x3ff) | (u16)(length >> 16); + __DSPRegs[21] = (u16)(__DSPRegs[21] & ~0xffe0) | (u16)(length & 0xffff); + OSRestoreInterrupts(enabled); } -u32 ARAlloc(u32 length) { - u32 tmp; - BOOL enabled; +u32 ARAlloc(u32 length) +{ + u32 tmp; + BOOL enabled; - enabled = OSDisableInterrupts(); - tmp = __AR_StackPointer; - __AR_StackPointer += length; - *__AR_BlockLength = length; - __AR_BlockLength++; - __AR_FreeBlocks--; - OSRestoreInterrupts(enabled); + enabled = OSDisableInterrupts(); + tmp = __AR_StackPointer; + __AR_StackPointer += length; + *__AR_BlockLength = length; + __AR_BlockLength++; + __AR_FreeBlocks--; + OSRestoreInterrupts(enabled); - return tmp; + return tmp; } #if NONMATCHING -u32 ARFree(u32* length) { - BOOL old; +u32 ARFree(u32 *length) +{ + BOOL old; - old = OSDisableInterrupts(); + old = OSDisableInterrupts(); - __AR_BlockLength--; + __AR_BlockLength--; - if (length) { - *length = *__AR_BlockLength; - } + if (length) { + *length = *__AR_BlockLength; + } - __AR_StackPointer -= *__AR_BlockLength; + __AR_StackPointer -= *__AR_BlockLength; - __AR_FreeBlocks++; + __AR_FreeBlocks++; - OSRestoreInterrupts(old); + OSRestoreInterrupts(old); - return __AR_StackPointer; + return __AR_StackPointer; } #else /* clang-format off */ @@ -129,123 +137,249 @@ lbl_8036DAB4: /* clang-format on */ #endif -BOOL ARCheckInit() { return __AR_init_flag; } - -u32 ARInit(u32* stack_index_addr, u32 num_entries) { - - BOOL old; - u16 refresh; - - if (__AR_init_flag == TRUE) { - return 0x4000; - } - - old = OSDisableInterrupts(); - - __AR_Callback = NULL; - - __OSSetInterruptHandler(__OS_INTERRUPT_DSP_ARAM, __ARHandler); - __OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_ARAM); - - __AR_StackPointer = 0x4000; - __AR_FreeBlocks = num_entries; - __AR_BlockLength = stack_index_addr; - - refresh = (u16)(__DSPRegs[13] & 0x000000ff); - - __DSPRegs[13] = (u16)((__DSPRegs[13] & ~0x000000ff) | (refresh & 0x000000ff)); - - __ARChecksize(); - - __AR_init_flag = TRUE; - - OSRestoreInterrupts(old); - - return __AR_StackPointer; -} - -u32 ARGetBaseAddress(void) { return 0x4000; } - -void ARSetSize(void) +BOOL ARCheckInit() { - + return __AR_init_flag; } -u32 ARGetSize() { return __AR_Size; } +u32 ARInit(u32 *stack_index_addr, u32 num_entries) +{ -static void __ARHandler(__OSInterrupt interrupt, OSContext* context) { + BOOL old; + u16 refresh; - OSContext exceptionContext; - u16 tmp; + if (__AR_init_flag == TRUE) { + return 0x4000; + } - tmp = __DSPRegs[5]; - tmp = (u16)((tmp & ~0x00000088) | 0x20); - __DSPRegs[5] = tmp; + old = OSDisableInterrupts(); - OSClearContext(&exceptionContext); - OSSetCurrentContext(&exceptionContext); + __AR_Callback = NULL; - if (__AR_Callback) { - (*__AR_Callback)(); - } + __OSSetInterruptHandler(__OS_INTERRUPT_DSP_ARAM, __ARHandler); + __OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_ARAM); - OSClearContext(&exceptionContext); - OSSetCurrentContext(context); + __AR_StackPointer = 0x4000; + __AR_FreeBlocks = num_entries; + __AR_BlockLength = stack_index_addr; + + refresh = (u16)(__DSPRegs[13] & 0x000000ff); + + __DSPRegs[13] = (u16)((__DSPRegs[13] & ~0x000000ff) | (refresh & 0x000000ff)); + + __ARChecksize(); + + __AR_init_flag = TRUE; + + OSRestoreInterrupts(old); + + return __AR_StackPointer; +} + +void ARSetSize(void) { } + +u32 ARGetBaseAddress(void) +{ + return 0x4000; +} + +u32 ARGetSize() +{ + return __AR_Size; +} + +static void __ARHandler(__OSInterrupt interrupt, OSContext *context) +{ + + OSContext exceptionContext; + u16 tmp; + + tmp = __DSPRegs[5]; + tmp = (u16)((tmp & ~0x00000088) | 0x20); + __DSPRegs[5] = tmp; + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + + if (__AR_Callback) { + (*__AR_Callback)(); + } + + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); } #define RoundUP32(x) (((u32)(x) + 32 - 1) & ~(32 - 1)) -void __ARClearInterrupt(void) { +void __ARClearInterrupt(void) +{ - u16 tmp; - tmp = __DSPRegs[5]; - tmp = (u16)((tmp & ~(0x00000080 | 0x00000008)) | 0x00000020); - __DSPRegs[5] = tmp; + u16 tmp; + tmp = __DSPRegs[5]; + tmp = (u16)((tmp & ~(0x00000080 | 0x00000008)) | 0x00000020); + __DSPRegs[5] = tmp; } -u16 __ARGetInterruptStatus(void) { return ((u16)(__DSPRegs[5] & 0x0200)); } - -static void __ARWaitForDMA(void) { - - while (__DSPRegs[5] & 0x0200) { - } +u16 __ARGetInterruptStatus(void) +{ + return ((u16)(__DSPRegs[5] & 0x0200)); } -static void __ARWriteDMA(u32 mmem_addr, u32 aram_addr, u32 length) { +static void __ARWaitForDMA(void) +{ - __DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16)); - __DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff)); - - __DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16)); - __DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff)); - - __DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x8000); - - __DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16)); - __DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff)); - - __ARWaitForDMA(); - - __ARClearInterrupt(); + while (__DSPRegs[5] & 0x0200) { } } -static void __ARReadDMA(u32 mmem_addr, u32 aram_addr, u32 length) { +static void __ARWriteDMA(u32 mmem_addr, u32 aram_addr, u32 length) +{ - __DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16)); - __DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff)); + __DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16)); + __DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff)); - __DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16)); - __DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff)); + __DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16)); + __DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff)); - __DSPRegs[20] = (u16)(__DSPRegs[20] | 0x8000); + __DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x8000); - __DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16)); - __DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff)); + __DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16)); + __DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff)); - __ARWaitForDMA(); + __ARWaitForDMA(); - __ARClearInterrupt(); + __ARClearInterrupt(); } -static void __ARChecksize(void) { - //TODO: Implement for this SDK version -} \ No newline at end of file +static void __ARReadDMA(u32 mmem_addr, u32 aram_addr, u32 length) +{ + + __DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16)); + __DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff)); + + __DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16)); + __DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff)); + + __DSPRegs[20] = (u16)(__DSPRegs[20] | 0x8000); + + __DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16)); + __DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff)); + + __ARWaitForDMA(); + + __ARClearInterrupt(); +} + +void __ARChecksize(void) +{ + u8 test_data_pad[0x20 + 31]; + u8 dummy_data_pad[0x20 + 31]; + u8 buffer_pad[0x20 + 31]; + + u32 *test_data; + u32 *dummy_data; + u32 *buffer; + + u16 ARAM_mode; + u32 ARAM_size; + + u32 i; + + while (!(__DSPRegs[11] & 1)) + ; + + ARAM_mode = 3; + ARAM_size = __AR_InternalSize = 0x1000000; + __DSPRegs[9] = (u16)((__DSPRegs[9] & ~(0x00000007 | 0x00000038)) | 0x20 | 2 | 1); + + test_data = (u32 *)(RoundUP32((u32)(test_data_pad))); + dummy_data = (u32 *)(RoundUP32((u32)(dummy_data_pad))); + buffer = (u32 *)(RoundUP32((u32)(buffer_pad))); + + for (i = 0; i < 8; i++) { + *(test_data + i) = 0xdeadbeef; + *(dummy_data + i) = 0xbad0bad0; + } + + DCFlushRange((void *)test_data, 0x20); + DCFlushRange((void *)dummy_data, 0x20); + + __AR_ExpansionSize = 0; + + __ARWriteDMA((u32)dummy_data, ARAM_size, 0x20U); + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x200000, 0x20U); + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x01000000, 0x20U); + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x200, 0x20U); + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x400000, 0x20U); + + memset((void *)buffer, 0, 0x20); + DCFlushRange((void *)buffer, 0x20); + + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + DCInvalidateRange((void *)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0000000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + memset((void *)buffer, 0, 0x20); + DCFlushRange((void *)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0200000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + ARAM_mode |= 0 << 1; + ARAM_size += 0x0200000; + __AR_ExpansionSize = 0x0200000; + } + else { + memset((void *)buffer, 0, 0x20); + DCFlushRange((void *)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x1000000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + ARAM_mode |= 4 << 1; + ARAM_size += 0x0400000; + __AR_ExpansionSize = 0x0400000; + } + else { + memset((void *)buffer, 0, 0x20); + DCFlushRange((void *)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0000200, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + ARAM_mode |= 8 << 1; + ARAM_size += 0x800000; + __AR_ExpansionSize = 0x0800000; + } + else { + memset((void *)buffer, 0, 0x20); + DCFlushRange((void *)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0400000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + ARAM_mode |= 12 << 1; + ARAM_size += 0x1000000; + __AR_ExpansionSize = 0x1000000; + } + else { + ARAM_mode |= 16 << 1; + ARAM_size += 0x2000000; + __AR_ExpansionSize = 0x2000000; + } + } + } + } + __DSPRegs[9] = (u16)((__DSPRegs[9] & ~(0x07 | 0x38)) | ARAM_mode); + } + + *(u32 *)OSPhysicalToUncached(0x00D0) = ARAM_size; + + __AR_Size = ARAM_size; +} From b4279816e7bf8ed81994acee488615906417f063 Mon Sep 17 00:00:00 2001 From: dbalatoni13 Date: Mon, 30 Dec 2024 21:01:04 +0100 Subject: [PATCH 3/4] Uncomment ar.c::ARFree --- src/dolphin/ar/ar.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/src/dolphin/ar/ar.c b/src/dolphin/ar/ar.c index 529a6000..94954318 100644 --- a/src/dolphin/ar/ar.c +++ b/src/dolphin/ar/ar.c @@ -74,7 +74,6 @@ u32 ARAlloc(u32 length) return tmp; } -#if NONMATCHING u32 ARFree(u32 *length) { BOOL old; @@ -95,47 +94,6 @@ u32 ARFree(u32 *length) return __AR_StackPointer; } -#else -/* clang-format off */ -#pragma push -#pragma optimization_level 0 -#pragma optimizewithasm off -asm u32 ARFree(u32* length) { - nofralloc - mflr r0 - stw r0, 4(r1) - stwu r1, -0x18(r1) - stw r31, 0x14(r1) - mr r31, r3 - bl OSDisableInterrupts - lwz r4, __AR_BlockLength - cmplwi r31, 0 - addi r0, r4, -4 - stw r0, __AR_BlockLength - beq lbl_8036DAB4 - lwz r4, __AR_BlockLength - lwz r0, 0(r4) - stw r0, 0(r31) -lbl_8036DAB4: - lwz r5, __AR_BlockLength - lwz r4, __AR_FreeBlocks - lwz r6, 0(r5) - addi r0, r4, 1 - lwz r5, __AR_StackPointer - stw r0, __AR_FreeBlocks - subf r0, r6, r5 - stw r0, __AR_StackPointer - bl OSRestoreInterrupts - lwz r3, __AR_StackPointer - lwz r0, 0x1c(r1) - lwz r31, 0x14(r1) - addi r1, r1, 0x18 - mtlr r0 - blr -} -#pragma pop -/* clang-format on */ -#endif BOOL ARCheckInit() { From 3b90bdcb7fb1525f122820f728d66b94fa4547ed Mon Sep 17 00:00:00 2001 From: dbalatoni13 Date: Tue, 31 Dec 2024 02:21:59 +0100 Subject: [PATCH 4/4] Match a lot of GX --- config/GMPE01_00/symbols.txt | 100 +-- config/GMPE01_01/symbols.txt | 2 +- config/GMPJ01_00/symbols.txt | 2 +- config/GMPP01_00/symbols.txt | 2 +- configure.py | 22 +- include/dolphin/gx/GXEnum.h | 2 +- include/dolphin/gx/GXPriv.h | 455 +++++++++--- include/dolphin/gx/GXStruct.h | 20 + include/dolphin/gx/GXTexture.h | 50 +- src/dolphin/gx/GXAttr.c | 586 +++++++++++++++ src/dolphin/gx/GXBump.c | 335 +++++++++ src/dolphin/gx/GXDisplayList.c | 83 +++ src/dolphin/gx/GXFifo.c | 559 ++++++++++++++ src/dolphin/gx/GXFrameBuf.c | 604 +++++++++++++++ src/dolphin/gx/GXGeometry.c | 146 ++++ src/dolphin/gx/GXInit.c | 372 ++++++++++ src/dolphin/gx/GXLight.c | 620 ++++++++++++++++ src/dolphin/gx/GXMisc.c | 485 ++++++++++++ src/dolphin/gx/GXPerf.c | 577 +++++++++++++++ src/dolphin/gx/GXPixel.c | 290 ++++++++ src/dolphin/gx/GXStubs.c | 5 + src/dolphin/gx/GXTev.c | 403 ++++++++++ src/dolphin/gx/GXTexture.c | 1269 ++++++++++++++++++++++++++++++++ src/dolphin/gx/GXTransform.c | 372 ++++++++++ src/game/kerent.c | 8 +- 25 files changed, 7195 insertions(+), 174 deletions(-) create mode 100644 src/dolphin/gx/GXAttr.c create mode 100644 src/dolphin/gx/GXBump.c create mode 100644 src/dolphin/gx/GXDisplayList.c create mode 100644 src/dolphin/gx/GXFifo.c create mode 100644 src/dolphin/gx/GXFrameBuf.c create mode 100644 src/dolphin/gx/GXGeometry.c create mode 100644 src/dolphin/gx/GXInit.c create mode 100644 src/dolphin/gx/GXLight.c create mode 100644 src/dolphin/gx/GXMisc.c create mode 100644 src/dolphin/gx/GXPerf.c create mode 100644 src/dolphin/gx/GXPixel.c create mode 100644 src/dolphin/gx/GXStubs.c create mode 100644 src/dolphin/gx/GXTev.c create mode 100644 src/dolphin/gx/GXTexture.c create mode 100644 src/dolphin/gx/GXTransform.c diff --git a/config/GMPE01_00/symbols.txt b/config/GMPE01_00/symbols.txt index 60b719ff..3e84f320 100644 --- a/config/GMPE01_00/symbols.txt +++ b/config/GMPE01_00/symbols.txt @@ -2572,7 +2572,7 @@ GXEndDisplayList = .text:0x800CF0E0; // type:function size:0xD4 GXCallDisplayList = .text:0x800CF1B4; // type:function size:0x70 GXProject = .text:0x800CF224; // type:function size:0x174 GXSetProjection = .text:0x800CF398; // type:function size:0xD4 -GXSetProjectionv = .text:0x800CF46C; // type:function size:0x78 +GXGetProjectionv = .text:0x800CF46C; // type:function size:0x78 WriteMTXPS4x3 = .text:0x800CF4E4; // type:function size:0x34 scope:local WriteMTXPS3x3from3x4 = .text:0x800CF518; // type:function size:0x34 scope:local WriteMTXPS4x2 = .text:0x800CF54C; // type:function size:0x24 scope:local @@ -7410,55 +7410,55 @@ lbl_801D63C8 = .sdata2:0x801D63C8; // type:object size:0x8 scope:local data:doub lbl_801D63D0 = .sdata2:0x801D63D0; // type:object size:0x8 scope:local data:float lbl_801D63D8 = .sdata2:0x801D63D8; // type:object size:0x4 scope:local data:float lbl_801D63E0 = .sdata2:0x801D63E0; // type:object size:0x8 scope:local data:double -lbl_801D63E8 = .sdata2:0x801D63E8; // type:object size:0x4 data:4byte -lbl_801D63EC = .sdata2:0x801D63EC; // type:object size:0x4 data:4byte -lbl_801D63F0 = .sdata2:0x801D63F0; // type:object size:0x4 data:4byte -lbl_801D63F4 = .sdata2:0x801D63F4; // type:object size:0x4 data:float -lbl_801D63F8 = .sdata2:0x801D63F8; // type:object size:0x4 data:float -lbl_801D63FC = .sdata2:0x801D63FC; // type:object size:0x4 data:float -lbl_801D6400 = .sdata2:0x801D6400; // type:object size:0x8 data:double -lbl_801D6408 = .sdata2:0x801D6408; // type:object size:0x8 data:float -lbl_801D6410 = .sdata2:0x801D6410; // type:object size:0x4 data:float -lbl_801D6414 = .sdata2:0x801D6414; // type:object size:0x4 data:float -lbl_801D6418 = .sdata2:0x801D6418; // type:object size:0x4 data:float -lbl_801D641C = .sdata2:0x801D641C; // type:object size:0x4 data:float -lbl_801D6420 = .sdata2:0x801D6420; // type:object size:0x4 data:float -lbl_801D6424 = .sdata2:0x801D6424; // type:object size:0x4 data:float -lbl_801D6428 = .sdata2:0x801D6428; // type:object size:0x4 data:float -lbl_801D642C = .sdata2:0x801D642C; // type:object size:0x4 data:float -lbl_801D6430 = .sdata2:0x801D6430; // type:object size:0x4 data:float -lbl_801D6434 = .sdata2:0x801D6434; // type:object size:0x4 data:float -lbl_801D6438 = .sdata2:0x801D6438; // type:object size:0x4 data:float -lbl_801D643C = .sdata2:0x801D643C; // type:object size:0x4 data:float -lbl_801D6440 = .sdata2:0x801D6440; // type:object size:0x4 data:float -lbl_801D6448 = .sdata2:0x801D6448; // type:object size:0x8 data:double -lbl_801D6450 = .sdata2:0x801D6450; // type:object size:0x8 data:double -lbl_801D6458 = .sdata2:0x801D6458; // type:object size:0x8 data:float -lbl_801D6460 = .sdata2:0x801D6460; // type:object size:0x4 data:float -lbl_801D6468 = .sdata2:0x801D6468; // type:object size:0x8 data:double -lbl_801D6470 = .sdata2:0x801D6470; // type:object size:0x4 data:float -lbl_801D6474 = .sdata2:0x801D6474; // type:object size:0x4 data:float -lbl_801D6478 = .sdata2:0x801D6478; // type:object size:0x4 data:float -lbl_801D647C = .sdata2:0x801D647C; // type:object size:0x4 data:float -lbl_801D6480 = .sdata2:0x801D6480; // type:object size:0x4 data:float -lbl_801D6484 = .sdata2:0x801D6484; // type:object size:0x4 data:float -lbl_801D6488 = .sdata2:0x801D6488; // type:object size:0x4 data:float -lbl_801D648C = .sdata2:0x801D648C; // type:object size:0x4 data:float -lbl_801D6490 = .sdata2:0x801D6490; // type:object size:0x4 data:float -lbl_801D6498 = .sdata2:0x801D6498; // type:object size:0x8 data:double -lbl_801D64A0 = .sdata2:0x801D64A0; // type:object size:0x4 data:float -lbl_801D64A4 = .sdata2:0x801D64A4; // type:object size:0x4 data:float -lbl_801D64A8 = .sdata2:0x801D64A8; // type:object size:0x8 data:double -lbl_801D64B0 = .sdata2:0x801D64B0; // type:object size:0x4 data:float -lbl_801D64B8 = .sdata2:0x801D64B8; // type:object size:0x8 data:double -lbl_801D64C0 = .sdata2:0x801D64C0; // type:object size:0x4 data:float -lbl_801D64C8 = .sdata2:0x801D64C8; // type:object size:0x8 data:double -lbl_801D64D0 = .sdata2:0x801D64D0; // type:object size:0x4 data:float -lbl_801D64D4 = .sdata2:0x801D64D4; // type:object size:0x4 data:float -lbl_801D64D8 = .sdata2:0x801D64D8; // type:object size:0x4 data:float -lbl_801D64E0 = .sdata2:0x801D64E0; // type:object size:0x8 data:double -lbl_801D64E8 = .sdata2:0x801D64E8; // type:object size:0x4 data:float -lbl_801D64EC = .sdata2:0x801D64EC; // type:object size:0x4 data:float +lbl_801D63E8 = .sdata2:0x801D63E8; // type:object size:0x4 scope:local data:4byte +lbl_801D63EC = .sdata2:0x801D63EC; // type:object size:0x4 scope:local data:4byte +lbl_801D63F0 = .sdata2:0x801D63F0; // type:object size:0x4 scope:local data:4byte +lbl_801D63F4 = .sdata2:0x801D63F4; // type:object size:0x4 scope:local data:float +lbl_801D63F8 = .sdata2:0x801D63F8; // type:object size:0x4 scope:local data:float +lbl_801D63FC = .sdata2:0x801D63FC; // type:object size:0x4 scope:local data:float +lbl_801D6400 = .sdata2:0x801D6400; // type:object size:0x8 scope:local data:double +lbl_801D6408 = .sdata2:0x801D6408; // type:object size:0x8 scope:local data:float +lbl_801D6410 = .sdata2:0x801D6410; // type:object size:0x4 scope:local data:float +lbl_801D6414 = .sdata2:0x801D6414; // type:object size:0x4 scope:local data:float +lbl_801D6418 = .sdata2:0x801D6418; // type:object size:0x4 scope:local data:float +lbl_801D641C = .sdata2:0x801D641C; // type:object size:0x4 scope:local data:float +lbl_801D6420 = .sdata2:0x801D6420; // type:object size:0x4 scope:local data:float +lbl_801D6424 = .sdata2:0x801D6424; // type:object size:0x4 scope:local data:float +lbl_801D6428 = .sdata2:0x801D6428; // type:object size:0x4 scope:local data:float +lbl_801D642C = .sdata2:0x801D642C; // type:object size:0x4 scope:local data:float +lbl_801D6430 = .sdata2:0x801D6430; // type:object size:0x4 scope:local data:float +lbl_801D6434 = .sdata2:0x801D6434; // type:object size:0x4 scope:local data:float +lbl_801D6438 = .sdata2:0x801D6438; // type:object size:0x4 scope:local data:float +lbl_801D643C = .sdata2:0x801D643C; // type:object size:0x4 scope:local data:float +lbl_801D6440 = .sdata2:0x801D6440; // type:object size:0x4 scope:local data:float +lbl_801D6448 = .sdata2:0x801D6448; // type:object size:0x8 scope:local data:double +lbl_801D6450 = .sdata2:0x801D6450; // type:object size:0x8 scope:local data:double +lbl_801D6458 = .sdata2:0x801D6458; // type:object size:0x8 scope:local data:float +lbl_801D6460 = .sdata2:0x801D6460; // type:object size:0x4 scope:local data:float +lbl_801D6468 = .sdata2:0x801D6468; // type:object size:0x8 scope:local data:double +lbl_801D6470 = .sdata2:0x801D6470; // type:object size:0x4 scope:local data:float +lbl_801D6474 = .sdata2:0x801D6474; // type:object size:0x4 scope:local data:float +lbl_801D6478 = .sdata2:0x801D6478; // type:object size:0x4 scope:local data:float +lbl_801D647C = .sdata2:0x801D647C; // type:object size:0x4 scope:local data:float +lbl_801D6480 = .sdata2:0x801D6480; // type:object size:0x4 scope:local data:float +lbl_801D6484 = .sdata2:0x801D6484; // type:object size:0x4 scope:local data:float +lbl_801D6488 = .sdata2:0x801D6488; // type:object size:0x4 scope:local data:float +lbl_801D648C = .sdata2:0x801D648C; // type:object size:0x4 scope:local data:float +lbl_801D6490 = .sdata2:0x801D6490; // type:object size:0x4 scope:local data:float +lbl_801D6498 = .sdata2:0x801D6498; // type:object size:0x8 scope:local data:double +lbl_801D64A0 = .sdata2:0x801D64A0; // type:object size:0x4 scope:local data:float +lbl_801D64A4 = .sdata2:0x801D64A4; // type:object size:0x4 scope:local data:float +lbl_801D64A8 = .sdata2:0x801D64A8; // type:object size:0x8 scope:local data:double +lbl_801D64B0 = .sdata2:0x801D64B0; // type:object size:0x4 scope:local data:float +lbl_801D64B8 = .sdata2:0x801D64B8; // type:object size:0x8 scope:local data:double +lbl_801D64C0 = .sdata2:0x801D64C0; // type:object size:0x4 scope:local data:float +lbl_801D64C8 = .sdata2:0x801D64C8; // type:object size:0x8 scope:local data:double +lbl_801D64D0 = .sdata2:0x801D64D0; // type:object size:0x4 scope:local data:float +lbl_801D64D4 = .sdata2:0x801D64D4; // type:object size:0x4 scope:local data:float +lbl_801D64D8 = .sdata2:0x801D64D8; // type:object size:0x4 scope:local data:float +lbl_801D64E0 = .sdata2:0x801D64E0; // type:object size:0x8 scope:local data:double +lbl_801D64E8 = .sdata2:0x801D64E8; // type:object size:0x4 scope:local data:float +lbl_801D64EC = .sdata2:0x801D64EC; // type:object size:0x4 scope:local data:float lbl_801D64F0 = .sdata2:0x801D64F0; // type:object size:0x8 data:double lbl_801D64F8 = .sdata2:0x801D64F8; // type:object size:0x4 data:float lbl_801D64FC = .sdata2:0x801D64FC; // type:object size:0x4 data:float diff --git a/config/GMPE01_01/symbols.txt b/config/GMPE01_01/symbols.txt index 4a3aaa79..ef9eff80 100644 --- a/config/GMPE01_01/symbols.txt +++ b/config/GMPE01_01/symbols.txt @@ -2572,7 +2572,7 @@ GXEndDisplayList = .text:0x800CF0E0; // type:function size:0xD4 GXCallDisplayList = .text:0x800CF1B4; // type:function size:0x70 GXProject = .text:0x800CF224; // type:function size:0x174 GXSetProjection = .text:0x800CF398; // type:function size:0xD4 -GXSetProjectionv = .text:0x800CF46C; // type:function size:0x78 +GXGetProjectionv = .text:0x800CF46C; // type:function size:0x78 WriteMTXPS4x3 = .text:0x800CF4E4; // type:function size:0x34 scope:local WriteMTXPS3x3from3x4 = .text:0x800CF518; // type:function size:0x34 scope:local WriteMTXPS4x2 = .text:0x800CF54C; // type:function size:0x24 scope:local diff --git a/config/GMPJ01_00/symbols.txt b/config/GMPJ01_00/symbols.txt index 8701d170..ca5a261c 100644 --- a/config/GMPJ01_00/symbols.txt +++ b/config/GMPJ01_00/symbols.txt @@ -2573,7 +2573,7 @@ GXEndDisplayList = .text:0x800CECD0; // type:function size:0xD4 GXCallDisplayList = .text:0x800CEDA4; // type:function size:0x70 GXProject = .text:0x800CEE14; // type:function size:0x174 GXSetProjection = .text:0x800CEF88; // type:function size:0xD4 -GXSetProjectionv = .text:0x800CF05C; // type:function size:0x78 +GXGetProjectionv = .text:0x800CF05C; // type:function size:0x78 WriteMTXPS4x3 = .text:0x800CF0D4; // type:function size:0x34 scope:local WriteMTXPS3x3from3x4 = .text:0x800CF108; // type:function size:0x34 scope:local WriteMTXPS4x2 = .text:0x800CF13C; // type:function size:0x24 scope:local diff --git a/config/GMPP01_00/symbols.txt b/config/GMPP01_00/symbols.txt index 83524e64..acf35410 100644 --- a/config/GMPP01_00/symbols.txt +++ b/config/GMPP01_00/symbols.txt @@ -2574,7 +2574,7 @@ GXEndDisplayList = .text:0x800CEF10; // type:function size:0xD4 GXCallDisplayList = .text:0x800CEFE4; // type:function size:0x70 GXProject = .text:0x800CF054; // type:function size:0x174 GXSetProjection = .text:0x800CF1C8; // type:function size:0xD4 -GXSetProjectionv = .text:0x800CF29C; // type:function size:0x78 +GXGetProjectionv = .text:0x800CF29C; // type:function size:0x78 fn_800CF314 = .text:0x800CF314; // type:function size:0x34 fn_800CF348 = .text:0x800CF348; // type:function size:0x34 fn_800CF37C = .text:0x800CF37C; // type:function size:0x24 diff --git a/configure.py b/configure.py index 88e5c103..ec8265ae 100644 --- a/configure.py +++ b/configure.py @@ -584,19 +584,19 @@ config.libs = [ [ Object(NonMatching, "dolphin/gx/GXInit.c"), Object(NonMatching, "dolphin/gx/GXFifo.c"), - Object(NonMatching, "dolphin/gx/GXAttr.c"), - Object(NonMatching, "dolphin/gx/GXMisc.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXAttr.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXMisc.c"), Object(NonMatching, "dolphin/gx/GXGeometry.c"), Object(NonMatching, "dolphin/gx/GXFrameBuf.c"), - Object(NonMatching, "dolphin/gx/GXLight.c"), - Object(NonMatching, "dolphin/gx/GXTexture.c"), - Object(NonMatching, "dolphin/gx/GXBump.c"), - Object(NonMatching, "dolphin/gx/GXTev.c"), - Object(NonMatching, "dolphin/gx/GXPixel.c"), - Object(NonMatching, "dolphin/gx/GXStubs.c"), - Object(NonMatching, "dolphin/gx/GXDisplayList.c"), - Object(NonMatching, "dolphin/gx/GXTransform.c"), - Object(NonMatching, "dolphin/gx/GXPerf.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXLight.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXTexture.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXBump.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXTev.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXPixel.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXStubs.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXDisplayList.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXTransform.c"), + Object(MatchingFor("GMPE01_00", "GMPE01_01"), "dolphin/gx/GXPerf.c"), ], ), DolphinLib( diff --git a/include/dolphin/gx/GXEnum.h b/include/dolphin/gx/GXEnum.h index d6fed014..d8c48579 100644 --- a/include/dolphin/gx/GXEnum.h +++ b/include/dolphin/gx/GXEnum.h @@ -901,7 +901,7 @@ typedef enum _GXAlphaReadMode { GX_READ_FF = 1, GX_READ_NONE = 2, -} _GXAlphaReadMode; +} GXAlphaReadMode; #ifdef __cplusplus } diff --git a/include/dolphin/gx/GXPriv.h b/include/dolphin/gx/GXPriv.h index ea3d2318..1cd42e37 100644 --- a/include/dolphin/gx/GXPriv.h +++ b/include/dolphin/gx/GXPriv.h @@ -1,7 +1,32 @@ #ifndef _DOLPHIN_GXPRIV #define _DOLPHIN_GXPRIV -#include "dolphin/gx/GXVert.h" +#include "dolphin/gx.h" + +#ifdef DEBUG +#define ASSERTLINE(line, cond) \ + ((cond) || (OSPanic(__FILE__, line, "Failed assertion " #cond), 0)) + +#define ASSERTMSGLINE(line, cond, msg) \ + ((cond) || (OSPanic(__FILE__, line, msg), 0)) + +// This is dumb but we dont have a Metrowerks way to do variadic macros in the macro to make this done in a not scrubby way. +#define ASSERTMSG1LINE(line, cond, msg, arg1) \ + ((cond) || (OSPanic(__FILE__, line, msg, arg1), 0)) + +#define ASSERTMSG2LINE(line, cond, msg, arg1, arg2) \ + ((cond) || (OSPanic(__FILE__, line, msg, arg1, arg2), 0)) + +#define ASSERTMSGLINEV(line, cond, ...) \ + ((cond) || (OSPanic(__FILE__, line, __VA_ARGS__), 0)) + +#else +#define ASSERTLINE(line, cond) (void)0 +#define ASSERTMSGLINE(line, cond, msg) (void)0 +#define ASSERTMSG1LINE(line, cond, msg, arg1) (void)0 +#define ASSERTMSG2LINE(line, cond, msg, arg1, arg2) (void)0 +#define ASSERTMSGLINEV(line, cond, ...) (void)0 +#endif typedef struct GXLightObjInt { u32 padding[3]; @@ -26,92 +51,137 @@ typedef struct GXLightObjInt { #define GX_FIFO_ADDR 0xCC008000 #define GX_WRITE_U8(v) (GXWGFifo.u8 = v) +#define GX_WRITE_U16(us) (GXWGFifo.u16 = (u16)(us)) #define GX_WRITE_U32(v) (GXWGFifo.u32 = v) +#define GX_WRITE_F32(f) (GXWGFifo.f32 = (f32)(f)) -typedef struct __GXData_struct { - u16 vNumNot; - u16 bpSentNot; - u16 vNum; - u16 vLim; - u32 cpEnable; - u32 cpStatus; - u32 cpClr; - u32 vcdLo; - u32 vcdHi; - u32 vatA[8]; - u32 vatB[8]; - u32 vatC[8]; - u32 lpSize; - u32 matIdxA; - u32 matIdxB; - u32 indexBase[4]; - u32 indexStride[4]; - u32 ambColor[2]; - u32 matColor[2]; - u32 suTs0[8]; - u32 suTs1[8]; - u32 suScis0; - u32 suScis1; - u32 tref[8]; - u32 iref; - u32 bpMask; - u32 IndTexScale0; - u32 IndTexScale1; - u32 tevc[16]; - u32 teva[16]; - u32 tevKsel[8]; - u32 cmode0; - u32 cmode1; - u32 zmode; - u32 peCtrl; - u32 cpDispSrc; - u32 cpDispSize; - u32 cpDispStride; - u32 cpDisp; - u32 cpTexSrc; - u32 cpTexSize; - u32 cpTexStride; - u32 cpTex; - GXBool cpTexZ; - u32 genMode; - GXTexRegion TexRegions[8]; - GXTexRegion TexRegionsCI[4]; - u32 nextTexRgn; - u32 nextTexRgnCI; - GXTlutRegion TlutRegions[20]; - GXTexRegion* (*texRegionCallback)(GXTexObj*, GXTexMapID); - GXTlutRegion* (*tlutRegionCallback)(u32); - GXAttrType nrmType; - GXBool hasNrms; - GXBool hasBiNrms; - u32 projType; - f32 projMtx[6]; - f32 vpLeft; - f32 vpTop; - f32 vpWd; - f32 vpHt; - f32 vpNearz; - f32 vpFarz; - u8 fgRange; - f32 fgSideX; - u32 tImage0[8]; - u32 tMode0[8]; - u32 texmapId[16]; - u32 tcsManEnab; - u32 tevTcEnab; - GXPerf0 perf0; - GXPerf1 perf1; - u32 perfSel; - GXBool inDispList; - GXBool dlSaveContext; - u8 dirtyVAT; - u32 dirtyState; -} GXData; +#if DEBUG +#define VERIF_XF_REG(addr, value) \ +do { \ + s32 regAddr = (addr); \ + if (regAddr >= 0 && regAddr < 0x50) { \ + __gxVerif->xfRegs[regAddr] = (value); \ + __gxVerif->xfRegsDirty[regAddr] = 1; \ + } \ +} while (0) +#define VERIF_XF_REG_alt(addr, value) \ +do { \ + s32 xfAddr = (addr); \ + if (xfAddr >= 0 && xfAddr < 0x50) { \ + __gxVerif->xfRegs[xfAddr] = (value); \ + __gxVerif->xfRegsDirty[xfAddr] = 1; \ + } \ +} while (0) +#define VERIF_RAS_REG(value) (__gxVerif->rasRegs[((value) & 0xFF000000) >> 24] = value) +#define VERIF_MTXLIGHT(addr, data) \ +do { \ + s32 xfAddr; \ + if (addr < 0x400U) { \ + __gxVerif->xfMtx[addr] = data; \ + __gxVerif->xfMtxDirty[addr] = 1; \ + } else if (addr < 0x500U) { \ + xfAddr = addr - 0x400; \ + __gxVerif->xfNrm[xfAddr] = data; \ + __gxVerif->xfNrmDirty[xfAddr] = 1; \ + } else if (addr < 0x600U) { \ + xfAddr = addr - 0x500; \ + __gxVerif->xfDMtx[xfAddr] = data; \ + __gxVerif->xfDMtxDirty[xfAddr] = 1; \ + } else if (addr < 0x680U) { \ + xfAddr = addr - 0x600; \ + __gxVerif->xfLight[xfAddr] = data; \ + __gxVerif->xfLightDirty[xfAddr] = 1; \ + } else { \ + xfAddr = addr - 0x1000; \ + if ((xfAddr >= 0) && (xfAddr < 0x50)) { \ + __gxVerif->xfRegs[xfAddr] = data; \ + __gxVerif->xfRegsDirty[xfAddr] = 1; \ + } \ + } \ +} while (0) +#else +#define VERIF_XF_REG(addr, value) ((void)0) +#define VERIF_XF_REG_alt(addr, value) ((void)0) +#define VERIF_RAS_REG(value) ((void)0) +#endif -extern GXData* gx; -// #define gx __GXData +#define GX_WRITE_XF_REG(addr, value) \ +do { \ + GX_WRITE_U8(0x10); \ + GX_WRITE_U32(0x1000 + (addr)); \ + GX_WRITE_U32(value); \ + VERIF_XF_REG(addr, value); \ +} while (0) -void __GXInitGX(); +#if DEBUG +#define GX_WRITE_XF_REG_2(addr, value) \ +do { \ + u32 xfData = (value); &xfData; \ + GX_WRITE_U32(value); \ + VERIF_XF_REG_alt(addr, xfData); \ +} while (0) +#define GX_WRITE_XF_REG_F(addr, value) \ +do { \ + f32 xfData = (value); \ + GX_WRITE_F32(value); \ + VERIF_XF_REG_alt(addr, *(u32 *)&xfData); \ +} while (0) +#else +#define GX_WRITE_XF_REG_2(addr, value) \ +do { \ + GX_WRITE_U32(value); \ +} while (0) +#define GX_WRITE_XF_REG_F(addr, value) \ +do { \ + GX_WRITE_F32(value); \ +} while (0) +#endif + +#define GX_WRITE_RAS_REG(value) \ +do { \ + GX_WRITE_U8(0x61); \ + GX_WRITE_U32(value); \ + VERIF_RAS_REG(value); \ +} while (0) + +#define GX_WRITE_SOME_REG2(a, b, c, addr) \ +do { \ + long regAddr; \ + GX_WRITE_U8(a); \ + GX_WRITE_U8(b); \ + GX_WRITE_U32(c); \ + regAddr = addr; \ + if (regAddr >= 0 && regAddr < 4) { \ + gx->indexBase[regAddr] = c; \ + } \ +} while (0) +#define GX_WRITE_SOME_REG3(a, b, c, addr) \ +do { \ + long regAddr; \ + GX_WRITE_U8(a); \ + GX_WRITE_U8(b); \ + GX_WRITE_U32(c); \ + regAddr = addr; \ + if (regAddr >= 0 && regAddr < 4) { \ + gx->indexStride[regAddr] = c; \ + } \ +} while (0) +#define GX_WRITE_SOME_REG4(a, b, c, addr) \ +do { \ + long regAddr; \ + GX_WRITE_U8(a); \ + GX_WRITE_U8(b); \ + GX_WRITE_U32(c); \ + regAddr = addr; \ +} while (0) + +#define GET_REG_FIELD(reg, size, shift) ((int)((reg) >> (shift)) & ((1 << (size)) - 1)) + +#define SET_REG_FIELD(line, reg, size, shift, val) \ +do { \ + ASSERTMSGLINE(line, ((u32)(val) & ~((1 << (size)) - 1)) == 0, "GX Internal: Register field out of range"); \ + (reg) = ((u32)(reg) & ~(((1 << (size)) - 1) << (shift))) | ((u32)(val) << (shift)); \ +} while (0) #define GX_REG_ASSERT(c) ASSERTMSG(c, "GX Internal: Register field out of range") @@ -358,4 +428,223 @@ void __GXInitGX(); #define GX_VAT_REG_B_UNK_SHIFT 31 #define GX_VAT_REG_B_UNK_MASK 0x80000000 +#define GX_GET_MEM_REG(offset) (*(volatile u16*)((volatile u16*)(__memReg) + (offset))) +#define GX_GET_CP_REG(offset) (*(volatile u16*)((volatile u16*)(__cpReg) + (offset))) +#define GX_GET_PE_REG(offset) (*(volatile u16*)((volatile u16*)(__peReg) + (offset))) +#define GX_GET_PI_REG(offset) (*(volatile u32*)((volatile u32*)(__piReg) + (offset))) + +#define GX_SET_MEM_REG(offset, val) (*(volatile u16*)((volatile u16*)(__memReg) + (offset)) = val) +#define GX_SET_CP_REG(offset, val) (*(volatile u16*)((volatile u16*)(__cpReg) + (offset)) = val) +#define GX_SET_PE_REG(offset, val) (*(volatile u16*)((volatile u16*)(__peReg) + (offset)) = val) +#define GX_SET_PI_REG(offset, val) (*(volatile u32*)((volatile u32*)(__piReg) + (offset)) = val) + +#define CHECK_GXBEGIN(line, name) ASSERTMSGLINE(line, !__GXinBegin, "'" name "' is not allowed between GXBegin/GXEnd") + +/* GXAttr.c */ + +void __GXSetVCD(void); +void __GXSetVAT(void); + +/* GXBump.c */ + +void __GXUpdateBPMask(void); +void __GXFlushTextureState(void); + +/* GXFifo.c */ + +// GXFifoObj private data +struct __GXFifoObj { + u8 *base; + u8 *top; + u32 size; + u32 hiWatermark; + u32 loWatermark; + void *rdPtr; + void *wrPtr; + s32 count; + u8 bind_cpu; + u8 bind_gp; +}; + +void __GXSaveCPUFifoAux(struct __GXFifoObj *realFifo); +void __GXFifoInit(void); +void __GXInsaneWatermark(void); +void __GXCleanGPFifo(void); + +/* GXGeometry.c */ + +void __GXSetDirtyState(void); +void __GXSendFlushPrim(void); +void __GXSetGenMode(void); + +/* GXInit.c */ +void __GXInitGX(); +void __GXInitRevisionBits(void); + +typedef struct __GXData_struct { + u16 vNumNot; + u16 bpSentNot; + u16 vNum; + u16 vLim; + u32 cpEnable; + u32 cpStatus; + u32 cpClr; + u32 vcdLo; + u32 vcdHi; + u32 vatA[8]; + u32 vatB[8]; + u32 vatC[8]; + u32 lpSize; + u32 matIdxA; + u32 matIdxB; + u32 indexBase[4]; + u32 indexStride[4]; + u32 ambColor[2]; + u32 matColor[2]; + u32 suTs0[8]; + u32 suTs1[8]; + u32 suScis0; + u32 suScis1; + u32 tref[8]; + u32 iref; + u32 bpMask; + u32 IndTexScale0; + u32 IndTexScale1; + u32 tevc[16]; + u32 teva[16]; + u32 tevKsel[8]; + u32 cmode0; + u32 cmode1; + u32 zmode; + u32 peCtrl; + u32 cpDispSrc; + u32 cpDispSize; + u32 cpDispStride; + u32 cpDisp; + u32 cpTexSrc; + u32 cpTexSize; + u32 cpTexStride; + u32 cpTex; + GXBool cpTexZ; + u32 genMode; + GXTexRegion TexRegions[8]; + GXTexRegion TexRegionsCI[4]; + u32 nextTexRgn; + u32 nextTexRgnCI; + GXTlutRegion TlutRegions[20]; + GXTexRegion* (*texRegionCallback)(GXTexObj*, GXTexMapID); + GXTlutRegion* (*tlutRegionCallback)(u32); + GXAttrType nrmType; + GXBool hasNrms; + GXBool hasBiNrms; + u32 projType; + f32 projMtx[6]; + f32 vpLeft; + f32 vpTop; + f32 vpWd; + f32 vpHt; + f32 vpNearz; + f32 vpFarz; + u8 fgRange; + f32 fgSideX; + u32 tImage0[8]; + u32 tMode0[8]; + u32 texmapId[16]; + u32 tcsManEnab; + u32 tevTcEnab; + GXPerf0 perf0; + GXPerf1 perf1; + u32 perfSel; + GXBool inDispList; + GXBool dlSaveContext; + u8 dirtyVAT; + u32 dirtyState; +} GXData; + +extern GXData* gx; +extern u16 *__memReg; +extern u16 *__peReg; +extern u16 *__cpReg; +extern u32 *__piReg; +// #define gx __GXData + +/* GXMisc.c */ + +void __GXBypass(u32 reg); +u16 __GXReadPEReg(u32 reg); +void __GXPEInit(void); +void __GXAbort(); + +/* GXPerf.c */ +void __GXSetBWDials(u16 cpDial, u16 tcDial, u16 peDial, u16 cpuRdDial, u16 cpuWrDial); + +static inline u32 __GXReadCPCounterU32(u32 regAddrL, u32 regAddrH) { + u32 ctrH0; + u32 ctrH1; + u32 ctrL; + + ctrH0 = GX_GET_CP_REG(regAddrH); + + do { + ctrH1 = ctrH0; + ctrL = GX_GET_CP_REG(regAddrL); + ctrH0 = GX_GET_CP_REG(regAddrH); + } while (ctrH0 != ctrH1); + + return (ctrH0 << 0x10) | ctrL; +} + +static inline u32 __GXReadMEMCounterU32(u32 regAddrL, u32 regAddrH) { + u32 ctrH0; + u32 ctrH1; + u32 ctrL; + + ctrH0 = GX_GET_MEM_REG(regAddrH); + + do { + ctrH1 = ctrH0; + ctrL = GX_GET_MEM_REG(regAddrL); + ctrH0 = GX_GET_MEM_REG(regAddrH); + } while (ctrH0 != ctrH1); + + return (ctrH0 << 0x10) | ctrL; +} + +static inline u32 __GXReadPECounterU32(u32 regAddrL, u32 regAddrH) { + u32 ctrH0; + u32 ctrH1; + u32 ctrL; + + ctrH0 = GX_GET_PE_REG(regAddrH); + + do { + ctrH1 = ctrH0; + ctrL = GX_GET_PE_REG(regAddrL); + ctrH0 = GX_GET_PE_REG(regAddrH); + } while (ctrH0 != ctrH1); + + return (ctrH0 << 0x10) | ctrL; +} + +/* GXSave.c */ + +void __GXShadowDispList(void *list, u32 nbytes); +void __GXShadowIndexState(u32 idx_reg, u32 reg_data); +void __GXPrintShadowState(void); + +/* GXStubs.c */ + +void __GXSetRange(float nearz, float fgSideX); + +/* GXTexture.c */ + +void __GetImageTileCount(GXTexFmt fmt, u16 wd, u16 ht, u32 *rowTiles, u32 *colTiles, u32 *cmpTiles); +void __GXSetSUTexRegs(void); +void __GXGetSUTexSize(GXTexCoordID coord, u16 *width, u16 *height); +void __GXSetTmemConfig(u32 config); + +/* GXTransform.c */ + +void __GXSetMatrixIndex(GXAttr matIdxAttr); + #endif // _DOLPHIN_GXPRIV diff --git a/include/dolphin/gx/GXStruct.h b/include/dolphin/gx/GXStruct.h index 4df23062..8b810140 100644 --- a/include/dolphin/gx/GXStruct.h +++ b/include/dolphin/gx/GXStruct.h @@ -72,6 +72,26 @@ typedef struct _GXTlutRegion { u32 dummy[4]; } GXTlutRegion; +typedef struct _GXFogAdjTable +{ + u16 r[10]; +} GXFogAdjTable; + +typedef enum _GXTlutSize +{ + GX_TLUT_16 = 1, + GX_TLUT_32 = 2, + GX_TLUT_64 = 4, + GX_TLUT_128 = 8, + GX_TLUT_256 = 16, + GX_TLUT_512 = 32, + GX_TLUT_1K = 64, + GX_TLUT_2K = 128, + GX_TLUT_4K = 256, + GX_TLUT_8K = 512, + GX_TLUT_16K = 1024, +} GXTlutSize; + typedef struct _GXVtxAttrFmtList { // total size: 0x10 GXAttr attr; // offset 0x0, size 0x4 diff --git a/include/dolphin/gx/GXTexture.h b/include/dolphin/gx/GXTexture.h index a30b7430..0b569528 100644 --- a/include/dolphin/gx/GXTexture.h +++ b/include/dolphin/gx/GXTexture.h @@ -8,29 +8,35 @@ extern "C" { #endif -typedef GXTexRegion* (*GXTexRegionCallback)(const GXTexObj* obj, GXTexMapID id); +typedef GXTexRegion *(*GXTexRegionCallback)(GXTexObj *t_obj, GXTexMapID id); +typedef GXTlutRegion *(*GXTlutRegionCallback)(u32 idx); -void GXInitTexObj(GXTexObj* obj, const void* data, u16 width, u16 height, u32 format, - GXTexWrapMode wrapS, GXTexWrapMode wrapT, GXBool mipmap); -void GXInitTexObjCI(GXTexObj* obj, const void* data, u16 width, u16 height, GXCITexFmt format, - GXTexWrapMode wrapS, GXTexWrapMode wrapT, GXBool mipmap, u32 tlut); -void GXInitTexObjData(GXTexObj* obj, const void* data); -void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter min_filt, GXTexFilter mag_filt, f32 min_lod, - f32 max_lod, f32 lod_bias, GXBool bias_clamp, GXBool do_edge_lod, - GXAnisotropy max_aniso); -void GXLoadTexObj(GXTexObj* obj, GXTexMapID id); -u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, GXBool mipmap, u8 max_lod); -void GXInvalidateTexAll(); -void GXInitTexObjWrapMode(GXTexObj* obj, GXTexWrapMode s, GXTexWrapMode t); -void GXInitTlutObj(GXTlutObj* obj, void* data, GXTlutFmt format, u16 entries); -void GXLoadTlut(const GXTlutObj* obj, GXTlut idx); -void GXSetTexCoordScaleManually(GXTexCoordID coord, GXBool enable, u16 ss, u16 ts); -void GXInitTexCacheRegion(GXTexRegion* region, GXBool is_32b_mipmap, u32 tmem_even, - GXTexCacheSize size_even, u32 tmem_odd, GXTexCacheSize size_odd); -GXTexRegionCallback GXSetTexRegionCallback(GXTexRegionCallback callback); -void GXInvalidateTexRegion(const GXTexRegion* region); - -void GXSetTexCoordScaleManually(GXTexCoordID coord, GXBool enable, u16 ss, u16 ts); +u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, u8 mipmap, u8 max_lod); +void GXInitTexObj(GXTexObj *obj, void *image_ptr, u16 width, u16 height, GXTexFmt format, GXTexWrapMode wrap_s, GXTexWrapMode wrap_t, u8 mipmap); +void GXInitTexObjCI(GXTexObj *obj, void *image_ptr, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrap_s, GXTexWrapMode wrap_t, u8 mipmap, u32 tlut_name); +void GXInitTexObjLOD(GXTexObj *obj, GXTexFilter min_filt, GXTexFilter mag_filt, + f32 min_lod, f32 max_lod, f32 lod_bias, GXBool bias_clamp, + GXBool do_edge_lod, GXAnisotropy max_aniso); +void GXInitTexObjData(GXTexObj *obj, void *image_ptr); +void GXInitTexObjWrapMode(GXTexObj *obj, GXTexWrapMode s, GXTexWrapMode t); +void GXInitTexObjTlut(GXTexObj *obj, u32 tlut_name); +void GXInitTexObjUserData(GXTexObj *obj, void *user_data); +void *GXGetTexObjUserData(const GXTexObj *obj); +void GXLoadTexObjPreLoaded(GXTexObj *obj, GXTexRegion *region, GXTexMapID id); +void GXLoadTexObj(GXTexObj *obj, GXTexMapID id); +void GXInitTlutObj(GXTlutObj *tlut_obj, void *lut, GXTlutFmt fmt, u16 n_entries); +void GXLoadTlut(GXTlutObj *tlut_obj, u32 tlut_name); +void GXInitTexCacheRegion(GXTexRegion *region, u8 is_32b_mipmap, u32 tmem_even, GXTexCacheSize size_even, u32 tmem_odd, GXTexCacheSize size_odd); +void GXInitTexPreLoadRegion(GXTexRegion *region, u32 tmem_even, u32 size_even, u32 tmem_odd, u32 size_odd); +void GXInitTlutRegion(GXTlutRegion *region, u32 tmem_addr, GXTlutSize tlut_size); +void GXInvalidateTexRegion(GXTexRegion *region); +void GXInvalidateTexAll(void); +GXTexRegionCallback GXSetTexRegionCallback(GXTexRegionCallback f); +GXTlutRegionCallback GXSetTlutRegionCallback(GXTlutRegionCallback f); +void GXPreLoadEntireTexture(GXTexObj *tex_obj, GXTexRegion *region); +void GXSetTexCoordScaleManually(GXTexCoordID coord, u8 enable, u16 ss, u16 ts); +void GXSetTexCoordCylWrap(GXTexCoordID coord, u8 s_enable, u8 t_enable); +void GXSetTexCoordBias(GXTexCoordID coord, u8 s_enable, u8 t_enable); #ifdef __cplusplus } #endif diff --git a/src/dolphin/gx/GXAttr.c b/src/dolphin/gx/GXAttr.c new file mode 100644 index 00000000..721027db --- /dev/null +++ b/src/dolphin/gx/GXAttr.c @@ -0,0 +1,586 @@ +#include +#include + +#include + +#define CHECK_ATTRPTR(line, attrPtr) ASSERTMSGLINE(line, (attrPtr) != NULL, "GXSetVtxDescv: attrPtr is NULL") +#define CHECK_ATTRNAME(line, attr) ASSERTMSGLINE(line, (attr) >= GX_VA_PNMTXIDX && (attr) < GX_VA_MAX_ATTR, "GXSetVtxDesc: Invalid vertex attribute name") +#define CHECK_ATTRNAME2(line, attr) ASSERTMSGLINE(line, (attr) >= GX_VA_POS && (attr) <= GX_VA_MAX_ATTR, "GXSetVtxAttrFmt: Invalid vertex attribute name") +#define CHECK_ATTRNAME3(line, attr) ASSERTMSGLINE(line, (attr) >= GX_VA_POS && (attr) <= GX_LIGHT_ARRAY, "GXSetArray: Invalid vertex attribute name") +#define CHECK_ATTRTYPE(line, type) ASSERTMSGLINE(line, (type) >= GX_NONE && (type) <= GX_INDEX16, "GXSetVtxDesc: Invalid vertex attribute type") +#define CHECK_VTXFMT(line, vtxfmt) ASSERTMSGLINE(line, (vtxfmt) < GX_MAX_VTXFMT, "GXSetVtxAttrFmt: Format Index is out of range") +#define CHECK_FRAC(line, frac) ASSERTMSGLINE(line, (frac) < 32, "GXSetVtxAttrFmt: Frac value is >= 32") +#define CHECK_LISTPTR(line, list) ASSERTMSGLINE(line, (list) != NULL, "GXSetVtxAttrFmt: list pointer is NULL") + +static void __GXXfVtxSpecs(void) +{ + u32 nCols = 0; + u32 nNrm; + u32 nTex; + u32 reg; + + nCols = GET_REG_FIELD(gx->vcdLo, 2, 13) ? 1 : 0; + nCols += GET_REG_FIELD(gx->vcdLo, 2, 15) ? 1 : 0; + nNrm = gx->hasBiNrms ? 2 : gx->hasNrms ? 1 : 0; + nTex = 0; + nTex += GET_REG_FIELD(gx->vcdHi, 2, 0) ? 1 : 0; + nTex += GET_REG_FIELD(gx->vcdHi, 2, 2) ? 1 : 0; + nTex += GET_REG_FIELD(gx->vcdHi, 2, 4) ? 1 : 0; + nTex += GET_REG_FIELD(gx->vcdHi, 2, 6) ? 1 : 0; + nTex += GET_REG_FIELD(gx->vcdHi, 2, 8) ? 1 : 0; + nTex += GET_REG_FIELD(gx->vcdHi, 2, 10) ? 1 : 0; + nTex += GET_REG_FIELD(gx->vcdHi, 2, 12) ? 1 : 0; + nTex += GET_REG_FIELD(gx->vcdHi, 2, 14) ? 1 : 0; + reg = (nCols) | (nNrm << 2) | (nTex << 4); + GX_WRITE_XF_REG(8, reg); + gx->bpSentNot = 1; +} + +static inline void SETVCDATTR(GXAttr Attr, GXAttrType Type) +{ + switch (Attr) { + case GX_VA_PNMTXIDX: SET_REG_FIELD(0xD4, gx->vcdLo, 1, 0, Type); break; + case GX_VA_TEX0MTXIDX: SET_REG_FIELD(0xD5, gx->vcdLo, 1, 1, Type); break; + case GX_VA_TEX1MTXIDX: SET_REG_FIELD(0xD6, gx->vcdLo, 1, 2, Type); break; + case GX_VA_TEX2MTXIDX: SET_REG_FIELD(0xD7, gx->vcdLo, 1, 3, Type); break; + case GX_VA_TEX3MTXIDX: SET_REG_FIELD(0xD8, gx->vcdLo, 1, 4, Type); break; + case GX_VA_TEX4MTXIDX: SET_REG_FIELD(0xD9, gx->vcdLo, 1, 5, Type); break; + case GX_VA_TEX5MTXIDX: SET_REG_FIELD(0xDA, gx->vcdLo, 1, 6, Type); break; + case GX_VA_TEX6MTXIDX: SET_REG_FIELD(0xDB, gx->vcdLo, 1, 7, Type); break; + case GX_VA_TEX7MTXIDX: SET_REG_FIELD(0xDC, gx->vcdLo, 1, 8, Type); break; + case GX_VA_POS: SET_REG_FIELD(0xDD, gx->vcdLo, 2, 9, Type); break; + case GX_VA_NRM: + if (Type != GX_NONE) { + gx->hasNrms = 1; + gx->hasBiNrms = 0; + gx->nrmType = Type; + } else { + gx->hasNrms = 0; + } + break; + case GX_VA_NBT: + if (Type != GX_NONE) { + gx->hasBiNrms = 1; + gx->hasNrms = 0; + gx->nrmType = Type; + } else { + gx->hasBiNrms = 0; + } + break; + case GX_VA_CLR0: SET_REG_FIELD(0xF6, gx->vcdLo, 2, 13, Type); break; + case GX_VA_CLR1: SET_REG_FIELD(0xF7, gx->vcdLo, 2, 15, Type); break; + case GX_VA_TEX0: SET_REG_FIELD(0xF8, gx->vcdHi, 2, 0, Type); break; + case GX_VA_TEX1: SET_REG_FIELD(0xF9, gx->vcdHi, 2, 2, Type); break; + case GX_VA_TEX2: SET_REG_FIELD(0xFA, gx->vcdHi, 2, 4, Type); break; + case GX_VA_TEX3: SET_REG_FIELD(0xFB, gx->vcdHi, 2, 6, Type); break; + case GX_VA_TEX4: SET_REG_FIELD(0xFC, gx->vcdHi, 2, 8, Type); break; + case GX_VA_TEX5: SET_REG_FIELD(0xFD, gx->vcdHi, 2, 10, Type); break; + case GX_VA_TEX6: SET_REG_FIELD(0xFE, gx->vcdHi, 2, 12, Type); break; + case GX_VA_TEX7: SET_REG_FIELD(0xFF, gx->vcdHi, 2, 14, Type); break; + } +} + +void GXSetVtxDesc(GXAttr attr, GXAttrType type) +{ + CHECK_GXBEGIN(0xCC, "GXSetVtxDesc"); + CHECK_ATTRNAME(0xCF, attr); + CHECK_ATTRTYPE(0xD1, type); + + SETVCDATTR(attr, type); + if (gx->hasNrms || gx->hasBiNrms) { + SET_REG_FIELD(0xD7, gx->vcdLo, 2, 11, gx->nrmType); + } else { + SET_REG_FIELD(0x00, gx->vcdLo, 2, 11, 0); + } + gx->dirtyState |= 8; +} + +void GXSetVtxDescv(GXVtxDescList *attrPtr) +{ + CHECK_GXBEGIN(0xF5, "GXSetVtxDescv"); + CHECK_ATTRPTR(0xF6, attrPtr); + while (attrPtr->attr != 0xFF) { + CHECK_ATTRNAME(0xFB, attrPtr->attr); + CHECK_ATTRTYPE(0xFE, attrPtr->type); + SETVCDATTR(attrPtr->attr, attrPtr->type); + attrPtr++; + } + if (gx->hasNrms || gx->hasBiNrms) { + SET_REG_FIELD(0x107, gx->vcdLo, 2, 11, gx->nrmType); + } else { + SET_REG_FIELD(0x107, gx->vcdLo, 2, 11, 0); + } + gx->dirtyState |= 8; +} + +void __GXSetVCD(void) +{ + GX_WRITE_SOME_REG4(8, 0x50, gx->vcdLo, -12); + GX_WRITE_SOME_REG4(8, 0x60, gx->vcdHi, -12); + __GXXfVtxSpecs(); +} + +void __GXCalculateVLim() { + static u8 tbl1[] = { 0, 4, 1, 2 }; + static u8 tbl2[] = { 0, 8, 1, 2 }; + static u8 tbl3[] = { 0, 12, 1, 2 }; + + GXCompCnt nc = 0; + unsigned long vlm; + unsigned long b; + unsigned long vl; + unsigned long vh; + unsigned long va; + + if (gx->vNum != 0) { + vl = gx->vcdLo; + vh = gx->vcdHi; + va = gx->vatA[0]; + nc = GET_REG_FIELD(va, 1, 9); + + vlm = GET_REG_FIELD(vl, 1, 0); + vlm += (u8)GET_REG_FIELD(vl, 1, 1); + vlm += (u8)GET_REG_FIELD(vl, 1, 2); + vlm += (u8)GET_REG_FIELD(vl, 1, 3); + vlm += (u8)GET_REG_FIELD(vl, 1, 4); + vlm += (u8)GET_REG_FIELD(vl, 1, 5); + vlm += (u8)GET_REG_FIELD(vl, 1, 6); + vlm += (u8)GET_REG_FIELD(vl, 1, 7); + vlm += (u8)GET_REG_FIELD(vl, 1, 8); + vlm += tbl3[(u8)GET_REG_FIELD(vl, 2, 9)]; + + if (nc == 1) { + b = 3; + } else { + b = 1; + } + + vlm += tbl3[(u8)GET_REG_FIELD(vl, 2, 11)] * b; + vlm += tbl1[(u8)GET_REG_FIELD(vl, 2, 13)]; + vlm += tbl1[(u8)GET_REG_FIELD(vl, 2, 15)]; + vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 0)]; + vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 2)]; + vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 4)]; + vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 6)]; + vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 8)]; + vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 10)]; + vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 12)]; + vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 14)]; + gx->vLim = vlm; + } +} + +void GXGetVtxDesc(GXAttr attr, GXAttrType *type) +{ + u32 cpType; + + CHECK_GXBEGIN(0x185, "GXGetVtxDesc"); + CHECK_ATTRNAME(0x187, attr); + + switch (attr) { + case GX_VA_PNMTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 0); break; + case GX_VA_TEX0MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 1); break; + case GX_VA_TEX1MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 2); break; + case GX_VA_TEX2MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 3); break; + case GX_VA_TEX3MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 4); break; + case GX_VA_TEX4MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 5); break; + case GX_VA_TEX5MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 6); break; + case GX_VA_TEX6MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 7); break; + case GX_VA_TEX7MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 8); break; + case GX_VA_POS: cpType = GET_REG_FIELD(gx->vcdLo, 2, 9); break; + case GX_VA_NRM: cpType = gx->hasNrms ? GET_REG_FIELD(gx->vcdLo, 2, 11) : 0; break; + case GX_VA_NBT: cpType = gx->hasBiNrms ? GET_REG_FIELD(gx->vcdLo, 2, 11) : 0; break; + case GX_VA_CLR0: cpType = GET_REG_FIELD(gx->vcdLo, 2, 13); break; + case GX_VA_CLR1: cpType = GET_REG_FIELD(gx->vcdLo, 2, 15); break; + case GX_VA_TEX0: cpType = GET_REG_FIELD(gx->vcdHi, 2, 0); break; + case GX_VA_TEX1: cpType = GET_REG_FIELD(gx->vcdHi, 2, 2); break; + case GX_VA_TEX2: cpType = GET_REG_FIELD(gx->vcdHi, 2, 4); break; + case GX_VA_TEX3: cpType = GET_REG_FIELD(gx->vcdHi, 2, 6); break; + case GX_VA_TEX4: cpType = GET_REG_FIELD(gx->vcdHi, 2, 8); break; + case GX_VA_TEX5: cpType = GET_REG_FIELD(gx->vcdHi, 2, 10); break; + case GX_VA_TEX6: cpType = GET_REG_FIELD(gx->vcdHi, 2, 12); break; + case GX_VA_TEX7: cpType = GET_REG_FIELD(gx->vcdHi, 2, 14); break; + default: cpType = 0; break; + } + *type = cpType; +} + +void GXGetVtxDescv(GXVtxDescList *vcd) +{ + GXAttr attr; + + CHECK_GXBEGIN(0x1BA, "GXGetVtxDescv"); + CHECK_ATTRPTR(0x1BC, vcd); + for (attr = 0; attr < GX_VA_MAX_ATTR; attr++) { + vcd[attr].attr = attr; + GXGetVtxDesc(attr, &vcd[attr].type); + } + vcd[attr].attr = 0xFF; +} + +void GXClearVtxDesc(void) +{ + CHECK_GXBEGIN(0x1D3, "GXClearVtxDesc"); + gx->vcdLo = 0; + SET_REG_FIELD(0x00, gx->vcdLo, 2, 9, 1); + gx->vcdHi = 0; + gx->hasNrms = 0; + gx->hasBiNrms = 0; + gx->dirtyState |= 8; +} + +static inline void SETVAT(u32 *va, u32 *vb, u32 *vc, GXAttr attr, GXCompCnt cnt, GXCompType type, u8 shft) +{ + switch (attr) { + case GX_VA_POS: + SET_REG_FIELD(511, *va, 1, 0, cnt); + SET_REG_FIELD(512, *va, 3, 1, type); + SET_REG_FIELD(513, *va, 5, 4, shft); + break; + case GX_VA_NRM: + case GX_VA_NBT: + SET_REG_FIELD(521, *va, 3, 10, type); + if (cnt == GX_NRM_NBT3) { + SET_REG_FIELD(0, *va, 1, 9, 1); + SET_REG_FIELD(0, *va, 1, 31, 1); + } else { + SET_REG_FIELD(527, *va, 1, 9, cnt); + SET_REG_FIELD(528, *va, 1, 31, 0); + } + break; + case GX_VA_CLR0: + SET_REG_FIELD(0x215, *va, 1, 13, cnt); + SET_REG_FIELD(0x216, *va, 3, 14, type); + break; + case GX_VA_CLR1: + SET_REG_FIELD(0x219, *va, 1, 0x11, cnt); + SET_REG_FIELD(0x21A, *va, 3, 18, type); + break; + case GX_VA_TEX0: + SET_REG_FIELD(0x21D, *va, 1, 0x15, cnt); + SET_REG_FIELD(0x21E, *va, 3, 0x16, type); + SET_REG_FIELD(0x21F, *va, 5, 0x19, shft); + break; + case GX_VA_TEX1: + SET_REG_FIELD(0x222, *vb, 1, 0, cnt); + SET_REG_FIELD(0x223, *vb, 3, 1, type); + SET_REG_FIELD(0x224, *vb, 5, 4, shft); + break; + case GX_VA_TEX2: + SET_REG_FIELD(0x227, *vb, 1, 9, cnt); + SET_REG_FIELD(0x228, *vb, 3, 10, type); + SET_REG_FIELD(0x229, *vb, 5, 13, shft); + break; + case GX_VA_TEX3: + SET_REG_FIELD(0x22C, *vb, 1, 18, cnt); + SET_REG_FIELD(0x22D, *vb, 3, 19, type); + SET_REG_FIELD(0x22E, *vb, 5, 22, shft); + break; + case GX_VA_TEX4: + SET_REG_FIELD(0x231, *vb, 1, 27, cnt); + SET_REG_FIELD(0x232, *vb, 3, 28, type); + SET_REG_FIELD(0x233, *vc, 5, 0, shft); + break; + case GX_VA_TEX5: + SET_REG_FIELD(0x236, *vc, 1, 5, cnt); + SET_REG_FIELD(0x237, *vc, 3, 6, type); + SET_REG_FIELD(0x238, *vc, 5, 9, shft); + break; + case GX_VA_TEX6: + SET_REG_FIELD(0x23B, *vc, 1, 14, cnt); + SET_REG_FIELD(0x23C, *vc, 3, 15, type); + SET_REG_FIELD(0x23D, *vc, 5, 18, shft); + break; + case GX_VA_TEX7: + SET_REG_FIELD(0x240, *vc, 1, 23, cnt); + SET_REG_FIELD(0x241, *vc, 3, 24, type); + SET_REG_FIELD(0x242, *vc, 5, 27, shft); + break; + } +} + +void GXSetVtxAttrFmt(GXVtxFmt vtxfmt, GXAttr attr, GXCompCnt cnt, GXCompType type, u8 frac) +{ + u32 *va; + u32 *vb; + u32 *vc; + + CHECK_GXBEGIN(0x252, "GXSetVtxAttrFmt"); + CHECK_VTXFMT(0x253, vtxfmt); + CHECK_ATTRNAME2(0x255, attr); + CHECK_FRAC(0x256, frac); + va = &gx->vatA[vtxfmt]; + vb = &gx->vatB[vtxfmt]; + vc = &gx->vatC[vtxfmt]; + SETVAT(va, vb, vc, attr, cnt, type, frac); + gx->dirtyState |= 0x10; + gx->dirtyVAT |= (u8)(1 << (u8)vtxfmt); +} + +void GXSetVtxAttrFmtv(GXVtxFmt vtxfmt, const GXVtxAttrFmtList *list) +{ + u32 *va; + u32 *vb; + u32 *vc; + + CHECK_GXBEGIN(0x27B, "GXSetVtxAttrFmtv"); + CHECK_LISTPTR(0x27C, list); + CHECK_VTXFMT(0x27D, vtxfmt); + va = &gx->vatA[vtxfmt]; + vb = &gx->vatB[vtxfmt]; + vc = &gx->vatC[vtxfmt]; + while (list->attr != GX_VA_NULL) { + CHECK_ATTRNAME2(0x286, list->attr); + CHECK_FRAC(0x287, list->frac); + SETVAT(va, vb, vc, list->attr, list->cnt, list->type, list->frac); + list++; + } + gx->dirtyState |= 0x10; + gx->dirtyVAT |= (u8)(1 << (u8)vtxfmt); +} + +void __GXSetVAT(void) +{ + u8 i; + + for (i = 0; i < 8; i++) { + if (gx->dirtyVAT & (1 << (u8)i)) { + GX_WRITE_SOME_REG4(8, i | 0x70, gx->vatA[i], i - 12); + GX_WRITE_SOME_REG4(8, i | 0x80, gx->vatB[i], i - 12); + GX_WRITE_SOME_REG4(8, i | 0x90, gx->vatC[i], i - 12); + } + } + gx->dirtyVAT = 0; +} + +void GXGetVtxAttrFmt(GXVtxFmt fmt, GXAttr attr, GXCompCnt *cnt, GXCompType *type, u8 *frac) +{ + u32 *va; + u32 *vb; + u32 *vc; + + CHECK_GXBEGIN(0x2CF, "GXGetVtxAttrFmt"); + CHECK_VTXFMT(0x2D0, fmt); + va = &gx->vatA[fmt]; + vb = &gx->vatB[fmt]; + vc = &gx->vatC[fmt]; + switch (attr) { + case GX_VA_POS: + *cnt = GET_REG_FIELD(*va, 1, 0); + *type = GET_REG_FIELD(*va, 3, 1); + *frac = (u8)(*va >> 4) & 0x1F; // GET_REG_FIELD(*va, 5, 4) + return; + case GX_VA_NRM: + case GX_VA_NBT: + *cnt = GET_REG_FIELD(*va, 1, 9); + if (*cnt == GX_TEX_ST && (u8)(*va >> 0x1F) != 0) { + *cnt = GX_NRM_NBT3; + } + *type = GET_REG_FIELD(*va, 3, 10); + *frac = 0; + return; + case GX_VA_CLR0: + *cnt = GET_REG_FIELD(*va, 1, 13); + *type = GET_REG_FIELD(*va, 3, 14); + *frac = 0; + return; + case GX_VA_CLR1: + *cnt = GET_REG_FIELD(*va, 1, 17); + *type = GET_REG_FIELD(*va, 3, 18); + *frac = 0; + return; + case GX_VA_TEX0: + *cnt = GET_REG_FIELD(*va, 1, 21); + *type = GET_REG_FIELD(*va, 3, 22); + *frac = (u8)(*va >> 0x19U) & 0x1F; + return; + case GX_VA_TEX1: + *cnt = GET_REG_FIELD(*vb, 1, 0); + *type = GET_REG_FIELD(*vb, 3, 1); + *frac = (u8)(*vb >> 4U) & 0x1F; + return; + case GX_VA_TEX2: + *cnt = GET_REG_FIELD(*vb, 1, 9); + *type = GET_REG_FIELD(*vb, 3, 10); + *frac = (u8)(*vb >> 0xDU) & 0x1F; + return; + case GX_VA_TEX3: + *cnt = GET_REG_FIELD(*vb, 1, 18); + *type = GET_REG_FIELD(*vb, 3, 19); + *frac = (u8)(*vb >> 0x16U) & 0x1F; + return; + case GX_VA_TEX4: + *cnt = GET_REG_FIELD(*vb, 1, 27); + *type = GET_REG_FIELD(*vb, 3, 28); + *frac = GET_REG_FIELD(*vc, 5, 0); + return; + case GX_VA_TEX5: + *cnt = GET_REG_FIELD(*vc, 1, 5); + *type = GET_REG_FIELD(*vc, 3, 6); + *frac = (u8)(*vc >> 9U) & 0x1F; + return; + case GX_VA_TEX6: + *cnt = GET_REG_FIELD(*vc, 1, 14); + *type = GET_REG_FIELD(*vc, 3, 15); + *frac = (u8)(*vc >> 0x12) & 0x1F; + return; + case GX_VA_TEX7: + *cnt = GET_REG_FIELD(*vc, 1, 23); + *type = GET_REG_FIELD(*vc, 3, 24); + *frac = (int)(*vc >> 0x1BU); + return; + default: + *cnt = GX_TEX_ST; + *type = GX_RGB565; + *frac = 0; + return; + } +} + +void GXGetVtxAttrFmtv(GXVtxFmt fmt, GXVtxAttrFmtList *vat) +{ + GXAttr attr; + + CHECK_GXBEGIN(0x330, "GXGetVtxAttrFmtv"); + CHECK_LISTPTR(0x331, vat); + CHECK_VTXFMT(0x332, fmt); + for (attr = GX_VA_POS; attr < GX_VA_MAX_ATTR; attr++) { + vat->attr = attr; + GXGetVtxAttrFmt(fmt, attr, &vat->cnt, &vat->type, &vat->frac); + vat++; + } + vat->attr = GX_VA_NULL; +} + +void GXSetArray(GXAttr attr, const void *base_ptr, u8 stride) +{ + GXAttr cpAttr; + unsigned long phyAddr; + + attr; // needed to match + + CHECK_GXBEGIN(0x34F, "GXSetArray"); + if (attr == GX_VA_NBT) { + attr = GX_VA_NRM; + } + CHECK_ATTRNAME3(0x352, attr); + cpAttr = attr - GX_VA_POS; + phyAddr = (u32)base_ptr & 0x3FFFFFFF; + GX_WRITE_SOME_REG2(8, cpAttr | 0xA0, phyAddr, cpAttr - 12); + GX_WRITE_SOME_REG3(8, cpAttr | 0xB0, stride, cpAttr - 12); +} + +void GXInvalidateVtxCache(void) +{ + CHECK_GXBEGIN(0x368, "GXInvalidateVtxCache"); + GX_WRITE_U8(0x48); +} + +void GXSetTexCoordGen2(GXTexCoordID dst_coord, GXTexGenType func, GXTexGenSrc src_param, u32 mtx, GXBool normalize, u32 pt_texmtx) +{ + u32 reg = 0; + u32 row; + u32 bumprow; // unused + u32 form; + GXAttr mtxIdAttr; + + CHECK_GXBEGIN(0x392, "GXSetTexCoordGen"); + ASSERTMSGLINE(0x393, dst_coord < 8, "GXSetTexCoordGen: Invalid coordinate Id"); + form = 0; + row = 5; + switch (src_param) { + case GX_TG_POS: row = 0; form = 1; break; + case GX_TG_NRM: row = 1; form = 1; break; + case GX_TG_BINRM: row = 3; form = 1; break; + case GX_TG_TANGENT: row = 4; form = 1; break; + case GX_TG_COLOR0: row = 2; break; + case GX_TG_COLOR1: row = 2; break; + case GX_TG_TEX0: row = 5; break; + case GX_TG_TEX1: row = 6; break; + case GX_TG_TEX2: row = 7; break; + case GX_TG_TEX3: row = 8; break; + case GX_TG_TEX4: row = 9; break; + case GX_TG_TEX5: row = 10; break; + case GX_TG_TEX6: row = 11; break; + case GX_TG_TEX7: row = 12; break; + case GX_TG_TEXCOORD0: bumprow; break; + case GX_TG_TEXCOORD1: bumprow; break; + case GX_TG_TEXCOORD2: bumprow; break; + case GX_TG_TEXCOORD3: bumprow; break; + case GX_TG_TEXCOORD4: bumprow; break; + case GX_TG_TEXCOORD5: bumprow; break; + case GX_TG_TEXCOORD6: bumprow; break; + default: + ASSERTMSGLINE(0x3AF, 0, "GXSetTexCoordGen: Invalid source parameter"); + break; + } + switch (func) + { + case GX_TG_MTX2x4: + SET_REG_FIELD(0x3B8, reg, 1, 1, 0); + SET_REG_FIELD(0x3B9, reg, 1, 2, form); + SET_REG_FIELD(0x3BA, reg, 3, 4, 0); + SET_REG_FIELD(0x3BB, reg, 5, 7, row); + break; + case GX_TG_MTX3x4: + SET_REG_FIELD(0x3BF, reg, 1, 1, 1); + SET_REG_FIELD(0x3C0, reg, 1, 2, form); + SET_REG_FIELD(0x3C1, reg, 3, 4, 0); + SET_REG_FIELD(0x3C2, reg, 5, 7, row); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + ASSERTMSGLINE(0x3CF, src_param >= 12 && src_param <= 18, "GXSetTexCoordGen: Bump source texture value is invalid"); + SET_REG_FIELD(0x3D0, reg, 1, 1, 0); + SET_REG_FIELD(0x3D1, reg, 1, 2, form); + SET_REG_FIELD(0x3D2, reg, 3, 4, 1); + SET_REG_FIELD(0x3D3, reg, 5, 7, row); + SET_REG_FIELD(0x3D4, reg, 3, 12, src_param - 12); + SET_REG_FIELD(0x3D5, reg, 3, 15, func - 2); + break; + case GX_TG_SRTG: + SET_REG_FIELD(0x3D9, reg, 1, 1, 0); + SET_REG_FIELD(0x3DA, reg, 1, 2, form); + if (src_param == GX_TG_COLOR0) { + SET_REG_FIELD(0, reg, 3, 4, 2); + } else { + SET_REG_FIELD(0, reg, 3, 4, 3); + } + SET_REG_FIELD(0, reg, 5, 7, 2); + break; + default: + ASSERTMSGLINE(0x3E5, 0, "GXSetTexCoordGen: Invalid function"); + break; + } + GX_WRITE_XF_REG(dst_coord + 0x40, reg); + reg = 0; + SET_REG_FIELD(0x3F8, reg, 6, 0, pt_texmtx - 64); + SET_REG_FIELD(0x3F9, reg, 1, 8, normalize); + GX_WRITE_XF_REG(dst_coord + 0x50, reg); + switch (dst_coord) { + case GX_TEXCOORD0: SET_REG_FIELD(0x402, gx->matIdxA, 6, 6, mtx); break; + case GX_TEXCOORD1: SET_REG_FIELD(0x403, gx->matIdxA, 6, 12, mtx); break; + case GX_TEXCOORD2: SET_REG_FIELD(0x404, gx->matIdxA, 6, 18, mtx); break; + case GX_TEXCOORD3: SET_REG_FIELD(0x405, gx->matIdxA, 6, 24, mtx); break; + case GX_TEXCOORD4: SET_REG_FIELD(0x406, gx->matIdxB, 6, 0, mtx); break; + case GX_TEXCOORD5: SET_REG_FIELD(0x407, gx->matIdxB, 6, 6, mtx); break; + case GX_TEXCOORD6: SET_REG_FIELD(0x408, gx->matIdxB, 6, 12, mtx); break; + default: SET_REG_FIELD(0x409, gx->matIdxB, 6, 18, mtx); break; + } + mtxIdAttr = dst_coord + 1; + __GXSetMatrixIndex(mtxIdAttr); +} + +void GXSetNumTexGens(u8 nTexGens) +{ + CHECK_GXBEGIN(0x41B, "GXSetNumTexGens"); + SET_REG_FIELD(0x41D, gx->genMode, 4, 0, nTexGens); + GX_WRITE_XF_REG(0x3F, nTexGens); + gx->dirtyState |= 4; +} diff --git a/src/dolphin/gx/GXBump.c b/src/dolphin/gx/GXBump.c new file mode 100644 index 00000000..910370d8 --- /dev/null +++ b/src/dolphin/gx/GXBump.c @@ -0,0 +1,335 @@ +#include +#include + +#include + +#if DEBUG +#define GX_WRITE_SOME_REG5(a, b) \ + do { \ + GX_WRITE_U8(a); \ + GX_WRITE_U32(b); \ + __gxVerif->rasRegs[(b >> 24) & 0xFF] = b; \ + } while (0) +#else +#define GX_WRITE_SOME_REG5(a, b) \ + do { \ + GX_WRITE_U8(a); \ + GX_WRITE_U32(b); \ + } while (0) +#endif + +void GXSetTevIndirect(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexFormat format, GXIndTexBiasSel bias_sel, GXIndTexMtxID matrix_sel, + GXIndTexWrap wrap_s, GXIndTexWrap wrap_t, GXBool add_prev, GXBool utc_lod, GXIndTexAlphaSel alpha_sel) +{ + u32 reg; + + CHECK_GXBEGIN(0x92, "GXInitIndTexture"); + reg = 0; + SET_REG_FIELD(0x81, reg, 2, 0, ind_stage); + SET_REG_FIELD(0x82, reg, 2, 2, format); + SET_REG_FIELD(0x83, reg, 3, 4, bias_sel); + SET_REG_FIELD(0x84, reg, 2, 7, alpha_sel); + SET_REG_FIELD(0x85, reg, 4, 9, matrix_sel); + SET_REG_FIELD(0x86, reg, 3, 13, wrap_s); + SET_REG_FIELD(0x87, reg, 3, 16, wrap_t); + SET_REG_FIELD(0x88, reg, 1, 19, utc_lod); + SET_REG_FIELD(0x89, reg, 1, 20, add_prev); + SET_REG_FIELD(0x8A, reg, 8, 24, tev_stage + 16); + GX_WRITE_SOME_REG5(0x61, reg); + gx->bpSentNot = 0; +} + +void GXSetIndTexMtx(GXIndTexMtxID mtx_id, f32 offset[2][3], s8 scale_exp) +{ + s32 mtx[6]; + u32 reg; + u32 id; + + CHECK_GXBEGIN(0xBA, "GXSetIndTexMtx"); + + switch (mtx_id) { + case GX_ITM_0: + case GX_ITM_1: + case GX_ITM_2: + id = mtx_id - 1; + break; + case GX_ITM_S0: + case GX_ITM_S1: + case GX_ITM_S2: + id = mtx_id - 5; + break; + case GX_ITM_T0: + case GX_ITM_T1: + case GX_ITM_T2: + id = mtx_id - 9; + break; + default: + id = 0; + break; + } + + mtx[0] = (int)(1024.0f * offset[0][0]) & 0x7FF; + mtx[1] = (int)(1024.0f * offset[1][0]) & 0x7FF; + scale_exp += 0x11; + reg = 0; + SET_REG_FIELD(0xBD, reg, 11, 0, mtx[0]); + SET_REG_FIELD(0xBE, reg, 11, 11, mtx[1]); + SET_REG_FIELD(0xBF, reg, 2, 22, scale_exp & 3); + SET_REG_FIELD(0xC0, reg, 8, 24, id * 3 + 6); + GX_WRITE_SOME_REG5(0x61, reg); + + mtx[2] = (int)(1024.0f * offset[0][1]) & 0x7FF; + mtx[3] = (int)(1024.0f * offset[1][1]) & 0x7FF; + reg = 0; + SET_REG_FIELD(0xC6, reg, 11, 0, mtx[2]); + SET_REG_FIELD(0xC7, reg, 11, 11, mtx[3]); + SET_REG_FIELD(0xC8, reg, 2, 22, (scale_exp >> 2) & 3); + SET_REG_FIELD(0xC9, reg, 8, 24, id * 3 + 7); + GX_WRITE_SOME_REG5(0x61, reg); + + mtx[4] = (int)(1024.0f * offset[0][2]) & 0x7FF; + mtx[5] = (int)(1024.0f * offset[1][2]) & 0x7FF; + reg = 0; + SET_REG_FIELD(0xCF, reg, 11, 0, mtx[4]); + SET_REG_FIELD(0xD0, reg, 11, 11, mtx[5]); + SET_REG_FIELD(0xD1, reg, 2, 22, (scale_exp >> 4) & 3); + SET_REG_FIELD(0xD2, reg, 8, 24, id * 3 + 8); + GX_WRITE_SOME_REG5(0x61, reg); + + gx->bpSentNot = 0; +} + +void GXSetIndTexCoordScale(GXIndTexStageID ind_state, GXIndTexScale scale_s, GXIndTexScale scale_t) +{ + CHECK_GXBEGIN(0xF9, "GXSetIndTexScale"); + + switch (ind_state) { + case GX_INDTEXSTAGE0: + SET_REG_FIELD(0xEA, gx->IndTexScale0, 4, 0, scale_s); + SET_REG_FIELD(0xEB, gx->IndTexScale0, 4, 4, scale_t); + SET_REG_FIELD(0xEC, gx->IndTexScale0, 8, 24, 0x25); + GX_WRITE_SOME_REG5(0x61, gx->IndTexScale0); + break; + case GX_INDTEXSTAGE1: + SET_REG_FIELD(0xF0, gx->IndTexScale0, 4, 8, scale_s); + SET_REG_FIELD(0xF1, gx->IndTexScale0, 4, 12, scale_t); + SET_REG_FIELD(0xF2, gx->IndTexScale0, 8, 24, 0x25); + GX_WRITE_SOME_REG5(0x61, gx->IndTexScale0); + break; + case GX_INDTEXSTAGE2: + SET_REG_FIELD(0xF6, gx->IndTexScale1, 4, 0, scale_s); + SET_REG_FIELD(0xF7, gx->IndTexScale1, 4, 4, scale_t); + SET_REG_FIELD(0xF8, gx->IndTexScale1, 8, 24, 0x26); + GX_WRITE_SOME_REG5(0x61, gx->IndTexScale1); + break; + case GX_INDTEXSTAGE3: + SET_REG_FIELD(0xFC, gx->IndTexScale1, 4, 8, scale_s); + SET_REG_FIELD(0xFD, gx->IndTexScale1, 4, 12, scale_t); + SET_REG_FIELD(0xFE, gx->IndTexScale1, 8, 24, 0x26); + GX_WRITE_SOME_REG5(0x61, gx->IndTexScale1); + break; + default: + ASSERTMSGLINE(0x115, 0, "GXSetIndTexCoordScale: Invalid Indirect Stage Id"); + break; + } + gx->bpSentNot = 0; +} + +void GXSetIndTexOrder(GXIndTexStageID ind_stage, GXTexCoordID tex_coord, GXTexMapID tex_map) +{ + CHECK_GXBEGIN(0x12E, "GXSetIndTexOrder"); + + ASSERTMSGLINE(0x11D, tex_map < 8, "GXSetIndTexOrder: Invalid direct texture Id"); + ASSERTMSGLINE(0x11E, tex_coord < 8, "GXSetIndTexOrder: Invalid texture coord"); + switch (ind_stage) { + case GX_INDTEXSTAGE0: + SET_REG_FIELD(0x122, gx->iref, 3, 0, tex_map); + SET_REG_FIELD(0x123, gx->iref, 3, 3, tex_coord); + break; + case GX_INDTEXSTAGE1: + SET_REG_FIELD(0x126, gx->iref, 3, 6, tex_map); + SET_REG_FIELD(0x127, gx->iref, 3, 9, tex_coord); + break; + case GX_INDTEXSTAGE2: + SET_REG_FIELD(0x12A, gx->iref, 3, 12, tex_map); + SET_REG_FIELD(0x12B, gx->iref, 3, 15, tex_coord); + break; + case GX_INDTEXSTAGE3: + SET_REG_FIELD(0x12E, gx->iref, 3, 18, tex_map); + SET_REG_FIELD(0x12F, gx->iref, 3, 21, tex_coord); + break; + default: + ASSERTMSGLINE(0x132, 0, "GXSetIndTexOrder: Invalid Indirect Stage Id"); + break; + } + GX_WRITE_SOME_REG5(0x61, gx->iref); + gx->dirtyState |= 3; + gx->bpSentNot = 0; +} + +void GXSetNumIndStages(u8 nIndStages) +{ + CHECK_GXBEGIN(0x144, "GXSetNumIndStages"); + ASSERTMSGLINE(0x146, nIndStages <= 4, "GXSetNumIndStages: Exceeds max. number of indirect texture stages"); + SET_REG_FIELD(0x147, gx->genMode, 3, 16, nIndStages); + gx->dirtyState |= 6; +} + +#pragma dont_inline on +void GXSetTevDirect(GXTevStageID tev_stage) +{ + CHECK_GXBEGIN(0x158, "GXSetTevDirect"); + GXSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, 0U, 0, 0); +} + +void GXSetTevIndWarp(GXTevStageID tev_stage, GXIndTexStageID ind_stage, u8 signed_offset, u8 replace_mode, GXIndTexMtxID matrix_sel) +{ + GXIndTexWrap wrap = (replace_mode != 0) ? GX_ITW_0 : GX_ITW_OFF; + + CHECK_GXBEGIN(0x16E, "GXSetTevIndWarp"); + GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, (signed_offset != 0) ? GX_ITB_STU : GX_ITB_NONE, matrix_sel, wrap, wrap, 0U, 0, 0); +} + +void GXSetTevIndTile(GXTevStageID tev_stage, GXIndTexStageID ind_stage, u16 tilesize_s, u16 tilesize_t, u16 tilespacing_s, u16 tilespacing_t, + GXIndTexFormat format, GXIndTexMtxID matrix_sel, GXIndTexBiasSel bias_sel, GXIndTexAlphaSel alpha_sel) +{ + GXIndTexWrap wrap_s; + GXIndTexWrap wrap_t; + f32 mtx[2][3]; + + CHECK_GXBEGIN(0x190, "GXSetTevIndTile"); + ASSERTMSGLINE(0x191, tev_stage < 16, "GXSetTevIndTile: Invalid tev stage id"); + ASSERTMSGLINE(0x192, ind_stage < 4, "GXSetTevIndTile: Invalid indirect stage id"); + switch (tilesize_s) { + case 256: + wrap_s = GX_ITW_256; + break; + case 128: + wrap_s = GX_ITW_128; + break; + case 64: + wrap_s = GX_ITW_64; + break; + case 32: + wrap_s = GX_ITW_32; + break; + case 16: + wrap_s = GX_ITW_16; + break; + default: + ASSERTMSGLINE(0x19B, 0, "GXSetTevIndTile: Invalid tilesize for S coordinate"); + wrap_s = GX_ITW_OFF; + break; + } + switch (tilesize_t) { + case 256: + wrap_t = GX_ITW_256; + break; + case 128: + wrap_t = GX_ITW_128; + break; + case 64: + wrap_t = GX_ITW_64; + break; + case 32: + wrap_t = GX_ITW_32; + break; + case 16: + wrap_t = GX_ITW_16; + break; + default: + ASSERTMSGLINE(0x1A7, 0, "GXSetTevIndTile: Invalid tilesize for T coordinate"); + wrap_t = GX_ITW_OFF; + break; + } + mtx[0][0] = tilespacing_s / 1024.0f; + mtx[0][1] = mtx[0][2] = 0.0f; + mtx[1][1] = tilespacing_t / 1024.0f; + mtx[1][0] = mtx[1][2] = 0.0f; + GXSetIndTexMtx(matrix_sel, mtx, 0xA); + GXSetTevIndirect(tev_stage, ind_stage, format, bias_sel, matrix_sel, wrap_s, wrap_t, 0U, 1, alpha_sel); +} +#pragma dont_inline off + +void GXSetTevIndBumpST(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel) +{ + GXIndTexMtxID sm; + GXIndTexMtxID tm; + + CHECK_GXBEGIN(0x1CF, "GXSetTevIndBumpST"); + switch (matrix_sel) { + case GX_ITM_0: + sm = GX_ITM_S0; + tm = GX_ITM_T0; + break; + case GX_ITM_1: + sm = GX_ITM_S1; + tm = GX_ITM_T1; + break; + case GX_ITM_2: + sm = GX_ITM_S2; + tm = GX_ITM_T2; + break; + default: + ASSERTMSGLINE(0x1E0, 0, "GXSetTevIndBumpST: Invalid matrix selection"); + break; + } + GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, GX_ITB_ST, sm, GX_ITW_0, GX_ITW_0, 0U, 0, 0); + GXSetTevIndirect(tev_stage + 1, ind_stage, GX_ITF_8, GX_ITB_ST, tm, GX_ITW_0, GX_ITW_0, 1U, 0, 0); + GXSetTevIndirect(tev_stage + 2, ind_stage, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, 1U, 0, 0); +} + +void GXSetTevIndBumpXYZ(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel) +{ + CHECK_GXBEGIN(0x214, "GXSetTevIndBumpXYZ"); + GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, GX_ITB_STU, matrix_sel, GX_ITW_OFF, GX_ITW_OFF, 0U, 0, 0); +} + +void GXSetTevIndRepeat(GXTevStageID tev_stage) +{ + CHECK_GXBEGIN(0x231, "GXSetTevIndRepeat"); + GXSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_0, GX_ITW_0, 1U, 0, 0); +} + +void __GXUpdateBPMask(void) +{ + u32 nIndStages; + u32 i; + u32 tmap; + u32 new_imask; + u32 nStages; + u32 new_dmask; + + new_imask = 0; + new_dmask = 0; + nIndStages = GET_REG_FIELD(gx->genMode, 3, 16); + for (i = 0; i < nIndStages; i++) { + switch (i) { + case 0: + tmap = GET_REG_FIELD(gx->iref, 3, 0); + break; + case 1: + tmap = GET_REG_FIELD(gx->iref, 3, 6); + break; + case 2: + tmap = GET_REG_FIELD(gx->iref, 3, 12); + break; + case 3: + tmap = GET_REG_FIELD(gx->iref, 3, 18); + break; + } + new_imask |= 1 << tmap; + } + + if ((u8)gx->bpMask != new_imask) { + SET_REG_FIELD(0x26E, gx->bpMask, 8, 0, new_imask); + GX_WRITE_SOME_REG5(0x61, gx->bpMask); + gx->bpSentNot = 0; + } +} + +void __GXFlushTextureState(void) +{ + GX_WRITE_SOME_REG5(0x61, gx->bpMask); + gx->bpSentNot = 0; +} diff --git a/src/dolphin/gx/GXDisplayList.c b/src/dolphin/gx/GXDisplayList.c new file mode 100644 index 00000000..cc751606 --- /dev/null +++ b/src/dolphin/gx/GXDisplayList.c @@ -0,0 +1,83 @@ +#include + +#include +#include + +#include + +static struct __GXFifoObj DisplayListFifo; +static volatile struct __GXFifoObj *OldCPUFifo; +static struct __GXData_struct __savedGXdata; + +void GXBeginDisplayList(void *list, u32 size) +{ + struct __GXFifoObj *CPUFifo = (struct __GXFifoObj *)GXGetCPUFifo(); + + CHECK_GXBEGIN(0x89, "GXBeginDisplayList"); + ASSERTMSGLINE(0x8A, !__GXData->inDispList, "GXBeginDisplayList: display list already in progress"); + ASSERTMSGLINE(0x8B, (size & 0x1F) == 0, "GXBeginDisplayList: size is not 32 byte aligned"); + ASSERTMSGLINE(0x8C, ((u32)list & 0x1F) == 0, "GXBeginDisplayList: list is not 32 byte aligned"); + if (gx->dirtyState != 0) { + __GXSetDirtyState(); + } + if (gx->dlSaveContext != 0) { + memcpy(&__savedGXdata, gx, sizeof(__savedGXdata)); + } + DisplayListFifo.base = (u8 *)list; + DisplayListFifo.top = (u8 *)list + size - 4; + DisplayListFifo.size = size; + DisplayListFifo.count = 0; + DisplayListFifo.rdPtr = list; + DisplayListFifo.wrPtr = list; + gx->inDispList = 1; + GXSaveCPUFifo((GXFifoObj *)CPUFifo); + OldCPUFifo = CPUFifo; + GXSetCPUFifo((GXFifoObj *)&DisplayListFifo); +} + +unsigned long GXEndDisplayList(void) +{ + u32 ov; + BOOL enabled; + u32 cpenable; + + CHECK_GXBEGIN(0xB5, "GXEndDisplayList"); + ASSERTMSGLINE(0xB6, gx->inDispList == TRUE, "GXEndDisplayList: no display list in progress"); + if (gx->dirtyState != 0) { + __GXSetDirtyState(); + } + ov = (__piReg[5] >> 26) & 1; + __GXSaveCPUFifoAux(&DisplayListFifo); + ASSERTMSGLINE(0xC3, !ov, "GXEndDisplayList: display list commands overflowed buffer"); + GXSetCPUFifo((GXFifoObj *)OldCPUFifo); + if (gx->dlSaveContext != 0) { + enabled = OSDisableInterrupts(); + cpenable = gx->cpEnable; + memcpy(gx, &__savedGXdata, sizeof(*gx)); + gx->cpEnable = cpenable; + OSRestoreInterrupts(enabled); + } + gx->inDispList = 0; + if (!ov) { + return DisplayListFifo.count; + } + return 0; +} + +void GXCallDisplayList(const void *list, u32 nbytes) +{ + CHECK_GXBEGIN(0xEC, "GXCallDisplayList"); + ASSERTMSGLINE(0xED, !gx->inDispList, "GXCallDisplayList: display list already in progress"); + ASSERTMSGLINE(0xEE, (nbytes & 0x1F) == 0, "GXCallDisplayList: nbytes is not 32 byte aligned"); + ASSERTMSGLINE(0xEF, ((u32)list & 0x1F) == 0, "GXCallDisplayList: list is not 32 byte aligned"); + + if (gx->dirtyState != 0) { + __GXSetDirtyState(); + } + if (*(u32 *)&gx->vNumNot == 0) { // checks both vNum and bpSent + __GXSendFlushPrim(); + } + GX_WRITE_U8(0x40); + GX_WRITE_U32((u32)list); + GX_WRITE_U32(nbytes); +} diff --git a/src/dolphin/gx/GXFifo.c b/src/dolphin/gx/GXFifo.c new file mode 100644 index 00000000..963be184 --- /dev/null +++ b/src/dolphin/gx/GXFifo.c @@ -0,0 +1,559 @@ +#include +#include +#include +#include + + +#include + +static OSThread *__GXCurrentThread; +static GXBool CPGPLinked; +static BOOL GXOverflowSuspendInProgress; +static GXBreakPtCallback BreakPointCB; +static u32 __GXOverflowCount; + +struct __GXFifoObj *CPUFifo; +struct __GXFifoObj *GPFifo; +void *__GXCurrentBP; + +static void __GXFifoReadEnable(void); +static void __GXFifoReadDisable(void); +static void __GXFifoLink(u8 arg0); +static void __GXWriteFifoIntEnable(u8 arg0, u8 arg1); +static void __GXWriteFifoIntReset(u8 arg0, u8 arg1); + +static void GXOverflowHandler(s16 interrupt, OSContext *context) +{ + ASSERTLINE(0x179, !GXOverflowSuspendInProgress); + + __GXOverflowCount++; + __GXWriteFifoIntEnable(0, 1); + __GXWriteFifoIntReset(1, 0); + GXOverflowSuspendInProgress = TRUE; + + OSSuspendThread(__GXCurrentThread); +} + +static void GXUnderflowHandler(s16 interrupt, OSContext *context) +{ + ASSERTLINE(0x1A3, GXOverflowSuspendInProgress); + + OSResumeThread(__GXCurrentThread); + GXOverflowSuspendInProgress = FALSE; + __GXWriteFifoIntReset(1U, 1U); + __GXWriteFifoIntEnable(1U, 0U); +} + +#define SOME_SET_REG_MACRO(reg, size, shift, val) \ + do { \ + (reg) = (u32)__rlwimi((u32)(reg), (val), (shift), (32 - (shift) - (size)), (31 - (shift))); \ + } while (0); + +static void GXBreakPointHandler(s16 interrupt, OSContext *context) +{ + OSContext exceptionContext; + + SOME_SET_REG_MACRO(gx->cpEnable, 1, 5, 0); + GX_SET_CP_REG(1, gx->cpEnable); + if (BreakPointCB != NULL) { + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + BreakPointCB(); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +static void GXCPInterruptHandler(s16 interrupt, OSContext *context) +{ + gx->cpStatus = GX_GET_CP_REG(0); + if (GET_REG_FIELD(gx->cpEnable, 1, 3) && GET_REG_FIELD(gx->cpStatus, 1, 1)) { + GXUnderflowHandler(interrupt, context); + } + if (GET_REG_FIELD(gx->cpEnable, 1, 2) && GET_REG_FIELD(gx->cpStatus, 1, 0)) { + GXOverflowHandler(interrupt, context); + } + if (GET_REG_FIELD(gx->cpEnable, 1, 5) && GET_REG_FIELD(gx->cpStatus, 1, 4)) { + GXBreakPointHandler(interrupt, context); + } +} + +void GXInitFifoBase(GXFifoObj *fifo, void *base, u32 size) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + + ASSERTMSGLINE(0x21E, realFifo != CPUFifo, "GXInitFifoBase: fifo is attached to CPU"); + ASSERTMSGLINE(0x220, realFifo != GPFifo, "GXInitFifoBase: fifo is attached to GP"); + ASSERTMSGLINE(0x222, ((u32)base & 0x1F) == 0, "GXInitFifoBase: base must be 32B aligned"); + ASSERTMSGLINE(0x224, base != NULL, "GXInitFifoBase: base pointer is NULL"); + ASSERTMSGLINE(0x226, (size & 0x1F) == 0, "GXInitFifoBase: size must be 32B aligned"); + ASSERTMSGLINE(0x228, size >= 0x10000, "GXInitFifoBase: fifo is not large enough"); + + realFifo->base = base; + realFifo->top = (u8 *)base + size - 4; + realFifo->size = size; + realFifo->count = 0; + GXInitFifoLimits(fifo, size - 0x4000, (size >> 1) & ~0x1F); + GXInitFifoPtrs(fifo, base, base); +} + +void GXInitFifoPtrs(GXFifoObj *fifo, void *readPtr, void *writePtr) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + BOOL enabled; + + ASSERTMSGLINE(0x250, realFifo != CPUFifo, "GXInitFifoPtrs: fifo is attached to CPU"); + ASSERTMSGLINE(0x252, realFifo != GPFifo, "GXInitFifoPtrs: fifo is attached to GP"); + ASSERTMSGLINE(0x254, ((u32)readPtr & 0x1F) == 0, "GXInitFifoPtrs: readPtr not 32B aligned"); + ASSERTMSGLINE(0x256, ((u32)writePtr & 0x1F) == 0, "GXInitFifoPtrs: writePtr not 32B aligned"); + ASSERTMSGLINE(0x259, realFifo->base <= readPtr && readPtr < realFifo->top, "GXInitFifoPtrs: readPtr not in fifo range"); + ASSERTMSGLINE(0x25C, realFifo->base <= writePtr && writePtr < realFifo->top, "GXInitFifoPtrs: writePtr not in fifo range"); + + enabled = OSDisableInterrupts(); + realFifo->rdPtr = readPtr; + realFifo->wrPtr = writePtr; + realFifo->count = (u8 *)writePtr - (u8 *)readPtr; + if (realFifo->count < 0) { + realFifo->count += realFifo->size; + } + OSRestoreInterrupts(enabled); +} + +void GXInitFifoLimits(GXFifoObj *fifo, u32 hiWatermark, u32 loWatermark) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + + ASSERTMSGLINE(0x281, realFifo != GPFifo, "GXInitFifoLimits: fifo is attached to GP"); + ASSERTMSGLINE(0x283, (hiWatermark & 0x1F) == 0, "GXInitFifoLimits: hiWatermark not 32B aligned"); + ASSERTMSGLINE(0x285, (loWatermark & 0x1F) == 0, "GXInitFifoLimits: loWatermark not 32B aligned"); + ASSERTMSGLINE(0x287, hiWatermark < realFifo->top - realFifo->base, "GXInitFifoLimits: hiWatermark too large"); + ASSERTMSGLINE(0x289, loWatermark < hiWatermark, "GXInitFifoLimits: hiWatermark below lo watermark"); + + realFifo->hiWatermark = hiWatermark; + realFifo->loWatermark = loWatermark; +} + +void GXSetCPUFifo(GXFifoObj *fifo) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + BOOL enabled = OSDisableInterrupts(); + + CPUFifo = realFifo; + if (CPUFifo == GPFifo) + { + u32 reg = 0; + + __piReg[3] = (u32)realFifo->base & 0x3FFFFFFF; + __piReg[4] = (u32)realFifo->top & 0x3FFFFFFF; + SET_REG_FIELD(0x294, reg, 21, 5, ((u32)realFifo->wrPtr & 0x3FFFFFFF) >> 5); + SET_REG_FIELD(0x295, reg, 1, 26, 0); + __piReg[5] = reg; + CPGPLinked = GX_TRUE; + __GXWriteFifoIntReset(1, 1); + __GXWriteFifoIntEnable(1, 0); + __GXFifoLink(1); + } + else + { + u32 reg; + + if (CPGPLinked) + { + __GXFifoLink(0); + CPGPLinked = GX_FALSE; + } + __GXWriteFifoIntEnable(0, 0); + reg = 0; + __piReg[3] = (u32)realFifo->base & 0x3FFFFFFF; + __piReg[4] = (u32)realFifo->top & 0x3FFFFFFF; + SET_REG_FIELD(0x2B7, reg, 21, 5, ((u32)realFifo->wrPtr & 0x3FFFFFFF) >> 5); + SET_REG_FIELD(0x2B8, reg, 1, 26, 0); + __piReg[5] = reg; + } + + __sync(); + + OSRestoreInterrupts(enabled); +} + +void GXSetGPFifo(GXFifoObj *fifo) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + BOOL enabled = OSDisableInterrupts(); + + __GXFifoReadDisable(); + __GXWriteFifoIntEnable(0, 0); + GPFifo = realFifo; + + GX_SET_CP_REG(16, (u32)realFifo->base & 0xFFFF); + GX_SET_CP_REG(18, (u32)realFifo->top & 0xFFFF); + GX_SET_CP_REG(24, realFifo->count & 0xFFFF); + GX_SET_CP_REG(26, (u32)realFifo->wrPtr & 0xFFFF); + GX_SET_CP_REG(28, (u32)realFifo->rdPtr & 0xFFFF); + GX_SET_CP_REG(20, (u32)realFifo->hiWatermark & 0xFFFF); + GX_SET_CP_REG(22, (u32)realFifo->loWatermark & 0xFFFF); + GX_SET_CP_REG(17, ((u32)realFifo->base & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(19, ((u32)realFifo->top & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(25, realFifo->count >> 16); + GX_SET_CP_REG(27, ((u32)realFifo->wrPtr & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(29, ((u32)realFifo->rdPtr & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(21, (u32)realFifo->hiWatermark >> 16); + GX_SET_CP_REG(23, (u32)realFifo->loWatermark >> 16); + + __sync(); + + if (CPUFifo == GPFifo) { + CPGPLinked = GX_TRUE; + __GXWriteFifoIntEnable(1, 0); + __GXFifoLink(1); + } + else { + CPGPLinked = GX_FALSE; + __GXWriteFifoIntEnable(0, 0); + __GXFifoLink(0); + } + __GXWriteFifoIntReset(1, 1); + __GXFifoReadEnable(); + OSRestoreInterrupts(enabled); +} + +void GXSaveCPUFifo(GXFifoObj *fifo) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + ASSERTMSGLINE(0x343, realFifo == CPUFifo, "GXSaveCPUFifo: fifo is not attached to CPU"); + __GXSaveCPUFifoAux(realFifo); +} + +#define SOME_MACRO1(fifo) \ + do { \ + u32 temp = GX_GET_CP_REG(29) << 16; \ + temp |= GX_GET_CP_REG(28); \ + fifo->rdPtr = OSPhysicalToCached(temp); \ + } while (0) + +#define SOME_MACRO2(fifo) \ + do { \ + u32 temp = GX_GET_CP_REG(25) << 16; \ + temp |= GX_GET_CP_REG(24); \ + fifo->count = temp; \ + } while (0) + +void __GXSaveCPUFifoAux(struct __GXFifoObj *realFifo) +{ + BOOL enabled = OSDisableInterrupts(); + + GXFlush(); + realFifo->base = OSPhysicalToCached(__piReg[3]); + realFifo->top = OSPhysicalToCached(__piReg[4]); + realFifo->wrPtr = OSPhysicalToCached(__piReg[5] & 0xFBFFFFFF); + if (CPGPLinked) { + SOME_MACRO1(realFifo); + SOME_MACRO2(realFifo); + } else { + realFifo->count = (u8 *)realFifo->wrPtr - (u8 *)realFifo->rdPtr; + if (realFifo->count < 0) + realFifo->count += realFifo->size; + } + OSRestoreInterrupts(enabled); +} + +void GXSaveGPFifo(GXFifoObj *fifo) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + unsigned long cpStatus; + unsigned char readIdle; + unsigned long temp; + + ASSERTMSGLINE(0x38C, realFifo == GPFifo, "GXSaveGPFifo: fifo is not attached to GP"); + cpStatus = GX_GET_CP_REG(0); + readIdle = GET_REG_FIELD(cpStatus, 1, 2); + ASSERTMSGLINE(0x393, readIdle, "GXSaveGPFifo: GP is not idle"); + + SOME_MACRO1(realFifo); + SOME_MACRO2(realFifo); +} + +void GXGetGPStatus(GXBool *overhi, GXBool *underlow, GXBool *readIdle, GXBool *cmdIdle, GXBool *brkpt) +{ + gx->cpStatus = GX_GET_CP_REG(0); + *overhi = GET_REG_FIELD(gx->cpStatus, 1, 0); + *underlow = (int)GET_REG_FIELD(gx->cpStatus, 1, 1); + *readIdle = (int)GET_REG_FIELD(gx->cpStatus, 1, 2); + *cmdIdle = (int)GET_REG_FIELD(gx->cpStatus, 1, 3); + *brkpt = (int)GET_REG_FIELD(gx->cpStatus, 1, 4); +} + +void GXGetFifoStatus(GXFifoObj *fifo, GXBool *overhi, GXBool *underflow, u32 *fifoCount, GXBool *cpuWrite, GXBool *gpRead, GXBool *fifowrap) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + + *underflow = GX_FALSE; + *overhi = GX_FALSE; + *fifoCount = 0; + *fifowrap = GX_FALSE; + if (realFifo == GPFifo) { + SOME_MACRO1(realFifo); + SOME_MACRO2(realFifo); + } + if (realFifo == CPUFifo) { + GXFlush(); + __GXSaveCPUFifoAux(realFifo); + *fifowrap = (int)GET_REG_FIELD(GX_GET_PI_REG(5), 1, 26); + } + *overhi = (realFifo->count > realFifo->hiWatermark); + *underflow = (realFifo->count < realFifo->loWatermark); + *fifoCount = (realFifo->count); + *cpuWrite = (CPUFifo == realFifo); + *gpRead = (GPFifo == realFifo); +} + +void GXGetFifoPtrs(GXFifoObj *fifo, void **readPtr, void **writePtr) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + + if (realFifo == CPUFifo) { + realFifo->wrPtr = OSPhysicalToCached(GX_GET_PI_REG(5) & 0xFBFFFFFF); + } + if (realFifo == GPFifo) { + SOME_MACRO1(realFifo); + SOME_MACRO2(realFifo); + } + else { + realFifo->count = (u8 *)realFifo->wrPtr - (u8 *)realFifo->rdPtr; + if (realFifo->count < 0) { + realFifo->count += realFifo->size; + } + } + *readPtr = realFifo->rdPtr; + *writePtr = realFifo->wrPtr; +} + +void *GXGetFifoBase(const GXFifoObj *fifo) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + + return realFifo->base; +} + +u32 GXGetFifoSize(const GXFifoObj *fifo) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + + return realFifo->size; +} + +void GXGetFifoLimits(const GXFifoObj *fifo, u32 *hi, u32 *lo) +{ + struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; + + *hi = realFifo->hiWatermark; + *lo = realFifo->loWatermark; +} + +GXBreakPtCallback GXSetBreakPtCallback(GXBreakPtCallback cb) +{ + GXBreakPtCallback oldcb = BreakPointCB; + BOOL enabled = OSDisableInterrupts(); + + BreakPointCB = cb; + OSRestoreInterrupts(enabled); + return oldcb; +} + +void *__GXCurrentBP; + +void GXEnableBreakPt(void *break_pt) +{ + BOOL enabled = OSDisableInterrupts(); + + __GXFifoReadDisable(); + GX_SET_CP_REG(30, (u32)break_pt); + GX_SET_CP_REG(31, ((u32)break_pt >> 16) & 0x3FFF); + SOME_SET_REG_MACRO(gx->cpEnable, 1, 1, 1); + SOME_SET_REG_MACRO(gx->cpEnable, 1, 5, 1); + GX_SET_CP_REG(1, gx->cpEnable); + __GXCurrentBP = break_pt; + __GXFifoReadEnable(); + OSRestoreInterrupts(enabled); +} + +void GXDisableBreakPt(void) +{ + BOOL enabled = OSDisableInterrupts(); + + SOME_SET_REG_MACRO(gx->cpEnable, 1, 1, 0); + SOME_SET_REG_MACRO(gx->cpEnable, 1, 5, 0); + GX_SET_CP_REG(1, gx->cpEnable); + __GXCurrentBP = NULL; + OSRestoreInterrupts(enabled); +} + +void __GXFifoInit(void) +{ + __OSSetInterruptHandler(0x11, GXCPInterruptHandler); + __OSUnmaskInterrupts(0x4000); + __GXCurrentThread = OSGetCurrentThread(); + GXOverflowSuspendInProgress = FALSE; + CPUFifo = NULL; + GPFifo = NULL; +} + +static void __GXFifoReadEnable(void) +{ + SET_REG_FIELD(0, gx->cpEnable, 1, 0, 1); + GX_SET_CP_REG(1, gx->cpEnable); +} + +static void __GXFifoReadDisable(void) +{ + SET_REG_FIELD(0, gx->cpEnable, 1, 0, 0); + GX_SET_CP_REG(1, gx->cpEnable); +} + +static void __GXFifoLink(u8 en) +{ + SET_REG_FIELD(0x4DA, gx->cpEnable, 1, 4, (en != 0) ? 1 : 0); + GX_SET_CP_REG(1, gx->cpEnable); +} + +static void __GXWriteFifoIntEnable(u8 hiWatermarkEn, u8 loWatermarkEn) +{ + SET_REG_FIELD(0x4F0, gx->cpEnable, 1, 2, hiWatermarkEn); + SET_REG_FIELD(0x4F1, gx->cpEnable, 1, 3, loWatermarkEn); + GX_SET_CP_REG(1, gx->cpEnable); +} + +static void __GXWriteFifoIntReset(u8 hiWatermarkClr, u8 loWatermarkClr) +{ + SET_REG_FIELD(0x508, gx->cpClr, 1, 0, hiWatermarkClr); + SET_REG_FIELD(0x509, gx->cpClr, 1, 1, loWatermarkClr); + GX_SET_CP_REG(2, gx->cpClr); +} + +void __GXInsaneWatermark(void) +{ + struct __GXFifoObj *realFifo = GPFifo; + + realFifo->hiWatermark = realFifo->loWatermark + 512; + GX_SET_CP_REG(20, (realFifo->hiWatermark & 0x3FFFFFFF) & 0xFFFF); + GX_SET_CP_REG(21, (realFifo->hiWatermark & 0x3FFFFFFF) >> 16); +} + +void __GXCleanGPFifo(void) +{ + GXFifoObj dummyFifo; + GXFifoObj *gpFifo = GXGetGPFifo(); + GXFifoObj *cpuFifo = GXGetCPUFifo(); + void *base = GXGetFifoBase(gpFifo); + + dummyFifo = *gpFifo; + GXInitFifoPtrs(&dummyFifo, base, base); + GXSetGPFifo(&dummyFifo); + if (cpuFifo == gpFifo) { + GXSetCPUFifo(&dummyFifo); + } + GXInitFifoPtrs(gpFifo, base, base); + GXSetGPFifo(gpFifo); + if (cpuFifo == gpFifo) { + GXSetCPUFifo(cpuFifo); + } +} + +OSThread *GXSetCurrentGXThread(void) +{ + BOOL enabled; + struct OSThread *prev; + + enabled = OSDisableInterrupts(); + prev = __GXCurrentThread; + ASSERTMSGLINE(0x561, !GXOverflowSuspendInProgress, "GXSetCurrentGXThread: Two threads cannot generate GX commands at the same time!"); + __GXCurrentThread = OSGetCurrentThread(); + OSRestoreInterrupts(enabled); + return prev; +} + +OSThread *GXGetCurrentGXThread(void) +{ + return __GXCurrentThread; +} + +GXFifoObj *GXGetCPUFifo(void) +{ + return (GXFifoObj *)CPUFifo; +} + +GXFifoObj *GXGetGPFifo(void) +{ + return (GXFifoObj *)GPFifo; +} + +u32 GXGetOverflowCount(void) +{ + return __GXOverflowCount; +} + +u32 GXResetOverflowCount(void) +{ + u32 oldcount; + + oldcount = __GXOverflowCount; + __GXOverflowCount = 0; + return oldcount; +} + +// NONMATCHING +volatile void *GXRedirectWriteGatherPipe(void *ptr) +{ + u32 reg = 0; + BOOL enabled = OSDisableInterrupts(); + + CHECK_GXBEGIN(0x5D5, "GXRedirectWriteGatherPipe"); + ASSERTLINE(0x5D6, OFFSET(ptr, 32) == 0); + ASSERTLINE(0x5D8, !IsWGPipeRedirected); + + GXFlush(); + while (PPCMfwpar() & 1) { } + PPCMtwpar((u32)OSUncachedToPhysical((void *)GXFIFO_ADDR)); + if (CPGPLinked) { + __GXFifoLink(0); + __GXWriteFifoIntEnable(0, 0); + } + CPUFifo->wrPtr = OSPhysicalToCached(GX_GET_PI_REG(5) & 0xFBFFFFFF); + GX_SET_PI_REG(3, 0); + GX_SET_PI_REG(4, 0x04000000); + SET_REG_FIELD(0x5F7, reg, 21, 5, ((u32)ptr & 0x3FFFFFFF) >> 5); + reg &= 0xFBFFFFFF; + GX_SET_PI_REG(5, reg); + PPCSync(); + OSRestoreInterrupts(enabled); + return (volatile void *)GXFIFO_ADDR; +} + +// NONMATCHING +void GXRestoreWriteGatherPipe(void) +{ + u32 reg = 0; // r31 + u32 i; // r29 + BOOL enabled; // r28 + + ASSERTLINE(0x610, IsWGPipeRedirected); + enabled = OSDisableInterrupts(); + for (i = 0; i < 31; i++) { + GXWGFifo.u8 = 0; + } + PPCSync(); + while (PPCMfwpar() & 1) { } + PPCMtwpar((u32)OSUncachedToPhysical((void *)GXFIFO_ADDR)); + GX_SET_PI_REG(3, (u32)CPUFifo->base & 0x3FFFFFFF); + GX_SET_PI_REG(4, (u32)CPUFifo->top & 0x3FFFFFFF); + SET_REG_FIELD(0x62A, reg, 21, 5, ((u32)CPUFifo->wrPtr & 0x3FFFFFFF) >> 5); + reg &= 0xFBFFFFFF; + GX_SET_PI_REG(5, reg); + if (CPGPLinked) { + __GXWriteFifoIntReset(1, 1); + __GXWriteFifoIntEnable(1, 0); + __GXFifoLink(1); + } + PPCSync(); + OSRestoreInterrupts(enabled); +} diff --git a/src/dolphin/gx/GXFrameBuf.c b/src/dolphin/gx/GXFrameBuf.c new file mode 100644 index 00000000..4c04abab --- /dev/null +++ b/src/dolphin/gx/GXFrameBuf.c @@ -0,0 +1,604 @@ +#include +#include + +#include + +GXRenderModeObj GXNtsc240Ds = { 1, 640, 240, 240, 40, 0, 640, 480, 0, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; + +GXRenderModeObj GXNtsc240DsAa = { 1, 640, 240, 240, 40, 0, 640, 480, 0, 0, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } }; + +GXRenderModeObj GXNtsc240Int = { 0, 640, 240, 240, 40, 0, 640, 480, 0, 1, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; + +GXRenderModeObj GXNtsc240IntAa = { 0, 640, 240, 240, 40, 0, 640, 480, 0, 1, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } }; + +GXRenderModeObj GXNtsc480IntDf = { 0, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 8, 8, 10, 12, 10, 8, 8 } }; + +GXRenderModeObj GXNtsc480Int = { 0, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; + +GXRenderModeObj GXNtsc480IntAa = { 0, 640, 242, 480, 40, 0, 640, 480, 1, 0, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } }; + +GXRenderModeObj GXNtsc480Prog = { 2, 640, 480, 480, 40, 0, 640, 480, 0, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; + +GXRenderModeObj GXNtsc480ProgSoft = { 2, 640, 480, 480, 40, 0, 640, 480, 0, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 8, 8, 10, 12, 10, 8, 8 } }; + +GXRenderModeObj GXNtsc480ProgAa = { 2, 640, 242, 480, 40, 0, 640, 480, 0, 0, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } }; + +GXRenderModeObj GXMpal240Ds = { 9, 640, 240, 240, 40, 0, 640, 480, 0, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXMpal240DsAa = { 9, 640, 240, 240, 40, 0, 640, 480, 0, 0, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXMpal240Int = { 8, 640, 240, 240, 40, 0, 640, 480, 0, 1, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXMpal240IntAa = { 8, 640, 240, 240, 40, 0, 640, 480, 0, 1, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXMpal480IntDf = { 8, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 8, 8, 10, 12, 10, 8, 8 } }; +GXRenderModeObj GXMpal480Int = { 8, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXMpal480IntAa = { 8, 640, 242, 480, 40, 0, 640, 480, 1, 0, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } }; +GXRenderModeObj GXPal264Ds = { 5, 640, 264, 264, 40, 11, 640, 528, 0, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXPal264DsAa = { 5, 640, 264, 264, 40, 11, 640, 528, 0, 0, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXPal264Int = { 4, 640, 264, 264, 40, 23, 640, 528, 0, 1, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXPal264IntAa = { 4, 640, 264, 264, 40, 23, 640, 528, 0, 1, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXPal528IntDf = { 4, 640, 528, 528, 40, 23, 640, 528, 1, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 8, 8, 10, 12, 10, 8, 8 } }; +GXRenderModeObj GXPal528Int = { 4, 640, 528, 528, 40, 23, 640, 528, 1, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXPal524IntAa = { 4, 640, 264, 524, 40, 23, 640, 524, 1, 0, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } }; +GXRenderModeObj GXEurgb60Hz240Ds = { 21, 640, 240, 240, 40, 0, 640, 480, 0, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXEurgb60Hz240DsAa = { 21, 640, 240, 240, 40, 0, 640, 480, 0, 0, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXEurgb60Hz240Int = { 20, 640, 240, 240, 40, 0, 640, 480, 0, 1, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXEurgb60Hz240IntAa = { 20, 640, 240, 240, 40, 0, 640, 480, 0, 1, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXEurgb60Hz480IntDf = { 20, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 8, 8, 10, 12, 10, 8, 8 } }; +GXRenderModeObj GXEurgb60Hz480Int = { 20, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0, + { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj GXEurgb60Hz480IntAa = { 20, 640, 242, 480, 40, 0, 640, 480, 1, 0, 1, + { 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } }; +GXRenderModeObj GXRmHW = { 1, 320, 240, 240, 40, 0, 640, 480, 0, 0, 0, { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, + { 0, 0, 21, 22, 21, 0, 0 } }; + +void GXAdjustForOverscan(GXRenderModeObj *rmin, GXRenderModeObj *rmout, u16 hor, u16 ver) +{ + u16 hor2 = hor * 2; + u16 ver2 = ver * 2; + u32 verf; + u32 mode; + + if (rmin != rmout) { + *rmout = *rmin; + } + + mode = rmin->viTVmode & 3; + rmout->fbWidth = rmin->fbWidth - hor2; + verf = (ver2 * rmin->efbHeight) / (u32)rmin->xfbHeight; + rmout->efbHeight = rmin->efbHeight - verf; + if (rmin->xFBmode == VI_XFBMODE_SF && ((rmin->viTVmode & 2) != 2)) { + rmout->xfbHeight = rmin->xfbHeight - ver; + } + else { + rmout->xfbHeight = rmin->xfbHeight - ver2; + } + + rmout->viWidth = rmin->viWidth - hor2; + rmout->viHeight = rmin->viHeight - ver2; + rmout->viXOrigin = rmin->viXOrigin + hor; + rmout->viYOrigin = rmin->viYOrigin + ver; +} + +void GXSetDispCopySrc(u16 left, u16 top, u16 wd, u16 ht) +{ + CHECK_GXBEGIN(0x4D3, "GXSetDispCopySrc"); + + gx->cpDispSrc = 0; + SET_REG_FIELD(0x4D6, gx->cpDispSrc, 10, 0, left); + SET_REG_FIELD(0x4D7, gx->cpDispSrc, 10, 10, top); + SET_REG_FIELD(0x4D7, gx->cpDispSrc, 8, 24, 0x49); + + gx->cpDispSize = 0; + SET_REG_FIELD(0x4DB, gx->cpDispSize, 10, 0, wd - 1); + SET_REG_FIELD(0x4DC, gx->cpDispSize, 10, 10, ht - 1); + SET_REG_FIELD(0x4DC, gx->cpDispSize, 8, 24, 0x4A); +} + +void GXSetTexCopySrc(u16 left, u16 top, u16 wd, u16 ht) +{ + CHECK_GXBEGIN(0x4EF, "GXSetTexCopySrc"); + + gx->cpTexSrc = 0; + SET_REG_FIELD(0x4F2, gx->cpTexSrc, 10, 0, left); + SET_REG_FIELD(0x4F3, gx->cpTexSrc, 10, 10, top); + SET_REG_FIELD(0x4F3, gx->cpTexSrc, 8, 24, 0x49); + + gx->cpTexSize = 0; + SET_REG_FIELD(0x4F7, gx->cpTexSize, 10, 0, wd - 1); + SET_REG_FIELD(0x4F8, gx->cpTexSize, 10, 10, ht - 1); + SET_REG_FIELD(0x4F8, gx->cpTexSize, 8, 24, 0x4A); +} + +void GXSetDispCopyDst(u16 wd, u16 ht) +{ + u16 stride; + + ASSERTMSGLINE(0x50D, (wd & 0xF) == 0, "GXSetDispCopyDst: Width must be a multiple of 16"); + CHECK_GXBEGIN(0x50E, "GXSetDispCopyDst"); + + stride = (int)wd * 2; + gx->cpDispStride = 0; + SET_REG_FIELD(0x514, gx->cpDispStride, 10, 0, (stride >> 5)); + SET_REG_FIELD(0x514, gx->cpDispStride, 8, 24, 0x4D); +} + +void GXSetTexCopyDst(u16 wd, u16 ht, GXTexFmt fmt, GXBool mipmap) +{ + u32 rowTiles; + u32 colTiles; + u32 cmpTiles; + u32 peTexFmt; + u32 peTexFmtH; + + CHECK_GXBEGIN(0x52F, "GXSetTexCopyDst"); + + gx->cpTexZ = 0; + peTexFmt = fmt & 0xF; + ASSERTMSGLINEV(0x54E, peTexFmt < 13, "%s: invalid texture format", "GXSetTexCopyDst"); + + if (fmt == GX_TF_Z16) { + peTexFmt = 0xB; + } + switch (fmt) { + case GX_TF_I4: + case GX_TF_I8: + case GX_TF_IA4: + case GX_TF_IA8: + case GX_CTF_YUVA8: + SET_REG_FIELD(0, gx->cpTex, 2, 15, 3); + break; + default: + SET_REG_FIELD(0, gx->cpTex, 2, 15, 2); + break; + } + + gx->cpTexZ = (fmt & _GX_TF_ZTF) == _GX_TF_ZTF; + peTexFmtH = (peTexFmt >> 3) & 1; + !peTexFmt; + SET_REG_FIELD(0x565, gx->cpTex, 1, 3, peTexFmtH); + peTexFmt = peTexFmt & 7; + __GetImageTileCount(fmt, wd, ht, &rowTiles, &colTiles, &cmpTiles); + + gx->cpTexStride = 0; + SET_REG_FIELD(0x56E, gx->cpTexStride, 10, 0, rowTiles * cmpTiles); + SET_REG_FIELD(0x570, gx->cpTexStride, 8, 24, 0x4D); + SET_REG_FIELD(0x570, gx->cpTex, 1, 9, mipmap); + SET_REG_FIELD(0x571, gx->cpTex, 3, 4, peTexFmt); +} + +void GXSetDispCopyFrame2Field(GXCopyMode mode) +{ + CHECK_GXBEGIN(0x582, "GXSetDispCopyFrame2Field"); + SET_REG_FIELD(0x583, gx->cpDisp, 2, 12, mode); + SET_REG_FIELD(0x583, gx->cpTex, 2, 12, 0); +} + +void GXSetCopyClamp(GXFBClamp clamp) +{ + u8 clmpB; + u8 clmpT; + + CHECK_GXBEGIN(0x597, "GXSetCopyClamp"); + + clmpT = (clamp & 1) == 1; + clmpB = (clamp & 2) == 2; + + SET_REG_FIELD(0x59B, gx->cpDisp, 1, 0, clmpT); + SET_REG_FIELD(0x59C, gx->cpDisp, 1, 1, clmpB); + + SET_REG_FIELD(0x59E, gx->cpTex, 1, 0, clmpT); + SET_REG_FIELD(0x59F, gx->cpTex, 1, 1, clmpB); +} + +static u32 __GXGetNumXfbLines(u32 efbHt, u32 iScale) +{ + u32 count; + u32 realHt; + u32 iScaleD; + + count = (efbHt - 1) * 0x100; + realHt = (count / iScale) + 1; + + iScaleD = iScale; + + if (iScaleD > 0x80 && iScaleD < 0x100) { + while (iScaleD % 2 == 0) { + iScaleD /= 2; + } + + if (efbHt % iScaleD == 0) { + realHt++; + } + } + + if (realHt > 0x400) { + realHt = 0x400; + } + + return realHt; +} + +u16 GXGetNumXfbLines(u16 efbHeight, f32 yScale) +{ + u32 iScale; + ASSERTMSGLINE(0x5CE, yScale >= 1.0f, "GXGetNumXfbLines: Vertical scale must be >= 1.0"); + + iScale = (u32)(256.0f / yScale) & 0x1FF; + return __GXGetNumXfbLines(efbHeight, iScale); +} + +f32 GXGetYScaleFactor(u16 efbHeight, u16 xfbHeight) +{ + f32 fScale; + f32 yScale; + u32 iScale; + u32 tgtHt; + u32 realHt; + + ASSERTMSGLINE(0x5E6, xfbHeight <= 1024, "GXGetYScaleFactor: Display copy only supports up to 1024 lines.\n"); + ASSERTMSGLINE(0x5E8, efbHeight <= xfbHeight, "GXGetYScaleFactor: EFB height should not be greater than XFB height.\n"); + + tgtHt = xfbHeight; + yScale = (f32)xfbHeight / (f32)efbHeight; + iScale = (u32)(256.0f / yScale) & 0x1FF; + realHt = __GXGetNumXfbLines(efbHeight, iScale); + + while (realHt > xfbHeight) { + tgtHt--; + yScale = (f32)tgtHt / (f32)efbHeight; + iScale = (u32)(256.0f / yScale) & 0x1FF; + realHt = __GXGetNumXfbLines(efbHeight, iScale); + } + + fScale = yScale; + while (realHt < xfbHeight) { + fScale = yScale; + tgtHt++; + yScale = (f32)tgtHt / (f32)efbHeight; + iScale = (u32)(256.0f / yScale) & 0x1FF; + realHt = __GXGetNumXfbLines(efbHeight, iScale); + } + + return fScale; +} + +u32 GXSetDispCopyYScale(f32 vscale) +{ + u8 enable; + u32 iScale; + u32 ht; + u32 reg; + + CHECK_GXBEGIN(0x615, "GXSetDispCopyYScale"); + + ASSERTMSGLINE(0x617, vscale >= 1.0f, "GXSetDispCopyYScale: Vertical scale must be >= 1.0"); + + iScale = (u32)(256.0f / vscale) & 0x1FF; + enable = (iScale != 256); + + reg = 0; + SET_REG_FIELD(0x61E, reg, 9, 0, iScale); + SET_REG_FIELD(0x61E, reg, 8, 24, 0x4E); + GX_WRITE_RAS_REG(reg); + gx->bpSentNot = 0; + SET_REG_FIELD(0x623, gx->cpDisp, 1, 10, enable); + ht = GET_REG_FIELD(gx->cpDispSize, 10, 10) + 1; + return __GXGetNumXfbLines(ht, iScale); +} + +void GXSetCopyClear(GXColor clear_clr, u32 clear_z) +{ + u32 reg; + + CHECK_GXBEGIN(0x63C, "GXSetCopyClear"); + ASSERTMSGLINE(0x63E, clear_z <= 0xFFFFFF, "GXSetCopyClear: Z clear value is out of range"); + + reg = 0; + SET_REG_FIELD(0x641, reg, 8, 0, clear_clr.r); + SET_REG_FIELD(0x642, reg, 8, 8, clear_clr.a); + SET_REG_FIELD(0x642, reg, 8, 24, 0x4F); + GX_WRITE_RAS_REG(reg); + + reg = 0; + SET_REG_FIELD(0x647, reg, 8, 0, clear_clr.b); + SET_REG_FIELD(0x648, reg, 8, 8, clear_clr.g); + SET_REG_FIELD(0x648, reg, 8, 24, 0x50); + GX_WRITE_RAS_REG(reg); + + reg = 0; + SET_REG_FIELD(0x64D, reg, 24, 0, clear_z); + SET_REG_FIELD(0x64D, reg, 8, 24, 0x51); + GX_WRITE_RAS_REG(reg); + gx->bpSentNot = 0; +} + +void GXSetCopyFilter(GXBool aa, u8 sample_pattern[12][2], GXBool vf, u8 vfilter[7]) +{ + u32 msLoc[4]; + u32 coeff0; + u32 coeff1; + + CHECK_GXBEGIN(0x669, "GXSetCopyFilter"); + + if (aa != 0) { + msLoc[0] = 0; + SET_REG_FIELD(0x66D, msLoc[0], 4, 0, sample_pattern[0][0]); + SET_REG_FIELD(0x66E, msLoc[0], 4, 4, sample_pattern[0][1]); + SET_REG_FIELD(0x66F, msLoc[0], 4, 8, sample_pattern[1][0]); + SET_REG_FIELD(0x670, msLoc[0], 4, 12, sample_pattern[1][1]); + SET_REG_FIELD(0x671, msLoc[0], 4, 16, sample_pattern[2][0]); + SET_REG_FIELD(0x672, msLoc[0], 4, 20, sample_pattern[2][1]); + SET_REG_FIELD(0x673, msLoc[0], 8, 24, 1); + + msLoc[1] = 0; + SET_REG_FIELD(0x676, msLoc[1], 4, 0, sample_pattern[3][0]); + SET_REG_FIELD(0x677, msLoc[1], 4, 4, sample_pattern[3][1]); + SET_REG_FIELD(0x678, msLoc[1], 4, 8, sample_pattern[4][0]); + SET_REG_FIELD(0x679, msLoc[1], 4, 12, sample_pattern[4][1]); + SET_REG_FIELD(0x67A, msLoc[1], 4, 16, sample_pattern[5][0]); + SET_REG_FIELD(0x67B, msLoc[1], 4, 20, sample_pattern[5][1]); + SET_REG_FIELD(0x67C, msLoc[1], 8, 24, 2); + + msLoc[2] = 0; + SET_REG_FIELD(0x67F, msLoc[2], 4, 0, sample_pattern[6][0]); + SET_REG_FIELD(0x680, msLoc[2], 4, 4, sample_pattern[6][1]); + SET_REG_FIELD(0x681, msLoc[2], 4, 8, sample_pattern[7][0]); + SET_REG_FIELD(0x682, msLoc[2], 4, 12, sample_pattern[7][1]); + SET_REG_FIELD(0x683, msLoc[2], 4, 16, sample_pattern[8][0]); + SET_REG_FIELD(0x684, msLoc[2], 4, 20, sample_pattern[8][1]); + SET_REG_FIELD(0x685, msLoc[2], 8, 24, 3); + + msLoc[3] = 0; + SET_REG_FIELD(0x688, msLoc[3], 4, 0, sample_pattern[9][0]); + SET_REG_FIELD(0x689, msLoc[3], 4, 4, sample_pattern[9][1]); + SET_REG_FIELD(0x68A, msLoc[3], 4, 8, sample_pattern[10][0]); + SET_REG_FIELD(0x68B, msLoc[3], 4, 12, sample_pattern[10][1]); + SET_REG_FIELD(0x68C, msLoc[3], 4, 16, sample_pattern[11][0]); + SET_REG_FIELD(0x68D, msLoc[3], 4, 20, sample_pattern[11][1]); + SET_REG_FIELD(0x68E, msLoc[3], 8, 24, 4); + } + else { + msLoc[0] = 0x01666666; + msLoc[1] = 0x02666666; + msLoc[2] = 0x03666666; + msLoc[3] = 0x04666666; + } + GX_WRITE_RAS_REG(msLoc[0]); + GX_WRITE_RAS_REG(msLoc[1]); + GX_WRITE_RAS_REG(msLoc[2]); + GX_WRITE_RAS_REG(msLoc[3]); + + coeff0 = 0; + SET_REG_FIELD(0, coeff0, 8, 24, 0x53); + coeff1 = 0; + SET_REG_FIELD(0, coeff1, 8, 24, 0x54); + if (vf != 0) { + SET_REG_FIELD(0x6A6, coeff0, 6, 0, vfilter[0]); + SET_REG_FIELD(0x6A7, coeff0, 6, 6, vfilter[1]); + SET_REG_FIELD(0x6A8, coeff0, 6, 12, vfilter[2]); + SET_REG_FIELD(0x6A9, coeff0, 6, 18, vfilter[3]); + SET_REG_FIELD(0x6AA, coeff1, 6, 0, vfilter[4]); + SET_REG_FIELD(0x6AB, coeff1, 6, 6, vfilter[5]); + SET_REG_FIELD(0x6AC, coeff1, 6, 12, vfilter[6]); + } + else { + SET_REG_FIELD(0, coeff0, 6, 0, 0); + SET_REG_FIELD(0, coeff0, 6, 6, 0); + SET_REG_FIELD(0, coeff0, 6, 12, 21); + SET_REG_FIELD(0, coeff0, 6, 18, 22); + SET_REG_FIELD(0, coeff1, 6, 0, 21); + SET_REG_FIELD(0, coeff1, 6, 6, 0); + SET_REG_FIELD(0, coeff1, 6, 12, 0); + } + GX_WRITE_RAS_REG(coeff0); + GX_WRITE_RAS_REG(coeff1); + gx->bpSentNot = 0; +} + +void GXSetDispCopyGamma(GXGamma gamma) +{ + CHECK_GXBEGIN(0x6CD, "GXSetDispCopyGamma"); + SET_REG_FIELD(0x6CE, gx->cpDisp, 2, 7, gamma); +} + +#if DEBUG +static void __GXVerifCopy(void *dest, u8 clear) +{ + u8 clmpT; + u8 clmpB; + u32 x0; + u32 y0; + u32 dx; + u32 dy; + + CHECK_GXBEGIN(0x6E2, "GXCopyDisp"); + + clmpT = GET_REG_FIELD(gx->cpDisp, 1, 0); + clmpB = (u32)GET_REG_FIELD(gx->cpDisp, 1, 1); + x0 = GET_REG_FIELD(gx->cpDispSrc, 10, 0); + dx = GET_REG_FIELD(gx->cpDispSize, 10, 0) + 1; + y0 = GET_REG_FIELD(gx->cpDispSrc, 10, 10); + dy = GET_REG_FIELD(gx->cpDispSize, 10, 10) + 1; + + ASSERTMSGLINE(0x6EC, clmpT || y0 != 0, "GXCopy: Have to set GX_CLAMP_TOP if source top == 0"); + ASSERTMSGLINE(0x6EE, clmpB || y0 + dy <= 528, "GXCopy: Have to set GX_CLAMP_BOTTOM if source bottom > 528"); + ASSERTMSGLINE(0x6F3, (gx->peCtrl & 7) != 3 || clear == 0, "GXCopy: Can not do clear while pixel type is Z"); + if ((u32)(gx->peCtrl & 7) == 5) { + ASSERTMSGLINE(0x6F9, clear == 0, "GXCopy: Can not clear YUV framebuffer"); + ASSERTMSGLINE(0x6FB, (x0 & 3) == 0, "GXCopy: Source x is not multiple of 4 for YUV copy"); + ASSERTMSGLINE(0x6FD, (y0 & 3) == 0, "GXCopy: Source y is not multiple of 4 for YUV copy"); + ASSERTMSGLINE(0x6FF, (dx & 3) == 0, "GXCopy: Source width is not multiple of 4 for YUV copy"); + ASSERTMSGLINE(0x701, (dy & 3) == 0, "GXCopy: Source height is not multiple of 4 for YUV copy"); + } + else { + ASSERTMSGLINE(0x705, (x0 & 1) == 0, "GXCopy: Source x is not multiple of 2 for RGB copy"); + ASSERTMSGLINE(0x707, (y0 & 1) == 0, "GXCopy: Source y is not multiple of 2 for RGB copy"); + ASSERTMSGLINE(0x709, (dx & 1) == 0, "GXCopy: Source width is not multiple of 2 for RGB copy"); + ASSERTMSGLINE(0x70B, (dy & 1) == 0, "GXCopy: Source height is not multiple of 2 for RGB copy"); + } + ASSERTMSGLINE(0x70F, ((u32)dest & 0x1F) == 0, "GXCopy: Display destination address not 32B aligned"); +} +#endif + +void GXCopyDisp(void *dest, GXBool clear) +{ + u32 reg; + u32 tempPeCtrl; + u32 phyAddr; + u8 changePeCtrl; + + CHECK_GXBEGIN(0x729, "GXCopyDisp"); + +#if DEBUG + __GXVerifCopy(dest, clear); +#endif + if (clear) { + reg = gx->zmode; + SET_REG_FIELD(0, reg, 1, 0, 1); + SET_REG_FIELD(0, reg, 3, 1, 7); + GX_WRITE_RAS_REG(reg); + + reg = gx->cmode0; + SET_REG_FIELD(0, reg, 1, 0, 0); + SET_REG_FIELD(0, reg, 1, 1, 0); + GX_WRITE_RAS_REG(reg); + } + changePeCtrl = FALSE; + if ((clear || (u32)GET_REG_FIELD(gx->peCtrl, 3, 0) == 3) && (u32)GET_REG_FIELD(gx->peCtrl, 1, 6) == 1) { + changePeCtrl = TRUE; + tempPeCtrl = gx->peCtrl; + SET_REG_FIELD(0, tempPeCtrl, 1, 6, 0); + GX_WRITE_RAS_REG(tempPeCtrl); + } + GX_WRITE_RAS_REG(gx->cpDispSrc); + GX_WRITE_RAS_REG(gx->cpDispSize); + GX_WRITE_RAS_REG(gx->cpDispStride); + + phyAddr = (u32)dest & 0x3FFFFFFF; + reg = 0; + SET_REG_FIELD(0x750, reg, 21, 0, phyAddr >> 5); + SET_REG_FIELD(0x754, reg, 8, 24, 0x4B); + GX_WRITE_RAS_REG(reg); + + SET_REG_FIELD(0x754, gx->cpDisp, 1, 11, clear); + SET_REG_FIELD(0x754, gx->cpDisp, 1, 14, 1); + SET_REG_FIELD(0x754, gx->cpDisp, 8, 24, 0x52); + GX_WRITE_RAS_REG(gx->cpDisp); + + if (clear) { + GX_WRITE_RAS_REG(gx->zmode); + GX_WRITE_RAS_REG(gx->cmode0); + } + if (changePeCtrl) { + GX_WRITE_RAS_REG(gx->peCtrl); + } + gx->bpSentNot = 0; +} + +void GXCopyTex(void *dest, GXBool clear) +{ + u32 reg; + u32 tempPeCtrl; + u32 phyAddr; + u8 changePeCtrl; + + CHECK_GXBEGIN(0x77C, "GXCopyTex"); + +#if DEBUG + __GXVerifCopy(dest, clear); +#endif + if (clear) { + reg = gx->zmode; + SET_REG_FIELD(0, reg, 1, 0, 1); + SET_REG_FIELD(0, reg, 3, 1, 7); + GX_WRITE_RAS_REG(reg); + + reg = gx->cmode0; + SET_REG_FIELD(0, reg, 1, 0, 0); + SET_REG_FIELD(0, reg, 1, 1, 0); + GX_WRITE_RAS_REG(reg); + } + changePeCtrl = 0; + tempPeCtrl = gx->peCtrl; + if (gx->cpTexZ && ((tempPeCtrl & 7) != 3)) { + changePeCtrl = 1; + SET_REG_FIELD(0, tempPeCtrl, 3, 0, 3); + } + if (((clear != 0) || ((u32)(tempPeCtrl & 7) == 3)) && ((u32)((tempPeCtrl >> 6U) & 1) == 1)) { + changePeCtrl = 1; + SET_REG_FIELD(0, tempPeCtrl, 1, 6, 0); + } + if (changePeCtrl) { + GX_WRITE_RAS_REG(tempPeCtrl); + } + GX_WRITE_RAS_REG(gx->cpTexSrc); + GX_WRITE_RAS_REG(gx->cpTexSize); + GX_WRITE_RAS_REG(gx->cpTexStride); + + phyAddr = (u32)dest & 0x3FFFFFFF; + reg = 0; + SET_REG_FIELD(0x7AD, reg, 21, 0, phyAddr >> 5); + SET_REG_FIELD(0x7AD, reg, 8, 24, 0x4B); + GX_WRITE_RAS_REG(reg); + + SET_REG_FIELD(0x7B1, gx->cpTex, 1, 11, clear); + SET_REG_FIELD(0x7B1, gx->cpTex, 1, 14, 0); + SET_REG_FIELD(0x7B1, gx->cpTex, 8, 24, 0x52); + GX_WRITE_RAS_REG(gx->cpTex); + + if (clear != 0) { + GX_WRITE_RAS_REG(gx->zmode); + GX_WRITE_RAS_REG(gx->cmode0); + } + if (changePeCtrl) { + GX_WRITE_RAS_REG(gx->peCtrl); + } + gx->bpSentNot = 0; +} + +void GXClearBoundingBox(void) +{ + u32 reg; + + CHECK_GXBEGIN(0x7D3, "GXClearBoundingBox"); + reg = 0x550003FF; + GX_WRITE_RAS_REG(reg); + reg = 0x560003FF; + GX_WRITE_RAS_REG(reg); + gx->bpSentNot = 0; +} + +void GXReadBoundingBox(u16 *left, u16 *top, u16 *right, u16 *bottom) +{ + *left = GX_GET_PE_REG(8); + *top = GX_GET_PE_REG(10); + *right = GX_GET_PE_REG(9); + *bottom = GX_GET_PE_REG(11); +} diff --git a/src/dolphin/gx/GXGeometry.c b/src/dolphin/gx/GXGeometry.c new file mode 100644 index 00000000..853e2989 --- /dev/null +++ b/src/dolphin/gx/GXGeometry.c @@ -0,0 +1,146 @@ +#include +#include +#include + +#include + +void __GXSetDirtyState(void) +{ + if (gx->dirtyState & 1) { + __GXSetSUTexRegs(); + } + if (gx->dirtyState & 2) { + __GXUpdateBPMask(); + } + if (gx->dirtyState & 4) { + __GXSetGenMode(); + } + if (gx->dirtyState & 8) { + __GXSetVCD(); + } + if (gx->dirtyState & 0x10) { + __GXSetVAT(); + } + if (gx->dirtyState & 0x18) { + __GXCalculateVLim(); + } + gx->dirtyState = 0; +} + +void GXBegin(GXPrimitive type, GXVtxFmt vtxfmt, u16 nverts) +{ + ASSERTMSGLINE(0x167, vtxfmt < 8, "GXBegin: Format Index is out of range"); + ASSERTMSGLINE(0x168, !__GXinBegin, "GXBegin: called inside another GXBegin/GXEnd"); + + if (gx->dirtyState != 0) { + __GXSetDirtyState(); + } + if (*(u32 *)&gx->vNumNot == 0) { // checks both vNum and bpSentNot + __GXSendFlushPrim(); + } + GX_WRITE_U8(vtxfmt | type); + GX_WRITE_U16(nverts); +} + +void __GXSendFlushPrim(void) +{ + u32 i; + u32 numD = gx->vNum * gx->vLim; + + GX_WRITE_U8(0x98); + GX_WRITE_U16(gx->vNum); + for (i = 0; i < numD; i += 4) { + GX_WRITE_U32(0); + } + gx->bpSentNot = 1; +} + +void GXSetLineWidth(u8 width, GXTexOffset texOffsets) +{ + CHECK_GXBEGIN(0x1B8, "GXSetLineWidth"); + SET_REG_FIELD(0x1B9, gx->lpSize, 8, 0, width); + SET_REG_FIELD(0x1BA, gx->lpSize, 3, 16, texOffsets); + GX_WRITE_RAS_REG(gx->lpSize); + gx->bpSentNot = 0; +} + +void GXGetLineWidth(u8 *width, GXTexOffset *texOffsets) +{ + ASSERTMSGLINE(0x1CF, width != NULL && texOffsets != NULL, "GXGet*: invalid null pointer"); + + *width = GET_REG_FIELD(gx->lpSize, 8, 0); + *texOffsets = GET_REG_FIELD(gx->lpSize, 3, 16); +} + +void GXSetPointSize(u8 pointSize, GXTexOffset texOffsets) +{ + CHECK_GXBEGIN(0x1E4, "GXSetPointSize"); + SET_REG_FIELD(0x1E5, gx->lpSize, 8, 8, pointSize); + SET_REG_FIELD(0x1E6, gx->lpSize, 3, 19, texOffsets); + GX_WRITE_RAS_REG(gx->lpSize); + gx->bpSentNot = 0; +} + +void GXGetPointSize(u8 *pointSize, GXTexOffset *texOffsets) +{ + ASSERTMSGLINE(0x1FB, pointSize != NULL && texOffsets != NULL, "GXGet*: invalid null pointer"); + + *pointSize = (int)GET_REG_FIELD(gx->lpSize, 8, 8); + *texOffsets = GET_REG_FIELD(gx->lpSize, 3, 19); +} + +void GXEnableTexOffsets(GXTexCoordID coord, u8 line_enable, u8 point_enable) +{ + CHECK_GXBEGIN(0x211, "GXEnableTexOffsets"); + + ASSERTMSGLINE(0x213, coord < 8, "GXEnableTexOffsets: Invalid coordinate Id"); + + SET_REG_FIELD(0x215, gx->suTs0[coord], 1, 18, line_enable); + SET_REG_FIELD(0x216, gx->suTs0[coord], 1, 19, point_enable); + GX_WRITE_RAS_REG(gx->suTs0[coord]); + gx->bpSentNot = 0; +} + +void GXSetCullMode(GXCullMode mode) +{ + GXCullMode hwMode; + + CHECK_GXBEGIN(0x21D, "GXSetCullMode"); + switch (mode) { + case GX_CULL_FRONT: + hwMode = GX_CULL_BACK; + break; + case GX_CULL_BACK: + hwMode = GX_CULL_FRONT; + break; + default: + hwMode = mode; + break; + } + SET_REG_FIELD(0x225, gx->genMode, 2, 14, hwMode); + gx->dirtyState |= 4; +} + +void GXGetCullMode(GXCullMode *mode) +{ + GXCullMode hwMode = gx->genMode; + *mode = ((hwMode >> 0xD) & 0x2) | (((((int)hwMode >> 0xE) & 0x2) >> 0x1)); +} + +void GXSetCoPlanar(GXBool enable) +{ + u32 reg; + + CHECK_GXBEGIN(0x265, "GXSetCoPlanar"); + + SET_REG_FIELD(0x267, gx->genMode, 1, 19, enable); + reg = 0xFE080000; + GX_WRITE_RAS_REG(reg); + GX_WRITE_RAS_REG(gx->genMode); +} + +void __GXSetGenMode(void) +{ + GX_WRITE_RAS_REG(gx->genMode); + gx->bpSentNot = 0; +} diff --git a/src/dolphin/gx/GXInit.c b/src/dolphin/gx/GXInit.c new file mode 100644 index 00000000..82874fab --- /dev/null +++ b/src/dolphin/gx/GXInit.c @@ -0,0 +1,372 @@ +#include + +#include +#include +#include +#include + +#include + +void __GXInitGX(); + +static struct __GXData_struct gxData; +struct __GXData_struct *gx = &gxData; +// DWARF info lists all of these as "void *", but these types make more sense. +u16 *__memReg; +u16 *__peReg; +u16 *__cpReg; +u32 *__piReg; + +// clang-format off +asm BOOL IsWriteGatherBufferEmpty(void) +{ + sync + mfspr r3, WPAR + andi. r3, r3, 1 +} +// clang-format on + +static void EnableWriteGatherPipe(void) +{ + u32 hid2 = PPCMfhid2(); + + PPCMtwpar(OSUncachedToPhysical((void *)GXFIFO_ADDR)); + hid2 |= 0x40000000; + PPCMthid2(hid2); +} + +static void DisableWriteGatherPipe(void) +{ + u32 hid2 = PPCMfhid2(); + + hid2 &= ~0x40000000; + PPCMthid2(hid2); +} + +static GXTexRegion *__GXDefaultTexRegionCallback(GXTexObj *t_obj, GXTexMapID unused) +{ + GXTexFmt fmt = GXGetTexObjFmt(t_obj); + + if (fmt != GX_TF_C4 && fmt != GX_TF_C8 && fmt != GX_TF_C14X2) { + return &gx->TexRegions[gx->nextTexRgn++ & 7]; + } + else { + return &gx->TexRegionsCI[gx->nextTexRgnCI++ & 3]; + } +} + +static GXTlutRegion *__GXDefaultTlutRegionCallback(u32 idx) +{ + if (idx >= 0x14U) { + return NULL; + } + return &gx->TlutRegions[idx]; +} + +GXFifoObj FifoObj; + +GXFifoObj *GXInit(void *base, u32 size) +{ + u32 i; + u32 reg; + u32 freqBase; + + // OSRegisterVersion(__GXVersion); + + gx->inDispList = FALSE; + gx->dlSaveContext = TRUE; + // gx->abtWaitPECopy = 1; +#if DEBUG + __GXinBegin = FALSE; +#endif + gx->tcsManEnab = FALSE; + gx->tevTcEnab = FALSE; + + GXSetMisc(GX_MT_XF_FLUSH, 0); + + __piReg = OSPhysicalToUncached(0xC003000); + __cpReg = OSPhysicalToUncached(0xC000000); + __peReg = OSPhysicalToUncached(0xC001000); + __memReg = OSPhysicalToUncached(0xC004000); + // __GXFifoInit(); + // GXInitFifoBase(&FifoObj, base, size); + // GXSetCPUFifo(&FifoObj); + // GXSetGPFifo(&FifoObj); + + // if (!resetFuncRegistered) { + // OSRegisterResetFunction(&GXResetFuncInfo); + // resetFuncRegistered = 1; + // } + + // __GXPEInit(); + // EnableWriteGatherPipe(); + + gx->genMode = 0; + SET_REG_FIELD(0, gx->genMode, 8, 24, 0); + gx->bpMask = 255; + SET_REG_FIELD(0, gx->bpMask, 8, 24, 0x0F); + gx->lpSize = 0; + SET_REG_FIELD(0, gx->lpSize, 8, 24, 0x22); + for (i = 0; i < 16; ++i) { + gx->tevc[i] = 0; + gx->teva[i] = 0; + gx->tref[i / 2] = 0; + gx->texmapId[i] = GX_TEXMAP_NULL; + SET_REG_FIELD(0x46A, gx->tevc[i], 8, 24, 0xC0 + i * 2); + SET_REG_FIELD(0x46B, gx->teva[i], 8, 24, 0xC1 + i * 2); + SET_REG_FIELD(0x46D, gx->tevKsel[i / 2], 8, 24, 0xF6 + i / 2); + SET_REG_FIELD(0x46F, gx->tref[i / 2], 8, 24, 0x28 + i / 2); + } + gx->iref = 0; + SET_REG_FIELD(0, gx->iref, 8, 24, 0x27); + for (i = 0; i < 8; ++i) { + gx->suTs0[i] = 0; + gx->suTs1[i] = 0; + SET_REG_FIELD(0x478, gx->suTs0[i], 8, 24, 0x30 + i * 2); + SET_REG_FIELD(0x479, gx->suTs1[i], 8, 24, 0x31 + i * 2); + } + SET_REG_FIELD(0, gx->suScis0, 8, 24, 0x20); + SET_REG_FIELD(0, gx->suScis1, 8, 24, 0x21); + SET_REG_FIELD(0, gx->cmode0, 8, 24, 0x41); + SET_REG_FIELD(0, gx->cmode1, 8, 24, 0x42); + SET_REG_FIELD(0, gx->zmode, 8, 24, 0x40); + SET_REG_FIELD(0, gx->peCtrl, 8, 24, 0x43); + SET_REG_FIELD(0, gx->cpTex, 2, 7, 0); + + // gx->zScale = 1.6777216E7f; + // gx->zOffset = 0.0f; + gx->dirtyState = 0; + gx->dirtyVAT = FALSE; +#if DEBUG + __gxVerif->verifyLevel = GX_WARN_NONE; + GXSetVerifyCallback((GXVerifyCallback)__GXDefaultVerifyCallback); + for (i = 0; i < 256; i++) { + SET_REG_FIELD(0, __gxVerif->rasRegs[i], 8, 24, 0xFF); + } + memset(__gxVerif->xfRegsDirty, 0, 0x50); + memset(__gxVerif->xfMtxDirty, 0, 0x100); + memset(__gxVerif->xfNrmDirty, 0, 0x60); + memset(__gxVerif->xfLightDirty, 0, 0x80); +#endif + freqBase = __OSBusClock / 500; + // __GXFlushTextureState(); + reg = (freqBase >> 11) | 0x400 | 0x69000000; + GX_WRITE_RAS_REG(reg); + + // __GXFlushTextureState(); + reg = (freqBase / 0x1080) | 0x200 | 0x46000000; + GX_WRITE_RAS_REG(reg); + + // __GXInitRevisionBits(); + + // for (i = 0; i < 8; i++) { + // GXInitTexCacheRegion(&gx->TexRegions0[i], GX_FALSE, GXTexRegionAddrTable[i], + // GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 8], GX_TEXCACHE_32K); + // GXInitTexCacheRegion(&gx->TexRegions1[i], GX_FALSE, GXTexRegionAddrTable[i + 16], + // GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 24], GX_TEXCACHE_32K); + // GXInitTexCacheRegion(&gx->TexRegions2[i], GX_TRUE, GXTexRegionAddrTable[i + 32], + // GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 40], GX_TEXCACHE_32K); + // } + + // for (i = 0; i < 16; i++) { + // GXInitTlutRegion(&gx->TlutRegions[i], 0xC0000 + 0x2000 * i, GX_TLUT_256); + // } + + // for (i = 0; i < 4; i++) { + // GXInitTlutRegion(&gx->TlutRegions[i + 16], 0xE0000 + 0x8000 * i, GX_TLUT_1K); + // } + + { + u32 reg = 0; +#if DEBUG + s32 regAddr; +#endif + GX_SET_CP_REG(3, reg); + + SET_REG_FIELD(0, gx->perfSel, 4, 4, 0); + GX_WRITE_U8(0x8); + GX_WRITE_U8(0x20); + GX_WRITE_U32(gx->perfSel); +#if DEBUG + regAddr = -12; +#endif + + reg = 0; + GX_WRITE_XF_REG(6, reg); + + reg = 0x23000000; + GX_WRITE_RAS_REG(reg); + + reg = 0x24000000; + GX_WRITE_RAS_REG(reg); + + reg = 0x67000000; + GX_WRITE_RAS_REG(reg); + } + + __GXSetIndirectMask(0); + __GXSetTmemConfig(2); + __GXInitGX(); + + return &FifoObj; +} + +void __GXInitGX() +{ + GXRenderModeObj *rmode; + GXAttr var_r30; + f32 identity_mtx[3][4]; + GXColor clear = { 64, 64, 64, 255 }; + GXColor black = { 0, 0, 0, 0 }; + GXColor white = { 255, 255, 255, 255 }; + u32 i; + + switch (VIGetTvFormat()) { + case 0: + rmode = &GXNtsc480IntDf; + break; + case 1: + rmode = &GXPal528IntDf; + break; + case 5: + rmode = &GXEurgb60Hz480IntDf; + break; + case 2: + rmode = &GXMpal480IntDf; + break; + default: + rmode = &GXNtsc480IntDf; + break; + } + + GXSetCopyClear(clear, 0xFFFFFF); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, 0x3CU); + GXSetNumTexGens(1); + GXClearVtxDesc(); + GXInvalidateVtxCache(); + for (var_r30 = GX_VA_POS; (u32)var_r30 <= 0x18; var_r30++) { + GXSetArray(var_r30, gx, 0); + } + GXSetLineWidth(6, 0); + GXSetPointSize(6, 0); + GXEnableTexOffsets(0, 0, 0); + GXEnableTexOffsets(1, 0, 0); + GXEnableTexOffsets(2, 0, 0); + GXEnableTexOffsets(3, 0, 0); + GXEnableTexOffsets(4, 0, 0); + GXEnableTexOffsets(5, 0, 0); + GXEnableTexOffsets(6, 0, 0); + GXEnableTexOffsets(7, 0, 0); + identity_mtx[0][0] = 1.0f; + identity_mtx[0][1] = 0.0f; + identity_mtx[0][2] = 0.0f; + identity_mtx[0][3] = 0.0f; + identity_mtx[1][0] = 0.0f; + identity_mtx[1][1] = 1.0f; + identity_mtx[1][2] = 0.0f; + identity_mtx[1][3] = 0.0f; + identity_mtx[2][0] = 0.0f; + identity_mtx[2][1] = 0.0f; + identity_mtx[2][2] = 1.0f; + identity_mtx[2][3] = 0.0f; + GXLoadPosMtxImm(identity_mtx, GX_PNMTX0); + GXLoadNrmMtxImm(identity_mtx, GX_PNMTX0); + GXSetCurrentMtx(GX_PNMTX0); + GXLoadTexMtxImm(identity_mtx, GX_IDENTITY, GX_MTX3x4); + GXLoadTexMtxImm(identity_mtx, GX_PTIDENTITY, GX_MTX3x4); + GXSetViewport(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f); + GXSetCoPlanar(GX_DISABLE); + GXSetCullMode(GX_CULL_BACK); + GXSetClipMode(GX_CLIP_ENABLE); + GXSetScissor(0, 0, rmode->fbWidth, rmode->efbHeight); + GXSetScissorBoxOffset(0, 0); + GXSetNumChans(0); + GXSetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetChanAmbColor(GX_COLOR0A0, black); + GXSetChanMatColor(GX_COLOR0A0, white); + GXSetChanCtrl(GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetChanAmbColor(GX_COLOR1A1, black); + GXSetChanMatColor(GX_COLOR1A1, white); + GXInvalidateTexAll(); + gx->nextTexRgnCI = gx->nextTexRgn = i = GX_TEVSTAGE0; + GXSetTexRegionCallback((void *)__GXDefaultTexRegionCallback); + GXSetTlutRegionCallback(__GXDefaultTlutRegionCallback); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE8, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE9, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE10, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE11, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE12, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE13, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE14, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE15, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + + GXSetNumTevStages(1); + GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0); + for (; i < GX_MAX_TEVSTAGE; i++) { + GXSetTevKColorSel((GXTevStageID)i, GX_TEV_KCSEL_1_4); + GXSetTevKAlphaSel((GXTevStageID)i, GX_TEV_KASEL_1); + GXSetTevSwapMode((GXTevStageID)i, GX_TEV_SWAP0, GX_TEV_SWAP0); + } + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA); + + for (i = GX_TEVSTAGE0; i < GX_MAX_TEVSTAGE; i++) + GXSetTevDirect((GXTevStageID)i); + GXSetNumIndStages(0); + GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE1, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE2, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE3, GX_ITS_1, GX_ITS_1); + + GXSetFog(GX_FOG_NONE, 0.0f, 1.0f, 0.1f, 1.0f, black); + GXSetFogRangeAdj(GX_DISABLE, 0, 0); + GXSetBlendMode(GX_BM_NONE, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + GXSetColorUpdate(GX_ENABLE); + GXSetAlphaUpdate(GX_ENABLE); + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GXSetZCompLoc(GX_TRUE); + GXSetDither(GX_ENABLE); + GXSetDstAlpha(GX_DISABLE, 0); + GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + GXSetFieldMask(GX_ENABLE, GX_ENABLE); + GXSetFieldMode(rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE)); + + GXSetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight); + GXSetDispCopyDst(rmode->fbWidth, rmode->efbHeight); + GXSetDispCopyYScale((f32)(rmode->xfbHeight) / (f32)(rmode->efbHeight)); + GXSetCopyClamp((GXFBClamp)(GX_CLAMP_TOP | GX_CLAMP_BOTTOM)); + GXSetCopyFilter(rmode->aa, rmode->sample_pattern, GX_TRUE, rmode->vfilter); + GXSetDispCopyGamma(GX_GM_1_0); + GXSetDispCopyFrame2Field(GX_COPY_PROGRESSIVE); + GXClearBoundingBox(); + + GXPokeColorUpdate(GX_TRUE); + GXPokeAlphaUpdate(GX_TRUE); + GXPokeDither(GX_FALSE); + GXPokeBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ONE, GX_LO_SET); + GXPokeAlphaMode(GX_ALWAYS, 0); + GXPokeAlphaRead(GX_READ_FF); + GXPokeDstAlpha(GX_DISABLE, 0); + GXPokeZMode(GX_TRUE, GX_ALWAYS, GX_TRUE); + GXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE); + GXClearGPMetric(); +} diff --git a/src/dolphin/gx/GXLight.c b/src/dolphin/gx/GXLight.c new file mode 100644 index 00000000..a084fd84 --- /dev/null +++ b/src/dolphin/gx/GXLight.c @@ -0,0 +1,620 @@ +#include +#include + +#include + +float cosf(float x); +inline float sqrtf(float x) +{ + static const double _half = .5; + static const double _three = 3.0; + volatile float y; + if (x > 0.0f) + { + double guess = __frsqrte((double)x); // returns an approximation to + guess = _half*guess*(_three - guess*guess*x); // now have 12 sig bits + guess = _half*guess*(_three - guess*guess*x); // now have 24 sig bits + guess = _half*guess*(_three - guess*guess*x); // now have 32 sig bits + y = (float)(x*guess); + return y ; + } + return x; +} + +// GXLightObj private data +struct __GXLightObjInt_struct { + u32 reserved[3]; + u32 Color; + f32 a[3]; + f32 k[3]; + f32 lpos[3]; + f32 ldir[3]; +}; + +void GXInitLightAttn(GXLightObj *lt_obj, f32 a0, f32 a1, f32 a2, f32 k0, f32 k1, f32 k2) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x62, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x63, "GXInitLightAttn"); + obj->a[0] = a0; + obj->a[1] = a1; + obj->a[2] = a2; + obj->k[0] = k0; + obj->k[1] = k1; + obj->k[2] = k2; +} + +void GXInitLightAttnA(GXLightObj *lt_obj, f32 a0, f32 a1, f32 a2) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x70, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x71, "GXInitLightAttnA"); + obj->a[0] = a0; + obj->a[1] = a1; + obj->a[2] = a2; +} + +void GXGetLightAttnA(GXLightObj *lt_obj, f32 *a0, f32 *a1, f32 *a2) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x7A, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x7B, "GXGetLightAttnA"); + *a0 = obj->a[0]; + *a1 = obj->a[1]; + *a2 = obj->a[2]; +} + +void GXInitLightAttnK(GXLightObj *lt_obj, f32 k0, f32 k1, f32 k2) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x84, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x85, "GXInitLightAttnK"); + obj->k[0] = k0; + obj->k[1] = k1; + obj->k[2] = k2; +} + +void GXGetLightAttnK(GXLightObj *lt_obj, f32 *k0, f32 *k1, f32 *k2) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x8E, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x8F, "GXGetLightAttnK"); + *k0 = obj->k[0]; + *k1 = obj->k[1]; + *k2 = obj->k[2]; +} + +void GXInitLightSpot(GXLightObj *lt_obj, f32 cutoff, GXSpotFn spot_func) +{ + float a0, a1, a2; + float d; + float cr; + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0xA7, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0xA9, "GXInitLightSpot"); + + if (cutoff <= 0.0f || cutoff > 90.0f) + spot_func = GX_SP_OFF; + + cr = cosf((3.1415927f * cutoff) / 180.0f); + switch (spot_func) { + case GX_SP_FLAT: + a0 = -1000.0f * cr; + a1 = 1000.0f; + a2 = 0.0f; + break; + case GX_SP_COS: + a0 = -cr / (1.0f - cr); + a1 = 1.0f / (1.0f - cr); + a2 = 0.0f; + break; + case GX_SP_COS2: + a0 = 0.0f; + a1 = -cr / (1.0f - cr); + a2 = 1.0f / (1.0f - cr); + break; + case GX_SP_SHARP: + d = (1.0f - cr) * (1.0f - cr); + a0 = (cr * (cr - 2.0f)) / d; + a1 = 2.0f / d; + a2 = -1.0f / d; + break; + case GX_SP_RING1: + d = (1.0f - cr) * (1.0f - cr); + a0 = (-4.0f * cr) / d; + a1 = (4.0f * (1.0f + cr)) / d; + a2 = -4.0f / d; + break; + case GX_SP_RING2: + d = (1.0f - cr) * (1.0f - cr); + a0 = 1.0f - ((2.0f * cr * cr) / d); + a1 = (4.0f * cr) / d; + a2 = -2.0f / d; + break; + case GX_SP_OFF: + default: + a0 = 1.0f; + a1 = 0.0f; + a2 = 0.0f; + break; + } + obj->a[0] = a0; + obj->a[1] = a1; + obj->a[2] = a2; +} + +void GXInitLightDistAttn(GXLightObj *lt_obj, f32 ref_dist, f32 ref_br, GXDistAttnFn dist_func) +{ + f32 k0, k1, k2; + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0xF2, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0xF4, "GXInitLightDistAttn"); + + if (ref_dist < 0.0f) + dist_func = GX_DA_OFF; + if (ref_br <= 0.0f || ref_br >= 1.0f) + dist_func = GX_DA_OFF; + + switch (dist_func) { + case GX_DA_GENTLE: + k0 = 1.0f; + k1 = (1.0f - ref_br) / (ref_br * ref_dist); + k2 = 0.0f; + break; + case GX_DA_MEDIUM: + k0 = 1.0f; + k1 = (0.5f * (1.0f - ref_br)) / (ref_br * ref_dist); + k2 = (0.5f * (1.0f - ref_br)) / (ref_br * ref_dist * ref_dist); + break; + case GX_DA_STEEP: + k0 = 1.0f; + k1 = 0.0f; + k2 = (1.0f - ref_br) / (ref_br * ref_dist * ref_dist); + break; + case GX_DA_OFF: + default: + k0 = 1.0f; + k1 = 0.0f; + k2 = 0.0f; + break; + } + + obj->k[0] = k0; + obj->k[1] = k1; + obj->k[2] = k2; +} + +void GXInitLightPos(GXLightObj *lt_obj, f32 x, f32 y, f32 z) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x129, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x12B, "GXInitLightPos"); + + obj->lpos[0] = x; + obj->lpos[1] = y; + obj->lpos[2] = z; +} + +void GXGetLightPos(const GXLightObj *lt_obj, f32 *x, f32 *y, f32 *z) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x134, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x136, "GXGetLightPos"); + + *x = obj->lpos[0]; + *y = obj->lpos[1]; + *z = obj->lpos[2]; +} + +void GXInitLightDir(GXLightObj *lt_obj, f32 nx, f32 ny, f32 nz) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x149, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + + obj->ldir[0] = -nx; + obj->ldir[1] = -ny; + obj->ldir[2] = -nz; +} + +void GXGetLightDir(GXLightObj *lt_obj, f32 *nx, f32 *ny, f32 *nz) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x155, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + + *nx = -obj->ldir[0]; + *ny = -obj->ldir[1]; + *nz = -obj->ldir[2]; +} + +void GXInitSpecularDir(GXLightObj *lt_obj, f32 nx, f32 ny, f32 nz) +{ + float mag; + float vx; + float vy; + float vz; + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x16F, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x170, "GXInitSpecularDir"); + + vx = -nx; + vy = -ny; + vz = -nz + 1.0f; + mag = 1.0f / sqrtf((vx * vx) + (vy * vy) + (vz * vz)); + obj->ldir[0] = vx * mag; + obj->ldir[1] = vy * mag; + obj->ldir[2] = vz * mag; + obj->lpos[0] = -nx * 1048576.0f; + obj->lpos[1] = -ny * 1048576.0f; + obj->lpos[2] = -nz * 1048576.0f; +} + +void GXInitSpecularDirHA(GXLightObj *lt_obj, f32 nx, f32 ny, f32 nz, f32 hx, f32 hy, f32 hz) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x18E, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x18F, "GXInitSpecularHA"); + + obj->ldir[0] = hx; + obj->ldir[1] = hy; + obj->ldir[2] = hz; + obj->lpos[0] = -nx * 1048576.0f; + obj->lpos[1] = -ny * 1048576.0f; + obj->lpos[2] = -nz * 1048576.0f; +} + +void GXInitLightColor(GXLightObj *lt_obj, GXColor color) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x1A8, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x1A9, "GXInitLightColor"); + + obj->Color = (color.r << 24) | (color.g << 16) | (color.b << 8) | color.a; +} + +void GXGetLightColor(const GXLightObj *lt_obj, GXColor *color) +{ + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x1B2, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x1B3, "GXGetLightColor"); + + color->r = (obj->Color >> 24) & 0xFF; + color->g = (obj->Color >> 16) & 0xFF; + color->b = (obj->Color >> 8) & 0xFF; + color->a = obj->Color & 0xFF; +} + +#if DEBUG +#define WRITE_SOME_LIGHT_REG1(val, addr) \ + do { \ + u32 xfData = val; \ + GX_WRITE_U32(val); \ + VERIF_MTXLIGHT(addr, xfData); \ + } while (0) + +#define WRITE_SOME_LIGHT_REG2(val, addr) \ + do { \ + f32 xfData = val; \ + GX_WRITE_F32(val); \ + VERIF_MTXLIGHT(addr, *(u32 *)&xfData); \ + } while (0) +#else +#define WRITE_SOME_LIGHT_REG1(val, addr) GX_WRITE_U32(val) +#define WRITE_SOME_LIGHT_REG2(val, addr) GX_WRITE_F32(val) +#endif + +void GXLoadLightObjImm(GXLightObj *lt_obj, GXLightID light) +{ + unsigned long addr; + unsigned long idx; + struct __GXLightObjInt_struct *obj; + + ASSERTMSGLINE(0x1C9, lt_obj != NULL, "Light Object Pointer is null"); + obj = (struct __GXLightObjInt_struct *)lt_obj; + CHECK_GXBEGIN(0x1CA, "GXLoadLightObjImm"); + + switch (light) { + case GX_LIGHT0: + idx = 0; + break; + case GX_LIGHT1: + idx = 1; + break; + case GX_LIGHT2: + idx = 2; + break; + case GX_LIGHT3: + idx = 3; + break; + case GX_LIGHT4: + idx = 4; + break; + case GX_LIGHT5: + idx = 5; + break; + case GX_LIGHT6: + idx = 6; + break; + case GX_LIGHT7: + idx = 7; + break; + default: + idx = 0; + ASSERTMSGLINE(0x1DA, 0, "GXLoadLightStateImm: Invalid Light Id"); + break; + } + + addr = idx * 0x10 + 0x600; + GX_WRITE_U8(0x10); + GX_WRITE_U32(addr | 0xF0000); + + WRITE_SOME_LIGHT_REG1(0, addr); + WRITE_SOME_LIGHT_REG1(0, addr + 1); + WRITE_SOME_LIGHT_REG1(0, addr + 2); + WRITE_SOME_LIGHT_REG1(obj->Color, addr + 3); + WRITE_SOME_LIGHT_REG2(obj->a[0], addr + 4); + WRITE_SOME_LIGHT_REG2(obj->a[1], addr + 5); + WRITE_SOME_LIGHT_REG2(obj->a[2], addr + 6); + WRITE_SOME_LIGHT_REG2(obj->k[0], addr + 7); + WRITE_SOME_LIGHT_REG2(obj->k[1], addr + 8); + WRITE_SOME_LIGHT_REG2(obj->k[2], addr + 9); + WRITE_SOME_LIGHT_REG2(obj->lpos[0], addr + 10); + WRITE_SOME_LIGHT_REG2(obj->lpos[1], addr + 11); + WRITE_SOME_LIGHT_REG2(obj->lpos[2], addr + 12); + WRITE_SOME_LIGHT_REG2(obj->ldir[0], addr + 13); + WRITE_SOME_LIGHT_REG2(obj->ldir[1], addr + 14); + WRITE_SOME_LIGHT_REG2(obj->ldir[2], addr + 15); + + gx->bpSentNot = 1; +} + +void GXLoadLightObjIndx(u32 lt_obj_indx, GXLightID light) +{ + unsigned long reg; + unsigned long addr; + unsigned long idx; + + CHECK_GXBEGIN(0x209, "GXLoadLightObjIndx"); + + switch (light) { + case GX_LIGHT0: + idx = 0; + break; + case GX_LIGHT1: + idx = 1; + break; + case GX_LIGHT2: + idx = 2; + break; + case GX_LIGHT3: + idx = 3; + break; + case GX_LIGHT4: + idx = 4; + break; + case GX_LIGHT5: + idx = 5; + break; + case GX_LIGHT6: + idx = 6; + break; + case GX_LIGHT7: + idx = 7; + break; + default: + idx = 0; + ASSERTMSGLINE(0x216, 0, "GXLoadLightObjIndx: Invalid Light Id"); + break; + } + + addr = idx * 0x10 + 0x600; + reg = 0; + SET_REG_FIELD(0x21C, reg, 12, 0, addr); + SET_REG_FIELD(0x21D, reg, 4, 12, 0xF); + SET_REG_FIELD(0x21E, reg, 16, 16, lt_obj_indx); + GX_WRITE_U8(0x38); + GX_WRITE_U32(reg); +#if DEBUG + __GXShadowIndexState(7, reg); +#endif + gx->bpSentNot = 1; +} + +void GXSetChanAmbColor(GXChannelID chan, GXColor amb_color) +{ + u32 reg = 0; + u32 colIdx; + u32 alpha; + + CHECK_GXBEGIN(0x239, "GXSetChanAmbColor"); + + switch (chan) { + case GX_COLOR0: + alpha = gx->ambColor[0] & 0xFF; + SET_REG_FIELD(0x23E, reg, 8, 0, alpha); + SET_REG_FIELD(0x23F, reg, 8, 8, amb_color.b); + SET_REG_FIELD(0x240, reg, 8, 16, amb_color.g); + SET_REG_FIELD(0x241, reg, 8, 24, amb_color.r); + colIdx = 0; + break; + case GX_COLOR1: + alpha = gx->ambColor[1] & 0xFF; + SET_REG_FIELD(0x247, reg, 8, 0, alpha); + SET_REG_FIELD(0x248, reg, 8, 8, amb_color.b); + SET_REG_FIELD(0x249, reg, 8, 16, amb_color.g); + SET_REG_FIELD(0x24A, reg, 8, 24, amb_color.r); + colIdx = 1; + break; + case GX_ALPHA0: + reg = gx->ambColor[0]; + SET_REG_FIELD(0x250, reg, 8, 0, amb_color.a); + colIdx = 0; + break; + case GX_ALPHA1: + reg = gx->ambColor[1]; + SET_REG_FIELD(0x256, reg, 8, 0, amb_color.a); + colIdx = 1; + break; + case GX_COLOR0A0: + SET_REG_FIELD(0x25B, reg, 8, 0, amb_color.a); + SET_REG_FIELD(0x25C, reg, 8, 8, amb_color.b); + SET_REG_FIELD(0x25D, reg, 8, 16, amb_color.g); + SET_REG_FIELD(0x25E, reg, 8, 24, amb_color.r); + colIdx = 0; + break; + case GX_COLOR1A1: + SET_REG_FIELD(0x263, reg, 8, 0, amb_color.a); + SET_REG_FIELD(0x264, reg, 8, 8, amb_color.b); + SET_REG_FIELD(0x265, reg, 8, 16, amb_color.g); + SET_REG_FIELD(0x266, reg, 8, 24, amb_color.r); + colIdx = 1; + break; + default: + ASSERTMSGLINE(0x26B, 0, "GXSetChanAmbColor: Invalid Channel Id"); + return; + } + + GX_WRITE_XF_REG(colIdx + 10, reg); + gx->bpSentNot = 1; + gx->ambColor[colIdx] = reg; +} + +void GXSetChanMatColor(GXChannelID chan, GXColor mat_color) +{ + u32 reg = 0; + u32 alpha; + u32 colIdx; + + CHECK_GXBEGIN(0x28A, "GXSetChanMatColor"); + + switch (chan) { + case GX_COLOR0: + alpha = gx->matColor[0] & 0xFF; + SET_REG_FIELD(0x28F, reg, 8, 0, alpha); + SET_REG_FIELD(0x290, reg, 8, 8, mat_color.b); + SET_REG_FIELD(0x291, reg, 8, 16, mat_color.g); + SET_REG_FIELD(0x292, reg, 8, 24, mat_color.r); + colIdx = 0; + break; + case GX_COLOR1: + alpha = gx->matColor[1] & 0xFF; + SET_REG_FIELD(0x298, reg, 8, 0, alpha); + SET_REG_FIELD(0x299, reg, 8, 8, mat_color.b); + SET_REG_FIELD(0x29A, reg, 8, 16, mat_color.g); + SET_REG_FIELD(0x29B, reg, 8, 24, mat_color.r); + colIdx = 1; + break; + case GX_ALPHA0: + reg = gx->matColor[0]; + SET_REG_FIELD(0x2A1, reg, 8, 0, mat_color.a); + colIdx = 0; + break; + case GX_ALPHA1: + reg = gx->matColor[1]; + SET_REG_FIELD(0x2A7, reg, 8, 0, mat_color.a); + colIdx = 1; + break; + case GX_COLOR0A0: + SET_REG_FIELD(0x2AC, reg, 8, 0, mat_color.a); + SET_REG_FIELD(0x2AD, reg, 8, 8, mat_color.b); + SET_REG_FIELD(0x2AE, reg, 8, 16, mat_color.g); + SET_REG_FIELD(0x2AF, reg, 8, 24, mat_color.r); + colIdx = 0; + break; + case GX_COLOR1A1: + SET_REG_FIELD(0x2B4, reg, 8, 0, mat_color.a); + SET_REG_FIELD(0x2B5, reg, 8, 8, mat_color.b); + SET_REG_FIELD(0x2B6, reg, 8, 16, mat_color.g); + SET_REG_FIELD(0x2B7, reg, 8, 24, mat_color.r); + colIdx = 1; + break; + default: + ASSERTMSGLINE(0x2BC, 0, "GXSetChanMatColor: Invalid Channel Id"); + return; + } + + GX_WRITE_XF_REG(colIdx + 12, reg); + gx->bpSentNot = 1; + gx->matColor[colIdx] = reg; +} + +void GXSetNumChans(u8 nChans) +{ + CHECK_GXBEGIN(0x2D5, "GXSetNumChans"); + ASSERTMSGLINE(0x2D6, nChans <= 2, "GXSetNumChans: nChans > 2"); + + SET_REG_FIELD(0x2D8, gx->genMode, 3, 4, nChans); + GX_WRITE_XF_REG(9, nChans); + gx->dirtyState |= 4; +} + +void GXSetChanCtrl(GXChannelID chan, GXBool enable, GXColorSrc amb_src, GXColorSrc mat_src, u32 light_mask, GXDiffuseFn diff_fn, GXAttnFn attn_fn) +{ + u32 reg; // r31 + u32 idx; // r26 + + CHECK_GXBEGIN(0x2F8, "GXSetChanCtrl"); + + ASSERTMSGLINE(0x2FB, chan >= 0 && chan <= 5, "GXSetChanCtrl: Invalid Channel Id"); + + if (chan == 4) + idx = 0; + else if (chan == 5) + idx = 1; + else + idx = chan; + + reg = 0; + SET_REG_FIELD(0x302, reg, 1, 1, enable); + SET_REG_FIELD(0x303, reg, 1, 0, mat_src); + SET_REG_FIELD(0x304, reg, 1, 6, amb_src); + SET_REG_FIELD(0x305, reg, 1, 2, (light_mask & GX_LIGHT0) != 0); + SET_REG_FIELD(0x306, reg, 1, 3, (light_mask & GX_LIGHT1) != 0); + SET_REG_FIELD(0x307, reg, 1, 4, (light_mask & GX_LIGHT2) != 0); + SET_REG_FIELD(0x308, reg, 1, 5, (light_mask & GX_LIGHT3) != 0); + SET_REG_FIELD(0x309, reg, 1, 11, (light_mask & GX_LIGHT4) != 0); + SET_REG_FIELD(0x30A, reg, 1, 12, (light_mask & GX_LIGHT5) != 0); + SET_REG_FIELD(0x30B, reg, 1, 13, (light_mask & GX_LIGHT6) != 0); + SET_REG_FIELD(0x30C, reg, 1, 14, (light_mask & GX_LIGHT7) != 0); + SET_REG_FIELD(0x30E, reg, 2, 7, (attn_fn == 0) ? 0 : diff_fn); + SET_REG_FIELD(0x30F, reg, 1, 9, (attn_fn != 2)); + SET_REG_FIELD(0x310, reg, 1, 10, (attn_fn != 0)); + + GX_WRITE_XF_REG(idx + 14, reg); + gx->bpSentNot = 1; + if (chan == GX_COLOR0A0) { + GX_WRITE_XF_REG(16, reg); + } + else if (chan == GX_COLOR1A1) { + GX_WRITE_XF_REG(17, reg); + } +} diff --git a/src/dolphin/gx/GXMisc.c b/src/dolphin/gx/GXMisc.c new file mode 100644 index 00000000..1b7bea94 --- /dev/null +++ b/src/dolphin/gx/GXMisc.c @@ -0,0 +1,485 @@ +#include +#include +#include +#include + + +#include + +static GXDrawSyncCallback TokenCB; +static GXDrawDoneCallback DrawDoneCB; +static u8 DrawDone; +static OSThreadQueue FinishQueue; + +void GXSetMisc(GXMiscToken token, u32 val) +{ + switch (token) { + case GX_MT_XF_FLUSH: + gx->vNum = val; + gx->vNumNot = !gx->vNum; + gx->bpSentNot = 1; + if (gx->vNum != 0) { + gx->dirtyState |= 8; + } + break; + case GX_MT_DL_SAVE_CONTEXT: + ASSERTMSGLINE(0xC4, !gx->inDispList, "GXSetMisc: Cannot change DL context setting while making a display list"); + gx->dlSaveContext = (val > 0); + break; + case GX_MT_NULL: + break; + default: + break; + } +} + +void GXFlush(void) +{ + CHECK_GXBEGIN(0x10E, "GXFlush"); + if (gx->dirtyState) { + __GXSetDirtyState(); + } + + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + + PPCSync(); +} + +void GXResetWriteGatherPipe(void) +{ + while (PPCMfwpar() & 1) { } + PPCMtwpar(OSUncachedToPhysical((void *)GXFIFO_ADDR)); +} + +static inline void __GXAbortWait(u32 clocks) +{ + OSTime time0; + OSTime time1; + + time0 = OSGetTime(); + do { + time1 = OSGetTime(); + } while (time1 - time0 <= (clocks / 4)); +} + +void __GXAbortWaitPECopyDone(void) +{ + __piReg[6] = 1; + __GXAbortWait(0xC8U); + __piReg[6] = 0; + __GXAbortWait(0x14U); + __GXCleanGPFifo(); +} + +void GXSetDrawSync(u16 token) +{ + BOOL enabled; + u32 reg; + + CHECK_GXBEGIN(0x162, "GXSetDrawSync"); + + enabled = OSDisableInterrupts(); + reg = token | 0x48000000; + GX_WRITE_RAS_REG(reg); + SET_REG_FIELD(0x16F, reg, 16, 0, token); + SET_REG_FIELD(0x170, reg, 8, 24, 0x47); + GX_WRITE_RAS_REG(reg); + GXFlush(); + OSRestoreInterrupts(enabled); + gx->bpSentNot = 0; +} + +u16 GXReadDrawSync(void) +{ + u16 token = __peReg[7]; + return token; +} + +void GXSetDrawDone(void) +{ + u32 reg; + BOOL enabled; + + CHECK_GXBEGIN(0x19C, "GXSetDrawDone"); + enabled = OSDisableInterrupts(); + reg = 0x45000002; + GX_WRITE_RAS_REG(reg); + GXFlush(); + DrawDone = 0; + OSRestoreInterrupts(enabled); +} + +void GXWaitDrawDone(void) +{ + BOOL enabled; + + CHECK_GXBEGIN(0x1CA, "GXWaitDrawDone"); + + enabled = OSDisableInterrupts(); + while (!DrawDone) { + OSSleepThread(&FinishQueue); + } + OSRestoreInterrupts(enabled); +} + +void GXDrawDone(void) +{ + CHECK_GXBEGIN(0x1EA, "GXDrawDone"); + GXSetDrawDone(); + GXWaitDrawDone(); +} + +void GXPixModeSync(void) +{ + CHECK_GXBEGIN(0x20D, "GXPixModeSync"); + GX_WRITE_RAS_REG(gx->peCtrl); + gx->bpSentNot = 0; +} + +void GXTexModeSync(void) +{ + u32 reg; + + CHECK_GXBEGIN(0x225, "GXTexModeSync"); + reg = 0x63000000; + GX_WRITE_RAS_REG(reg); + gx->bpSentNot = 0; +} + +void GXPokeAlphaMode(GXCompare func, u8 threshold) +{ + u32 reg; + + CHECK_GXBEGIN(0x25F, "GXPokeAlphaMode"); + reg = (func << 8) | threshold; + __peReg[3] = reg; +} + +void GXPokeAlphaRead(GXAlphaReadMode mode) +{ + u32 reg; + + CHECK_GXBEGIN(0x26A, "GXPokeAlphaRead"); + reg = 0; + SET_REG_FIELD(0x26D, reg, 2, 0, mode); + SET_REG_FIELD(0x26E, reg, 1, 2, 1); + __peReg[4] = reg; +} + +void GXPokeAlphaUpdate(GXBool update_enable) +{ + u32 reg; + + CHECK_GXBEGIN(0x277, "GXPokeAlphaUpdate"); + reg = __peReg[1]; + SET_REG_FIELD(0x27A, reg, 1, 4, update_enable); + __peReg[1] = reg; +} + +void GXPokeBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp op) +{ + u32 reg; + + CHECK_GXBEGIN(0x284, "GXPokeBlendUpdate"); + reg = __peReg[1]; + SET_REG_FIELD(0x28C, reg, 1, 0, (type == GX_BM_BLEND) || (type == GX_BM_SUBTRACT)); + SET_REG_FIELD(0x28D, reg, 1, 11, (type == GX_BM_SUBTRACT)); + SET_REG_FIELD(0x28F, reg, 1, 1, (type == GX_BM_LOGIC)); + SET_REG_FIELD(0x290, reg, 4, 12, op); + SET_REG_FIELD(0x291, reg, 3, 8, src_factor); + SET_REG_FIELD(0x292, reg, 3, 5, dst_factor); + SET_REG_FIELD(0x293, reg, 8, 24, 0x41); + __peReg[1] = reg; +} + +void GXPokeColorUpdate(GXBool update_enable) +{ + u32 reg; + + CHECK_GXBEGIN(0x29D, "GXPokeColorUpdate"); + reg = __peReg[1]; + SET_REG_FIELD(0x2A0, reg, 1, 3, update_enable); + __peReg[1] = reg; +} + +void GXPokeDstAlpha(GXBool enable, u8 alpha) +{ + u32 reg = 0; + + CHECK_GXBEGIN(0x2A9, "GXPokeDstAlpha"); + SET_REG_FIELD(0x2AB, reg, 8, 0, alpha); + SET_REG_FIELD(0x2AC, reg, 1, 8, enable); + __peReg[2] = reg; +} + +void GXPokeDither(GXBool dither) +{ + u32 reg; + + CHECK_GXBEGIN(0x2B5, "GXPokeDither"); + reg = __peReg[1]; + SET_REG_FIELD(0x2B8, reg, 1, 2, dither); + __peReg[1] = reg; +} + +void GXPokeZMode(GXBool compare_enable, GXCompare func, GXBool update_enable) +{ + u32 reg = 0; + + CHECK_GXBEGIN(0x2C1, "GXPokeZMode"); + + SET_REG_FIELD(0x2C3, reg, 1, 0, compare_enable); + SET_REG_FIELD(0x2C4, reg, 3, 1, func); + SET_REG_FIELD(0x2C5, reg, 1, 4, update_enable); + __peReg[0] = reg; +} + +void GXPeekARGB(u16 x, u16 y, u32 *color) +{ + u32 addr = (u32)OSPhysicalToUncached(0x08000000); + + SET_REG_FIELD(0x2DC, addr, 10, 2, x); + SET_REG_FIELD(0x2DD, addr, 10, 12, y); + SET_REG_FIELD(0x2DE, addr, 2, 22, 0); + *color = *(u32 *)addr; +} + +void GXPokeARGB(u16 x, u16 y, u32 color) +{ + u32 addr = (u32)OSPhysicalToUncached(0x08000000); + + SET_REG_FIELD(0x2E6, addr, 10, 2, x); + SET_REG_FIELD(0x2E7, addr, 10, 12, y); + SET_REG_FIELD(0x2E8, addr, 2, 22, 0); + *(u32 *)addr = color; +} + +void GXPeekZ(u16 x, u16 y, u32 *z) +{ + u32 addr = (u32)OSPhysicalToUncached(0x08000000); + + SET_REG_FIELD(0x2F0, addr, 10, 2, x); + SET_REG_FIELD(0x2F1, addr, 10, 12, y); + SET_REG_FIELD(0x2F2, addr, 2, 22, 1); + *z = *(u32 *)addr; +} + +void GXPokeZ(u16 x, u16 y, u32 z) +{ + u32 addr = (u32)OSPhysicalToUncached(0x08000000); + + SET_REG_FIELD(0x2FA, addr, 10, 2, x); + SET_REG_FIELD(0x2FB, addr, 10, 12, y); + SET_REG_FIELD(0x2FC, addr, 2, 22, 1); + *(u32 *)addr = z; +} + +GXDrawSyncCallback GXSetDrawSyncCallback(GXDrawSyncCallback cb) +{ + GXDrawSyncCallback oldcb; + BOOL enabled; + + oldcb = TokenCB; + enabled = OSDisableInterrupts(); + TokenCB = cb; + OSRestoreInterrupts(enabled); + return oldcb; +} + +static void GXTokenInterruptHandler(__OSInterrupt interrupt, OSContext *context) +{ + u16 token; + OSContext exceptionContext; + u32 reg; + + token = __peReg[7]; + if (TokenCB != NULL) { + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + TokenCB(token); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } + reg = __peReg[5]; + SET_REG_FIELD(0, reg, 1, 2, 1); + __peReg[5] = reg; +} + +GXDrawDoneCallback GXSetDrawDoneCallback(GXDrawDoneCallback cb) +{ + GXDrawDoneCallback oldcb; + BOOL enabled; + + oldcb = DrawDoneCB; + enabled = OSDisableInterrupts(); + DrawDoneCB = cb; + OSRestoreInterrupts(enabled); + return oldcb; +} + +static void GXFinishInterruptHandler(__OSInterrupt interrupt, OSContext *context) +{ + OSContext exceptionContext; + u32 reg; + + reg = __peReg[5]; + SET_REG_FIELD(0, reg, 1, 3, 1); + __peReg[5] = reg; + DrawDone = 1; + if (DrawDoneCB != NULL) { + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + DrawDoneCB(); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } + OSWakeupThread(&FinishQueue); +} + +void __GXPEInit(void) +{ + u32 reg; + __OSSetInterruptHandler(0x12, GXTokenInterruptHandler); + __OSSetInterruptHandler(0x13, GXFinishInterruptHandler); + OSInitThreadQueue(&FinishQueue); + __OSUnmaskInterrupts(0x2000); + __OSUnmaskInterrupts(0x1000); + reg = __peReg[5]; + SET_REG_FIELD(0, reg, 1, 2, 1); + SET_REG_FIELD(0, reg, 1, 3, 1); + SET_REG_FIELD(0, reg, 1, 0, 1); + SET_REG_FIELD(0, reg, 1, 1, 1); + __peReg[5] = reg; +} + +u32 GXCompressZ16(u32 z24, GXZFmt16 zfmt) +{ + u32 z16; + u32 z24n; + s32 exp; + s32 shift; + s32 temp; + u8 unused[4]; + + z24n = ~(z24 << 8); + temp = __cntlzw(z24n); + switch (zfmt) { + case GX_ZC_LINEAR: + z16 = (z24 >> 8) & 0xFFFF; + break; + case GX_ZC_NEAR: + if (temp > 3) { + exp = 3; + } + else { + exp = temp; + } + if (exp == 3) { + shift = 7; + } + else { + shift = 9 - exp; + } + z16 = ((z24 >> shift) & 0x3FFF & ~0xFFFFC000) | (exp << 14); + break; + case GX_ZC_MID: + if (temp > 7) { + exp = 7; + } + else { + exp = temp; + } + if (exp == 7) { + shift = 4; + } + else { + shift = 10 - exp; + } + z16 = ((z24 >> shift) & 0x1FFF & ~0xFFFFE000) | (exp << 13); + break; + case GX_ZC_FAR: + if (temp > 12) { + exp = 12; + } + else { + exp = temp; + } + if (exp == 12) { + shift = 0; + } + else { + shift = 11 - exp; + } + z16 = ((z24 >> shift) & 0xFFF & ~0xFFFFF000) | (exp << 12); + break; + default: + OSPanic(__FILE__, 0x3B0, "GXCompressZ16: Invalid Z format\n"); + break; + } + return z16; +} + +u32 GXDecompressZ16(u32 z16, GXZFmt16 zfmt) +{ + u32 z24; + u32 cb1; + long exp; + long shift; + + cb1; + cb1; + cb1; + z16; + z16; + z16; // needed to match + + switch (zfmt) { + case GX_ZC_LINEAR: + z24 = (z16 << 8) & 0xFFFF00; + break; + case GX_ZC_NEAR: + exp = (z16 >> 14) & 3; + if (exp == 3) { + shift = 7; + } + else { + shift = 9 - exp; + } + cb1 = -1 << (24 - exp); + z24 = (cb1 | ((z16 & 0x3FFF) << shift)) & 0xFFFFFF; + break; + case GX_ZC_MID: + exp = (z16 >> 13) & 7; + if (exp == 7) { + shift = 4; + } + else { + shift = 10 - exp; + } + cb1 = -1 << (24 - exp); + z24 = (cb1 | ((z16 & 0x1FFF) << shift)) & 0xFFFFFF; + break; + case GX_ZC_FAR: + exp = (z16 >> 12) & 0xF; + if (exp == 12) { + shift = 0; + } + else { + shift = 11 - exp; + } + cb1 = -1 << (24 - exp); + z24 = (cb1 | ((z16 & 0xFFF) << shift)) & 0xFFFFFF; + break; + default: + OSPanic(__FILE__, 0x3E2, "GXDecompressZ16: Invalid Z format\n"); + break; + } + return z24; +} diff --git a/src/dolphin/gx/GXPerf.c b/src/dolphin/gx/GXPerf.c new file mode 100644 index 00000000..34b4d0ae --- /dev/null +++ b/src/dolphin/gx/GXPerf.c @@ -0,0 +1,577 @@ +#include +#include + +#include + +void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) +{ + u32 reg; + + CHECK_GXBEGIN(0x6A, "GXSetGPMetric"); + + switch (gx->perf0) { + case GX_PERF0_VERTICES: + case GX_PERF0_CLIP_VTX: + case GX_PERF0_CLIP_CLKS: + case GX_PERF0_XF_WAIT_IN: + case GX_PERF0_XF_WAIT_OUT: + case GX_PERF0_XF_XFRM_CLKS: + case GX_PERF0_XF_LIT_CLKS: + case GX_PERF0_XF_BOT_CLKS: + case GX_PERF0_XF_REGLD_CLKS: + case GX_PERF0_XF_REGRD_CLKS: + case GX_PERF0_CLIP_RATIO: + case GX_PERF0_CLOCKS: + reg = 0; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_TRIANGLES: + case GX_PERF0_TRIANGLES_CULLED: + case GX_PERF0_TRIANGLES_PASSED: + case GX_PERF0_TRIANGLES_SCISSORED: + case GX_PERF0_TRIANGLES_0TEX: + case GX_PERF0_TRIANGLES_1TEX: + case GX_PERF0_TRIANGLES_2TEX: + case GX_PERF0_TRIANGLES_3TEX: + case GX_PERF0_TRIANGLES_4TEX: + case GX_PERF0_TRIANGLES_5TEX: + case GX_PERF0_TRIANGLES_6TEX: + case GX_PERF0_TRIANGLES_7TEX: + case GX_PERF0_TRIANGLES_8TEX: + case GX_PERF0_TRIANGLES_0CLR: + case GX_PERF0_TRIANGLES_1CLR: + case GX_PERF0_TRIANGLES_2CLR: + reg = 0x23000000; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_QUAD_0CVG: + case GX_PERF0_QUAD_NON0CVG: + case GX_PERF0_QUAD_1CVG: + case GX_PERF0_QUAD_2CVG: + case GX_PERF0_QUAD_3CVG: + case GX_PERF0_QUAD_4CVG: + case GX_PERF0_AVG_QUAD_CNT: + reg = 0x24000000; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_NONE: + break; + default: + ASSERTMSGLINE(0xA6, 0, "GXSetGPMetric: Invalid GXPerf0 metric name"); + break; + } + + switch (gx->perf1) { + case GX_PERF1_TEXELS: + case GX_PERF1_TX_IDLE: + case GX_PERF1_TX_REGS: + case GX_PERF1_TX_MEMSTALL: + case GX_PERF1_TC_CHECK1_2: + case GX_PERF1_TC_CHECK3_4: + case GX_PERF1_TC_CHECK5_6: + case GX_PERF1_TC_CHECK7_8: + case GX_PERF1_TC_MISS: + case GX_PERF1_CLOCKS: + reg = 0x67000000; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_VC_ELEMQ_FULL: + case GX_PERF1_VC_MISSQ_FULL: + case GX_PERF1_VC_MEMREQ_FULL: + case GX_PERF1_VC_STATUS7: + case GX_PERF1_VC_MISSREP_FULL: + case GX_PERF1_VC_STREAMBUF_LOW: + case GX_PERF1_VC_ALL_STALLS: + case GX_PERF1_VERTICES: + SET_REG_FIELD(0, gx->perfSel, 4, 4, 0); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + break; + case GX_PERF1_FIFO_REQ: + case GX_PERF1_CALL_REQ: + case GX_PERF1_VC_MISS_REQ: + case GX_PERF1_CP_ALL_REQ: + reg = 0; + GX_SET_CP_REG(3, reg); + break; + case GX_PERF1_NONE: + break; + default: + ASSERTMSGLINE(0xD8, 0, "GXSetGPMetric: Invalid GXPerf1 metric name"); + break; + } + + gx->perf0 = perf0; + switch (gx->perf0) { + case GX_PERF0_VERTICES: + reg = 0x273; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_CLIP_VTX: + reg = 0x14A; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_CLIP_CLKS: + reg = 0x16B; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_XF_WAIT_IN: + reg = 0x84; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_XF_WAIT_OUT: + reg = 0xC6; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_XF_XFRM_CLKS: + reg = 0x210; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_XF_LIT_CLKS: + reg = 0x252; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_XF_BOT_CLKS: + reg = 0x231; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_XF_REGLD_CLKS: + reg = 0x1AD; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_XF_REGRD_CLKS: + reg = 0x1CE; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_CLOCKS: + reg = 0x21; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_CLIP_RATIO: + reg = 0x153; + GX_WRITE_XF_REG(6, reg); + break; + case GX_PERF0_TRIANGLES: + reg = 0x2300AE7F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_CULLED: + reg = 0x23008E7F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_PASSED: + reg = 0x23009E7F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_SCISSORED: + reg = 0x23001E7F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_0TEX: + reg = 0x2300AC3F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_1TEX: + reg = 0x2300AC7F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_2TEX: + reg = 0x2300ACBF; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_3TEX: + reg = 0x2300ACFF; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_4TEX: + reg = 0x2300AD3F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_5TEX: + reg = 0x2300AD7F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_6TEX: + reg = 0x2300ADBF; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_7TEX: + reg = 0x2300ADFF; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_8TEX: + reg = 0x2300AE3F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_0CLR: + reg = 0x2300A27F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_1CLR: + reg = 0x2300A67F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_TRIANGLES_2CLR: + reg = 0x2300AA7F; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_QUAD_0CVG: + reg = 0x2402C0C6; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_QUAD_NON0CVG: + reg = 0x2402C16B; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_QUAD_1CVG: + reg = 0x2402C0E7; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_QUAD_2CVG: + reg = 0x2402C108; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_QUAD_3CVG: + reg = 0x2402C129; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_QUAD_4CVG: + reg = 0x2402C14A; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_AVG_QUAD_CNT: + reg = 0x2402C1AD; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF0_NONE: + break; + default: + ASSERTMSGLINE(0x1DA, 0, "GXSetGPMetric: Invalid GXPerf0 metric name"); + break; + } + + gx->perf1 = perf1; + switch (gx->perf1) { + case GX_PERF1_TEXELS: + reg = 0x67000042; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_TX_IDLE: + reg = 0x67000084; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_TX_REGS: + reg = 0x67000063; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_TX_MEMSTALL: + reg = 0x67000129; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_TC_MISS: + reg = 0x67000252; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_CLOCKS: + reg = 0x67000021; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_TC_CHECK1_2: + reg = 0x6700014B; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_TC_CHECK3_4: + reg = 0x6700018D; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_TC_CHECK5_6: + reg = 0x670001CF; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_TC_CHECK7_8: + reg = 0x67000211; + GX_WRITE_RAS_REG(reg); + break; + case GX_PERF1_VC_ELEMQ_FULL: + SET_REG_FIELD(0, gx->perfSel, 4, 4, 2); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + break; + case GX_PERF1_VC_MISSQ_FULL: + SET_REG_FIELD(0, gx->perfSel, 4, 4, 3); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + break; + case GX_PERF1_VC_MEMREQ_FULL: + SET_REG_FIELD(0, gx->perfSel, 4, 4, 4); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + break; + case GX_PERF1_VC_STATUS7: + SET_REG_FIELD(0, gx->perfSel, 4, 4, 5); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + break; + case GX_PERF1_VC_MISSREP_FULL: + SET_REG_FIELD(0, gx->perfSel, 4, 4, 6); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + break; + case GX_PERF1_VC_STREAMBUF_LOW: + SET_REG_FIELD(0, gx->perfSel, 4, 4, 7); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + break; + case GX_PERF1_VC_ALL_STALLS: + SET_REG_FIELD(0, gx->perfSel, 4, 4, 9); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + break; + case GX_PERF1_VERTICES: + SET_REG_FIELD(0, gx->perfSel, 4, 4, 8); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + break; + case GX_PERF1_FIFO_REQ: + reg = 2; + GX_SET_CP_REG(3, reg); + break; + case GX_PERF1_CALL_REQ: + reg = 3; + GX_SET_CP_REG(3, reg); + break; + case GX_PERF1_VC_MISS_REQ: + reg = 4; + GX_SET_CP_REG(3, reg); + break; + case GX_PERF1_CP_ALL_REQ: + reg = 5; + GX_SET_CP_REG(3, reg); + break; + case GX_PERF1_NONE: + break; + default: + ASSERTMSGLINE(0x26B, 0, "GXSetGPMetric: Invalid GXPerf1 metric name"); + break; + } + + gx->bpSentNot = 0; +} + +#pragma scheduling off +void GXReadGPMetric(u32 *cnt0, u32 *cnt1) +{ + u32 cpCtr0, cpCtr1, cpCtr2, cpCtr3; + + ASSERTMSGLINE(0x286, !gx->inDispList, "GXReadGPMetric: don't use in a display list"); + + cpCtr0 = __GXReadCPCounterU32(32, 33); + cpCtr1 = __GXReadCPCounterU32(34, 35); + cpCtr2 = __GXReadCPCounterU32(36, 37); + cpCtr3 = __GXReadCPCounterU32(38, 39); + + switch (gx->perf0) { + case GX_PERF0_CLIP_RATIO: + *cnt0 = cpCtr1 * 0x3E8 / cpCtr0; + break; + case GX_PERF0_VERTICES: + case GX_PERF0_CLIP_VTX: + case GX_PERF0_CLIP_CLKS: + case GX_PERF0_XF_WAIT_IN: + case GX_PERF0_XF_WAIT_OUT: + case GX_PERF0_XF_XFRM_CLKS: + case GX_PERF0_XF_LIT_CLKS: + case GX_PERF0_XF_BOT_CLKS: + case GX_PERF0_XF_REGLD_CLKS: + case GX_PERF0_XF_REGRD_CLKS: + case GX_PERF0_TRIANGLES: + case GX_PERF0_TRIANGLES_CULLED: + case GX_PERF0_TRIANGLES_PASSED: + case GX_PERF0_TRIANGLES_SCISSORED: + case GX_PERF0_TRIANGLES_0TEX: + case GX_PERF0_TRIANGLES_1TEX: + case GX_PERF0_TRIANGLES_2TEX: + case GX_PERF0_TRIANGLES_3TEX: + case GX_PERF0_TRIANGLES_4TEX: + case GX_PERF0_TRIANGLES_5TEX: + case GX_PERF0_TRIANGLES_6TEX: + case GX_PERF0_TRIANGLES_7TEX: + case GX_PERF0_TRIANGLES_8TEX: + case GX_PERF0_TRIANGLES_0CLR: + case GX_PERF0_TRIANGLES_1CLR: + case GX_PERF0_TRIANGLES_2CLR: + case GX_PERF0_QUAD_0CVG: + case GX_PERF0_QUAD_NON0CVG: + case GX_PERF0_QUAD_1CVG: + case GX_PERF0_QUAD_2CVG: + case GX_PERF0_QUAD_3CVG: + case GX_PERF0_QUAD_4CVG: + case GX_PERF0_AVG_QUAD_CNT: + case GX_PERF0_CLOCKS: + *cnt0 = cpCtr0; + break; + case GX_PERF0_NONE: + *cnt0 = 0; + break; + default: + ASSERTMSGLINE(0x2CF, 0, "GXReadGPMetric: Invalid GXPerf0 metric name"); + *cnt0 = 0; + break; + } + + switch (gx->perf1) { + case GX_PERF1_TEXELS: + *cnt1 = cpCtr3 * 4; + break; + case GX_PERF1_TC_CHECK1_2: + *cnt1 = cpCtr2 + (cpCtr3 * 2); + break; + case GX_PERF1_TC_CHECK3_4: + *cnt1 = (cpCtr2 * 3) + (cpCtr3 * 4); + break; + case GX_PERF1_TC_CHECK5_6: + *cnt1 = (cpCtr2 * 5) + (cpCtr3 * 6); + break; + case GX_PERF1_TC_CHECK7_8: + *cnt1 = (cpCtr2 * 7) + (cpCtr3 * 8); + break; + case GX_PERF1_TX_IDLE: + case GX_PERF1_TX_REGS: + case GX_PERF1_TX_MEMSTALL: + case GX_PERF1_TC_MISS: + case GX_PERF1_VC_ELEMQ_FULL: + case GX_PERF1_VC_MISSQ_FULL: + case GX_PERF1_VC_MEMREQ_FULL: + case GX_PERF1_VC_STATUS7: + case GX_PERF1_VC_MISSREP_FULL: + case GX_PERF1_VC_STREAMBUF_LOW: + case GX_PERF1_VC_ALL_STALLS: + case GX_PERF1_VERTICES: + case GX_PERF1_CLOCKS: + *cnt1 = cpCtr3; + break; + case GX_PERF1_FIFO_REQ: + case GX_PERF1_CALL_REQ: + case GX_PERF1_VC_MISS_REQ: + case GX_PERF1_CP_ALL_REQ: + *cnt1 = cpCtr2; + break; + case GX_PERF1_NONE: + *cnt1 = 0; + break; + default: + ASSERTMSGLINE(0x30A, 0, "GXReadGPMetric: Invalid GXPerf1 metric name"); + *cnt1 = 0; + break; + } +} +#pragma scheduling reset + +void GXClearGPMetric(void) +{ + u32 reg; + + ASSERTMSGLINE(0x322, !gx->inDispList, "GXClearGPMetric: don't use in a display list"); + reg = 4; + __cpReg[2] = reg; +} + +u32 GXReadGP0Metric(void) +{ + u32 cnt0, cnt1; + + GXReadGPMetric(&cnt0, &cnt1); + return cnt0; +} + +u32 GXReadGP1Metric(void) +{ + u32 cnt0, cnt1; + + GXReadGPMetric(&cnt0, &cnt1); + return cnt1; +} + +#pragma scheduling off +void GXReadMemMetric( + u32 *cp_req, u32 *tc_req, u32 *cpu_rd_req, u32 *cpu_wr_req, u32 *dsp_req, u32 *io_req, u32 *vi_req, u32 *pe_req, u32 *rf_req, u32 *fi_req) +{ + ASSERTMSGLINE(0x380, !gx->inDispList, "GXReadMemMetric: don't use in a display list"); + + *cp_req = __GXReadMEMCounterU32(26, 25); + *tc_req = __GXReadMEMCounterU32(28, 27); + *cpu_rd_req = __GXReadMEMCounterU32(30, 29); + *cpu_wr_req = __GXReadMEMCounterU32(32, 31); + *dsp_req = __GXReadMEMCounterU32(34, 33); + *io_req = __GXReadMEMCounterU32(36, 35); + *vi_req = __GXReadMEMCounterU32(38, 37); + *pe_req = __GXReadMEMCounterU32(40, 39); + *rf_req = __GXReadMEMCounterU32(42, 41); + *fi_req = __GXReadMEMCounterU32(44, 43); +} +#pragma scheduling reset + +void GXClearMemMetric(void) +{ + ASSERTMSGLINE(0x3B9, !gx->inDispList, "GXClearMemMetric: don't use in a display list"); + + GX_SET_MEM_REG(25, 0); + GX_SET_MEM_REG(26, 0); + GX_SET_MEM_REG(27, 0); + GX_SET_MEM_REG(28, 0); + GX_SET_MEM_REG(30, 0); + GX_SET_MEM_REG(29, 0); + GX_SET_MEM_REG(32, 0); + GX_SET_MEM_REG(31, 0); + GX_SET_MEM_REG(34, 0); + GX_SET_MEM_REG(33, 0); + GX_SET_MEM_REG(36, 0); + GX_SET_MEM_REG(35, 0); + GX_SET_MEM_REG(38, 0); + GX_SET_MEM_REG(37, 0); + GX_SET_MEM_REG(40, 0); + GX_SET_MEM_REG(39, 0); + GX_SET_MEM_REG(42, 0); + GX_SET_MEM_REG(41, 0); + GX_SET_MEM_REG(44, 0); + GX_SET_MEM_REG(43, 0); +} + +#pragma scheduling off +void GXReadPixMetric(u32 *top_pixels_in, u32 *top_pixels_out, u32 *bot_pixels_in, u32 *bot_pixels_out, u32 *clr_pixels_in, u32 *copy_clks) +{ + *top_pixels_in = __GXReadPECounterU32(12, 13) * 4; + *top_pixels_out = __GXReadPECounterU32(14, 15) * 4; + *bot_pixels_in = __GXReadPECounterU32(16, 17) * 4; + *bot_pixels_out = __GXReadPECounterU32(18, 19) * 4; + *clr_pixels_in = __GXReadPECounterU32(20, 21) * 4; + *copy_clks = __GXReadPECounterU32(22, 23); +} +#pragma scheduling reset + +void GXClearPixMetric(void) +{ + u32 reg; + + CHECK_GXBEGIN(0x48B, "GXClearPixMetric"); + reg = 0x57000000; + GX_WRITE_RAS_REG(reg); + reg = 0x57000AAA; + GX_WRITE_RAS_REG(reg); + gx->bpSentNot = 0; +} + +void GXSetVCacheMetric(GXVCachePerf attr) +{ + u32 reg; + + SET_REG_FIELD(0x43C, gx->perfSel, 4, 0, attr); + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + reg = 1; + GX_WRITE_SOME_REG4(8, 0x10, reg, -12); +} + +#pragma scheduling off +void GXReadVCacheMetric(u32 *check, u32 *miss, u32 *stall) +{ + *check = __GXReadCPCounterU32(40, 41); + *miss = __GXReadCPCounterU32(42, 43); + *stall = __GXReadCPCounterU32(44, 45); +} +#pragma scheduling on + +void GXClearVCacheMetric(void) +{ + GX_WRITE_SOME_REG4(8, 0, 0, -12); +} diff --git a/src/dolphin/gx/GXPixel.c b/src/dolphin/gx/GXPixel.c new file mode 100644 index 00000000..5460b4b6 --- /dev/null +++ b/src/dolphin/gx/GXPixel.c @@ -0,0 +1,290 @@ +#include +#include +#include + +#include + +void GXSetFog(GXFogType type, f32 startz, f32 endz, f32 nearz, f32 farz, GXColor color) +{ + u32 fogclr; + u32 fog0; + u32 fog1; + u32 fog2; + u32 fog3; + f32 A; + f32 B; + f32 B_mant; + f32 C; + f32 a; + f32 c; + u32 B_expn; + u32 b_m; + u32 b_s; + u32 a_hex; + u32 c_hex; + + CHECK_GXBEGIN(0x8A, "GXSetFog"); + + ASSERTMSGLINE(0x8C, farz >= 0.0f, "GXSetFog: The farz should be positive value"); + ASSERTMSGLINE(0x8D, farz >= nearz, "GXSetFog: The farz should be larger than nearz"); + + if (farz == nearz || endz == startz) { + A = 0.0f; + B = 0.5f; + C = 0.0f; + } + else { + A = (farz * nearz) / ((farz - nearz) * (endz - startz)); + B = farz / (farz - nearz); + C = startz / (endz - startz); + } + + B_mant = B; + B_expn = 0; + while (B_mant > 1.0) { + B_mant *= 0.5f; + B_expn++; + } + while (B_mant > 0.0f && B_mant < 0.5) { + B_mant *= 2.0f; + B_expn--; + } + + a = A / (f32)(1 << (B_expn + 1)); + b_m = 8.388638e6f * B_mant; + b_s = B_expn + 1; + c = C; + + fog1 = 0; + SET_REG_FIELD(0x94, fog1, 24, 0, b_m); + SET_REG_FIELD(0x95, fog1, 8, 24, 0xEF); + + fog2 = 0; + SET_REG_FIELD(0x98, fog2, 5, 0, b_s); + SET_REG_FIELD(0x99, fog2, 8, 24, 0xF0); + + a_hex = *(u32 *)&a; + c_hex = *(u32 *)&c; + + fog0 = 0; + SET_REG_FIELD(0xA0, fog0, 11, 0, (a_hex >> 12) & 0x7FF); + SET_REG_FIELD(0xA1, fog0, 8, 11, (a_hex >> 23) & 0xFF); + SET_REG_FIELD(0xA2, fog0, 1, 19, (a_hex >> 31)); + SET_REG_FIELD(0xA3, fog0, 8, 24, 0xEE); + + fog3 = 0; + SET_REG_FIELD(0xA6, fog3, 11, 0, (c_hex >> 12) & 0x7FF); + SET_REG_FIELD(0xA7, fog3, 8, 11, (c_hex >> 23) & 0xFF); + SET_REG_FIELD(0xA8, fog3, 1, 19, (c_hex >> 31)); + SET_REG_FIELD(0xA9, fog3, 1, 20, 0); + SET_REG_FIELD(0xAA, fog3, 3, 21, type); + SET_REG_FIELD(0xAB, fog3, 8, 24, 0xF1); + + fogclr = 0; + SET_REG_FIELD(0xAE, fogclr, 8, 0, color.b); + SET_REG_FIELD(0xAF, fogclr, 8, 8, color.g); + SET_REG_FIELD(0xB0, fogclr, 8, 16, color.r); + SET_REG_FIELD(0xB1, fogclr, 8, 24, 0xF2); + + GX_WRITE_RAS_REG(fog0); + GX_WRITE_RAS_REG(fog1); + GX_WRITE_RAS_REG(fog2); + GX_WRITE_RAS_REG(fog3); + GX_WRITE_RAS_REG(fogclr); + gx->bpSentNot = 0; +} + +void GXSetFogColor(GXColor color) +{ + unsigned long rgba; + unsigned long fogclr = 0xF2000000; + + rgba = *(u32 *)&color; + SET_REG_FIELD(0xFA, fogclr, 24, 0, rgba >> 8); + GX_WRITE_RAS_REG(fogclr); + gx->bpSentNot = 0; +} + +void GXInitFogAdjTable(GXFogAdjTable *table, u16 width, const f32 projmtx[4][4]) +{ + f32 xi; + f32 iw; + f32 rangeVal; + f32 nearZ; + f32 sideX; + u32 i; + + CHECK_GXBEGIN(0x113, "GXInitFogAdjTable"); + ASSERTMSGLINE(0x114, table != NULL, "GXInitFogAdjTable: table pointer is null"); + ASSERTMSGLINE(0x115, width <= 640, "GXInitFogAdjTable: invalid width value"); + + if (0.0 == projmtx[3][3]) { + nearZ = projmtx[2][3] / (projmtx[2][2] - 1.0f); + sideX = nearZ / projmtx[0][0]; + } + else { + sideX = 1.0f / projmtx[0][0]; + nearZ = 1.73205f * sideX; + } + + iw = 2.0f / width; + for (i = 0; i < 10; i++) { + xi = (i + 1) << 5; + xi *= iw; + xi *= sideX; + rangeVal = sqrtf(1.0f + ((xi * xi) / (nearZ * nearZ))); + table->r[i] = (u32)(256.0f * rangeVal) & 0xFFF; + } +} + +void GXSetFogRangeAdj(GXBool enable, u16 center, const GXFogAdjTable *table) +{ + u32 i; + u32 range_adj; + u32 range_c; + + CHECK_GXBEGIN(0x14B, "GXSetFogRangeAdj"); + + if (enable) { + ASSERTMSGLINE(0x14E, table != NULL, "GXSetFogRangeAdj: table pointer is null"); + for (i = 0; i < 10; i += 2) { + range_adj = 0; + SET_REG_FIELD(0x152, range_adj, 12, 0, table->r[i]); + SET_REG_FIELD(0x153, range_adj, 12, 12, table->r[i + 1]); + SET_REG_FIELD(0x154, range_adj, 8, 24, (i >> 1) + 0xE9); + GX_WRITE_RAS_REG(range_adj); + } + } + range_c = 0; + SET_REG_FIELD(0x15A, range_c, 10, 0, center + 342); + SET_REG_FIELD(0x15B, range_c, 1, 10, enable); + SET_REG_FIELD(0x15C, range_c, 8, 24, 0xE8); + GX_WRITE_RAS_REG(range_c); + gx->bpSentNot = 0; +} + +void GXSetBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp op) +{ + CHECK_GXBEGIN(0x177, "GXSetBlendMode"); + + SET_REG_FIELD(0x135, gx->cmode0, 1, 0, (type == GX_BM_BLEND || type == GX_BM_SUBTRACT)); + SET_REG_FIELD(0x136, gx->cmode0, 1, 11, (type == GX_BM_SUBTRACT)); + SET_REG_FIELD(0x138, gx->cmode0, 1, 1, (type == GX_BM_LOGIC)); + SET_REG_FIELD(0x139, gx->cmode0, 4, 12, op); + SET_REG_FIELD(0x13A, gx->cmode0, 3, 8, src_factor); + SET_REG_FIELD(0x13B, gx->cmode0, 3, 5, dst_factor); + SET_REG_FIELD(0x13C, gx->cmode0, 8, 24, 0x41); + GX_WRITE_RAS_REG(gx->cmode0); + gx->bpSentNot = 0; +} + +void GXSetColorUpdate(GXBool update_enable) +{ + CHECK_GXBEGIN(0x1A3, "GXSetColorUpdate"); + + SET_REG_FIELD(0x150, gx->cmode0, 1, 3, update_enable); + GX_WRITE_RAS_REG(gx->cmode0); + gx->bpSentNot = 0; +} + +void GXSetAlphaUpdate(GXBool update_enable) +{ + CHECK_GXBEGIN(0x1B0, "GXSetAlphaUpdate"); + + SET_REG_FIELD(0x159, gx->cmode0, 1, 4, update_enable); + GX_WRITE_RAS_REG(gx->cmode0); + gx->bpSentNot = 0; +} + +void GXSetZMode(GXBool compare_enable, GXCompare func, GXBool update_enable) +{ + CHECK_GXBEGIN(0x1CB, "GXSetZMode"); + + SET_REG_FIELD(0x171, gx->zmode, 1, 0, compare_enable); + SET_REG_FIELD(0x172, gx->zmode, 3, 1, func); + SET_REG_FIELD(0x173, gx->zmode, 1, 4, update_enable); + GX_WRITE_RAS_REG(gx->zmode); + gx->bpSentNot = 0; +} + +void GXSetZCompLoc(GXBool before_tex) +{ + CHECK_GXBEGIN(0x1DA, "GXSetZCompLoc"); + + SET_REG_FIELD(0x1DB, gx->peCtrl, 1, 6, before_tex); + GX_WRITE_RAS_REG(gx->peCtrl); + gx->bpSentNot = 0; +} + +void GXSetPixelFmt(GXPixelFmt pix_fmt, GXZFmt16 z_fmt) +{ + u32 oldPeCtrl; + u8 aa; + static u32 p2f[8] = { 0, 1, 2, 3, 4, 4, 4, 5 }; + + CHECK_GXBEGIN(0x1FF, "GXSetPixelFmt"); + oldPeCtrl = gx->peCtrl; + ASSERTMSGLINE(0x203, pix_fmt >= 0 && pix_fmt <= 7, "Invalid Pixel format"); + SET_REG_FIELD(0x205, gx->peCtrl, 3, 0, p2f[pix_fmt]); + SET_REG_FIELD(0x206, gx->peCtrl, 3, 3, z_fmt); + if (oldPeCtrl != gx->peCtrl) { + GX_WRITE_RAS_REG(gx->peCtrl); + if (pix_fmt == GX_PF_RGB565_Z16) + aa = 1; + else + aa = 0; + SET_REG_FIELD(0x20F, gx->genMode, 1, 9, aa); + gx->dirtyState |= 4; + } + if (p2f[pix_fmt] == 4) { + SET_REG_FIELD(0x216, gx->cmode1, 2, 9, (pix_fmt - 4) & 0x3); + SET_REG_FIELD(0x216, gx->cmode1, 8, 24, 0x42); + GX_WRITE_RAS_REG(gx->cmode1); + } + gx->bpSentNot = 0; +} + +void GXSetDither(GXBool dither) +{ + CHECK_GXBEGIN(0x22C, "GXSetDither"); + + SET_REG_FIELD(0x1CE, gx->cmode0, 1, 2, dither); + GX_WRITE_RAS_REG(gx->cmode0); + gx->bpSentNot = 0; +} + +void GXSetDstAlpha(GXBool enable, u8 alpha) +{ + CHECK_GXBEGIN(0x245, "GXSetDstAlpha"); + + SET_REG_FIELD(0x1E2, gx->cmode1, 8, 0, alpha); + SET_REG_FIELD(0x1E3, gx->cmode1, 1, 8, enable); + GX_WRITE_RAS_REG(gx->cmode1); + gx->bpSentNot = 0; +} + +void GXSetFieldMask(GXBool odd_mask, GXBool even_mask) +{ + u32 reg; + + CHECK_GXBEGIN(0x260, "GXSetFieldMask"); + reg = 0; + SET_REG_FIELD(0x262, reg, 1, 0, even_mask); + SET_REG_FIELD(0x263, reg, 1, 1, odd_mask); + SET_REG_FIELD(0x263, reg, 8, 24, 0x44); + GX_WRITE_RAS_REG(reg); + gx->bpSentNot = 0; +} + +void GXSetFieldMode(GXBool field_mode, GXBool half_aspect_ratio) +{ + u32 reg; + + CHECK_GXBEGIN(0x27D, "GXSetFieldMode"); + SET_REG_FIELD(0x281, gx->lpSize, 1, 22, half_aspect_ratio); + GX_WRITE_RAS_REG(gx->lpSize); + __GXFlushTextureState(); + reg = field_mode | 0x68000000; + GX_WRITE_RAS_REG(reg); + __GXFlushTextureState(); +} diff --git a/src/dolphin/gx/GXStubs.c b/src/dolphin/gx/GXStubs.c new file mode 100644 index 00000000..85f05a89 --- /dev/null +++ b/src/dolphin/gx/GXStubs.c @@ -0,0 +1,5 @@ +#include + +#include + +void __GXSetRange(float nearz, float fgSideX) {} diff --git a/src/dolphin/gx/GXTev.c b/src/dolphin/gx/GXTev.c new file mode 100644 index 00000000..c2f6d67a --- /dev/null +++ b/src/dolphin/gx/GXTev.c @@ -0,0 +1,403 @@ +#include +#include + +#include + +void GXSetTevOp(GXTevStageID id, GXTevMode mode) +{ + GXTevColorArg carg = GX_CC_RASC; + GXTevAlphaArg aarg = GX_CA_RASA; + + CHECK_GXBEGIN(0x1A4, "GXSetTevOp"); + ASSERTMSGLINE(0x1A5, id < 16, "GXSetTevColor*: Invalid Tev Stage Index"); + ASSERTMSGLINE(0x1A6, mode <= 4, "GXSetTevOp: Invalid Tev Mode"); + + if (id != GX_TEVSTAGE0) { + carg = GX_CC_CPREV; + aarg = GX_CA_APREV; + } + + switch (mode) { + case GX_MODULATE: + GXSetTevColorIn(id, GX_CC_ZERO, GX_CC_TEXC, carg, GX_CC_ZERO); + GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO); + break; + case GX_DECAL: + GXSetTevColorIn(id, carg, GX_CC_TEXC, GX_CC_TEXA, GX_CC_ZERO); + GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg); + break; + case GX_BLEND: + GXSetTevColorIn(id, carg, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO); + GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO); + break; + case GX_REPLACE: + GXSetTevColorIn(id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC); + GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA); + break; + case GX_PASSCLR: + GXSetTevColorIn(id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, carg); + GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg); + break; + } + GXSetTevColorOp(id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); +} + +void GXSetTevColorIn(GXTevStageID stage, GXTevColorArg a, GXTevColorArg b, GXTevColorArg c, GXTevColorArg d) +{ + u32 *pTevReg; + + CHECK_GXBEGIN(0x242, "GXSetTevColorIn"); + ASSERTMSGLINE(0x243, stage < 16, "GXSetTevColor*: Invalid Tev Stage Index"); + ASSERTMSGLINE(0x244, a <= 15, "GXSetTev*In: A/B/C/D argument out of range"); + ASSERTMSGLINE(0x245, b <= 15, "GXSetTev*In: A/B/C/D argument out of range"); + ASSERTMSGLINE(0x246, c <= 15, "GXSetTev*In: A/B/C/D argument out of range"); + ASSERTMSGLINE(0x247, d <= 15, "GXSetTev*In: A/B/C/D argument out of range"); + + pTevReg = &gx->tevc[stage]; + SET_REG_FIELD(0xED, *pTevReg, 4, 12, a); + SET_REG_FIELD(0xEE, *pTevReg, 4, 8, b); + SET_REG_FIELD(0xEF, *pTevReg, 4, 4, c); + SET_REG_FIELD(0xF0, *pTevReg, 4, 0, d); + + GX_WRITE_RAS_REG(*pTevReg); + gx->bpSentNot = 0; +} + +void GXSetTevAlphaIn(GXTevStageID stage, GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c, GXTevAlphaArg d) +{ + u32 *pTevReg; + + CHECK_GXBEGIN(0x266, "GXSetTevAlphaIn"); + ASSERTMSGLINE(0x267, stage < 16, "GXSetTevAlpha*: Invalid Tev Stage Index"); + ASSERTMSGLINE(0x268, a <= 7, "GXSetTev*In: A/B/C/D argument out of range"); + ASSERTMSGLINE(0x269, b <= 7, "GXSetTev*In: A/B/C/D argument out of range"); + ASSERTMSGLINE(0x26A, c <= 7, "GXSetTev*In: A/B/C/D argument out of range"); + ASSERTMSGLINE(0x26B, d <= 7, "GXSetTev*In: A/B/C/D argument out of range"); + + pTevReg = &gx->teva[stage]; + SET_REG_FIELD(0x110, *pTevReg, 3, 13, a); + SET_REG_FIELD(0x111, *pTevReg, 3, 10, b); + SET_REG_FIELD(0x112, *pTevReg, 3, 7, c); + SET_REG_FIELD(0x113, *pTevReg, 3, 4, d); + + GX_WRITE_RAS_REG(*pTevReg); + gx->bpSentNot = 0; +} + +void GXSetTevColorOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID out_reg) +{ + u32 *pTevReg; + + CHECK_GXBEGIN(0x28D, "GXSetTevColorOp"); + ASSERTMSGLINE(0x28E, stage < 16, "GXSetTevColor*: Invalid Tev Stage Index"); + + pTevReg = &gx->tevc[stage]; + SET_REG_FIELD(0x137, *pTevReg, 1, 18, op & 1); + if (op <= 1) { + SET_REG_FIELD(0x139, *pTevReg, 2, 20, scale); + SET_REG_FIELD(0x13A, *pTevReg, 2, 16, bias); + } + else { + SET_REG_FIELD(0x13C, *pTevReg, 2, 20, (op >> 1) & 3); + SET_REG_FIELD(0x13D, *pTevReg, 2, 16, 3); + } + SET_REG_FIELD(0x140, *pTevReg, 1, 19, clamp & 0xFF); + SET_REG_FIELD(0x141, *pTevReg, 2, 22, out_reg); + + GX_WRITE_RAS_REG(*pTevReg); + gx->bpSentNot = 0; +} + +void GXSetTevAlphaOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID out_reg) +{ + u32 *pTevReg; + + CHECK_GXBEGIN(0x2BB, "GXSetTevAlphaOp"); + ASSERTMSGLINE(0x2BC, stage < 16, "GXSetTevAlpha*: Invalid Tev Stage Index"); + + pTevReg = &gx->teva[stage]; + SET_REG_FIELD(0x163, *pTevReg, 1, 18, op & 1); + if (op <= 1) { + SET_REG_FIELD(0x165, *pTevReg, 2, 20, scale); + SET_REG_FIELD(0x166, *pTevReg, 2, 16, bias); + } + else { + SET_REG_FIELD(0x168, *pTevReg, 2, 20, (op >> 1) & 3); + SET_REG_FIELD(0x169, *pTevReg, 2, 16, 3); + } + SET_REG_FIELD(0x16C, *pTevReg, 1, 19, clamp & 0xFF); + SET_REG_FIELD(0x16D, *pTevReg, 2, 22, out_reg); + + GX_WRITE_RAS_REG(*pTevReg); + gx->bpSentNot = 0; +} + +void GXSetTevColor(GXTevRegID id, GXColor color) +{ + u32 regRA; + u32 regBG; + + CHECK_GXBEGIN(0x2E4, "GXSetTevColor"); + regRA = 0; + SET_REG_FIELD(0x185, regRA, 11, 0, color.r); + SET_REG_FIELD(0x186, regRA, 11, 12, color.a); + SET_REG_FIELD(0x187, regRA, 8, 24, 224 + id * 2); + + regBG = 0; + SET_REG_FIELD(0x18A, regBG, 11, 0, color.b); + SET_REG_FIELD(0x18B, regBG, 11, 12, color.g); + SET_REG_FIELD(0x18C, regBG, 8, 24, 225 + id * 2); + + GX_WRITE_RAS_REG(regRA); + GX_WRITE_RAS_REG(regBG); + GX_WRITE_RAS_REG(regBG); + GX_WRITE_RAS_REG(regBG); + gx->bpSentNot = 0; +} + +void GXSetTevColorS10(GXTevRegID id, GXColorS10 color) +{ + u32 regRA; + u32 regBG; + + ASSERTMSGLINE(0x309, color.r >= -1024 && color.r < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023"); + ASSERTMSGLINE(0x30A, color.g >= -1024 && color.g < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023"); + ASSERTMSGLINE(0x30B, color.b >= -1024 && color.b < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023"); + ASSERTMSGLINE(0x30C, color.a >= -1024 && color.a < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023"); + + CHECK_GXBEGIN(0x30E, "GXSetTevColorS10"); + regRA = 0; + SET_REG_FIELD(0x1AF, regRA, 11, 0, color.r & 0x7FF); + SET_REG_FIELD(0x1B0, regRA, 11, 12, color.a & 0x7FF); + SET_REG_FIELD(0x1B1, regRA, 8, 24, 224 + id * 2); + + regBG = 0; + SET_REG_FIELD(0x1B4, regBG, 11, 0, color.b & 0x7FF); + SET_REG_FIELD(0x1B5, regBG, 11, 12, color.g & 0x7FF); + SET_REG_FIELD(0x1B6, regBG, 8, 24, 225 + id * 2); + + GX_WRITE_RAS_REG(regRA); + GX_WRITE_RAS_REG(regBG); + GX_WRITE_RAS_REG(regBG); + GX_WRITE_RAS_REG(regBG); + gx->bpSentNot = 0; +} + +void GXSetTevKColor(GXTevKColorID id, GXColor color) +{ + u32 regRA; + u32 regBG; + + CHECK_GXBEGIN(0x341, "GXSetTevKColor"); + regRA = 0; + SET_REG_FIELD(0x1E0, regRA, 8, 0, color.r); + SET_REG_FIELD(0x1E1, regRA, 8, 12, color.a); + SET_REG_FIELD(0x1E2, regRA, 4, 20, 8); + SET_REG_FIELD(0x1E3, regRA, 8, 24, 224 + id * 2); + + regBG = 0; + SET_REG_FIELD(0x1E6, regBG, 8, 0, color.b); + SET_REG_FIELD(0x1E7, regBG, 8, 12, color.g); + SET_REG_FIELD(0x1E8, regBG, 4, 20, 8); + SET_REG_FIELD(0x1E9, regBG, 8, 24, 225 + id * 2); + + GX_WRITE_RAS_REG(regRA); + GX_WRITE_RAS_REG(regBG); + gx->bpSentNot = 0; +} + +void GXSetTevKColorSel(GXTevStageID stage, GXTevKColorSel sel) +{ + u32 *Kreg; + + CHECK_GXBEGIN(0x368, "GXSetTevKColorSel"); + ASSERTMSGLINE(0x369, stage < 16, "GXSetTevKColor*: Invalid Tev Stage Index"); + + Kreg = &gx->tevKsel[stage >> 1]; + if (stage & 1) { + SET_REG_FIELD(0x20A, *Kreg, 5, 14, sel); + } + else { + SET_REG_FIELD(0x20C, *Kreg, 5, 4, sel); + } + + GX_WRITE_RAS_REG(*Kreg); + gx->bpSentNot = 0; +} + +void GXSetTevKAlphaSel(GXTevStageID stage, GXTevKAlphaSel sel) +{ + u32 *Kreg; + + CHECK_GXBEGIN(0x389, "GXSetTevKAlphaSel"); + ASSERTMSGLINE(0x38A, stage < 16, "GXSetTevKColor*: Invalid Tev Stage Index"); + + Kreg = &gx->tevKsel[stage >> 1]; + if (stage & 1) { + SET_REG_FIELD(0x22B, *Kreg, 5, 19, sel); + } + else { + SET_REG_FIELD(0x22D, *Kreg, 5, 9, sel); + } + + GX_WRITE_RAS_REG(*Kreg); + gx->bpSentNot = 0; +} + +void GXSetTevSwapMode(GXTevStageID stage, GXTevSwapSel ras_sel, GXTevSwapSel tex_sel) +{ + u32 *pTevReg; + + CHECK_GXBEGIN(0x3AE, "GXSetTevSwapMode"); + ASSERTMSGLINE(0x3AF, stage < 16, "GXSetTevSwapMode: Invalid Tev Stage Index"); + + pTevReg = &gx->teva[stage]; + SET_REG_FIELD(0x24E, *pTevReg, 2, 0, ras_sel); + SET_REG_FIELD(0x24F, *pTevReg, 2, 2, tex_sel); + + GX_WRITE_RAS_REG(*pTevReg); + gx->bpSentNot = 0; +} + +void GXSetTevSwapModeTable(GXTevSwapSel table, GXTevColorChan red, GXTevColorChan green, GXTevColorChan blue, GXTevColorChan alpha) +{ + u32 *Kreg; +#if !DEBUG + // not a real variable, but needed to match release + int index = table * 2; +#endif + + CHECK_GXBEGIN(0x3D2, "GXSetTevSwapModeTable"); + ASSERTMSGLINE(0x3D3, table < 4, "GXSetTevSwapModeTable: Invalid Swap Selection Index"); + +#if DEBUG + Kreg = &gx->tevKsel[table * 2]; +#else + Kreg = &gx->tevKsel[index]; +#endif + SET_REG_FIELD(0x272, *Kreg, 2, 0, red); + SET_REG_FIELD(0x273, *Kreg, 2, 2, green); + + GX_WRITE_RAS_REG(*Kreg); + + Kreg = &gx->tevKsel[table * 2 + 1]; + SET_REG_FIELD(0x277, *Kreg, 2, 0, blue); + SET_REG_FIELD(0x278, *Kreg, 2, 2, alpha); + + GX_WRITE_RAS_REG(*Kreg); + gx->bpSentNot = 0; +} + +void GXSetTevClampMode(void) +{ + ASSERTMSGLINE(0x3F4, 0, "GXSetTevClampMode: not available on this hardware"); +} + +void GXSetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1) +{ + u32 reg = 0; + + CHECK_GXBEGIN(0x416, "GXSetAlphaCompare"); + SET_REG_FIELD(0x2B4, reg, 8, 0, ref0); + SET_REG_FIELD(0x2B5, reg, 8, 8, ref1); + SET_REG_FIELD(0x2B6, reg, 3, 16, comp0); + SET_REG_FIELD(0x2B7, reg, 3, 19, comp1); + SET_REG_FIELD(0x2B8, reg, 2, 22, op); + SET_REG_FIELD(0x2B9, reg, 8, 24, 0xF3); + + GX_WRITE_RAS_REG(reg); + gx->bpSentNot = 0; +} + +void GXSetZTexture(GXZTexOp op, GXTexFmt fmt, u32 bias) +{ + u32 zenv0; + u32 zenv1; + u32 type; + + CHECK_GXBEGIN(0x435, "GXSetZTexture"); + + zenv0 = 0; + SET_REG_FIELD(0x2D4, zenv0, 24, 0, bias); + SET_REG_FIELD(0x2D5, zenv0, 8, 24, 0xF4); + + zenv1 = 0; + switch (fmt) { + case GX_TF_Z8: + type = 0; + break; + case GX_TF_Z16: + type = 1; + break; + case GX_TF_Z24X8: + type = 2; + break; + default: + ASSERTMSGLINE(0x441, 0, "GXSetZTexture: Invalid z-texture format"); + type = 2; + break; + } + SET_REG_FIELD(0x2E0, zenv1, 2, 0, type); + SET_REG_FIELD(0x2E1, zenv1, 2, 2, op); + SET_REG_FIELD(0x2E2, zenv1, 8, 24, 0xF5); + + GX_WRITE_RAS_REG(zenv0); + GX_WRITE_RAS_REG(zenv1); + gx->bpSentNot = 0; +} + +void GXSetTevOrder(GXTevStageID stage, GXTexCoordID coord, GXTexMapID map, GXChannelID color) +{ + u32 *ptref; + u32 tmap; + u32 tcoord; + static int c2r[] = { 0, 1, 0, 1, 0, 1, 7, 5, 6 }; + + CHECK_GXBEGIN(0x46B, "GXSetTevOrder"); + ASSERTMSGLINE(0x46C, stage < 16, "GXSetTevOrder: Invalid Tev Stage Index"); + ASSERTMSGLINE(0x46E, coord < 8 || coord == 0xFF, "GXSetTevOrder: Invalid Texcoord"); + ASSERTMSGLINE(0x470, (map & ~0x100) < 8 || map == 0xFF, "GXSetTevOrder: Invalid Tex Map"); + ASSERTMSGLINE(0x472, color >= 4 && color <= 0xFF, "GXSetTevOrder: Invalid Color Channel ID"); + + ptref = &gx->tref[stage / 2]; + gx->texmapId[stage] = map; + + tmap = map & ~0x100; + tmap = (tmap >= GX_MAX_TEXMAP) ? GX_TEXMAP0 : tmap; + + if (coord >= GX_MAX_TEXCOORD) { + tcoord = GX_TEXCOORD0; + gx->tevTcEnab = gx->tevTcEnab & ~(1 << stage); + } + else { + tcoord = coord; + gx->tevTcEnab = gx->tevTcEnab | (1 << stage); + } + + if (stage & 1) { + SET_REG_FIELD(0x486, *ptref, 3, 12, tmap); + SET_REG_FIELD(0x487, *ptref, 3, 15, tcoord); + SET_REG_FIELD(0x489, *ptref, 3, 19, (color == GX_COLOR_NULL) ? 7 : c2r[color]); + SET_REG_FIELD(0x48B, *ptref, 1, 18, (map != GX_TEXMAP_NULL && !(map & 0x100))); + } + else { + SET_REG_FIELD(0x48E, *ptref, 3, 0, tmap); + SET_REG_FIELD(0x48F, *ptref, 3, 3, tcoord); + SET_REG_FIELD(0x491, *ptref, 3, 7, (color == GX_COLOR_NULL) ? 7 : c2r[color]); + SET_REG_FIELD(0x493, *ptref, 1, 6, (map != GX_TEXMAP_NULL && !(map & 0x100))); + } + + GX_WRITE_RAS_REG(*ptref); + gx->bpSentNot = 0; + gx->dirtyState |= 1; +} + +void GXSetNumTevStages(u8 nStages) +{ + CHECK_GXBEGIN(0x4A3, "GXSetNumTevStages"); + + ASSERTMSGLINE(0x4A5, nStages != 0 && nStages <= 16, "GXSetNumTevStages: Exceed max number of tex stages"); + SET_REG_FIELD(0x334, gx->genMode, 4, 10, nStages - 1); + gx->dirtyState |= 4; +} diff --git a/src/dolphin/gx/GXTexture.c b/src/dolphin/gx/GXTexture.c new file mode 100644 index 00000000..ec67f795 --- /dev/null +++ b/src/dolphin/gx/GXTexture.c @@ -0,0 +1,1269 @@ +#include +#include + +#include + +// GXTexObj internal data +typedef struct __GXTexObjInt_struct { + u32 mode0; + u32 mode1; + u32 image0; + u32 image3; + void *userData; + GXTexFmt fmt; + u32 tlutName; + u16 loadCnt; + u8 loadFmt; + u8 flags; +} __GXTexObjInt; + +// GXTexRegion internal data +typedef struct __GXTexRegionInt_struct { + u32 image1; + u32 image2; + u16 sizeEven; + u16 sizeOdd; + u8 is32bMipmap; + u8 isCached; +} __GXTexRegionInt; + +// GXTlutObj internal data +typedef struct __GXTlutObjInt_struct { + u32 tlut; + u32 loadTlut0; + u16 numEntries; +} __GXTlutObjInt; + +// GXTlutRegion internal data +typedef struct __GXTlutRegionInt_struct { + u32 loadTlut1; + __GXTlutObjInt tlutObj; +} __GXTlutRegionInt; + +u8 GXTexMode0Ids[8] = { 0x80, 0x81, 0x82, 0x83, 0xA0, 0xA1, 0xA2, 0xA3 }; +u8 GXTexMode1Ids[8] = { 0x84, 0x85, 0x86, 0x87, 0xA4, 0xA5, 0xA6, 0xA7 }; +u8 GXTexImage0Ids[8] = { 0x88, 0x89, 0x8A, 0x8B, 0xA8, 0xA9, 0xAA, 0xAB }; +u8 GXTexImage1Ids[8] = { 0x8C, 0x8D, 0x8E, 0x8F, 0xAC, 0xAD, 0xAE, 0xAF }; +u8 GXTexImage2Ids[8] = { 0x90, 0x91, 0x92, 0x93, 0xB0, 0xB1, 0xB2, 0xB3 }; +u8 GXTexImage3Ids[8] = { 0x94, 0x95, 0x96, 0x97, 0xB4, 0xB5, 0xB6, 0xB7 }; +u8 GXTexTlutIds[8] = { 0x98, 0x99, 0x9A, 0x9B, 0xB8, 0xB9, 0xBA, 0xBB }; +static u8 GX2HWFiltConv[6] = { 0x00, 0x04, 0x01, 0x05, 0x02, 0x06 }; +static u8 HW2GXFiltConv[8] = { 0x00, 0x02, 0x04, 0x00, 0x01, 0x03, 0x05, 0x00 }; + +static void __GXGetTexTileShift(GXTexFmt fmt, u32 *rowTileS, u32 *colTileS) +{ + switch (fmt) { + case GX_TF_I4: + case 0x8: + case GX_TF_CMPR: + case GX_CTF_R4: + case GX_CTF_Z4: + *rowTileS = 3; + *colTileS = 3; + break; + case GX_TF_I8: + case GX_TF_IA4: + case 0x9: + case GX_TF_Z8: + case GX_CTF_RA4: + case GX_TF_A8: + case GX_CTF_R8: + case GX_CTF_G8: + case GX_CTF_B8: + case GX_CTF_Z8M: + case GX_CTF_Z8L: + *rowTileS = 3; + *colTileS = 2; + break; + case GX_TF_IA8: + case GX_TF_RGB565: + case GX_TF_RGB5A3: + case GX_TF_RGBA8: + case 0xA: + case GX_TF_Z16: + case GX_TF_Z24X8: + case GX_CTF_RA8: + case GX_CTF_RG8: + case GX_CTF_GB8: + case GX_CTF_Z16L: + *rowTileS = 2; + *colTileS = 2; + break; + default: + *rowTileS = *colTileS = 0; + ASSERTMSGLINEV(0x1BC, 0, "%s: invalid texture format", "GX"); + break; + } +} + +u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, u8 mipmap, u8 max_lod) +{ + u32 tileShiftX; + u32 tileShiftY; + u32 tileBytes; + u32 bufferSize; + u32 nx; + u32 ny; + u32 level; + + ASSERTMSGLINEV(0x1CC, width <= 1024, "%s: width too large", "GXGetTexBufferSize"); + ASSERTMSGLINEV(0x1CD, height <= 1024, "%s: height too large", "GXGetTexBufferSize"); + + __GXGetTexTileShift(format, &tileShiftX, &tileShiftY); + if (format == GX_TF_RGBA8 || format == GX_TF_Z24X8) { + tileBytes = 64; + } + else { + tileBytes = 32; + } + if (mipmap == 1) { + nx = 1 << (31 - __cntlzw(width)); + ASSERTMSGLINEV(0x1DF, width == nx, "%s: width must be a power of 2", "GXGetTexBufferSize"); + ny = 1 << (31 - __cntlzw(height)); + ASSERTMSGLINEV(0x1E2, height == ny, "%s: height must be a power of 2", "GXGetTexBufferSize"); + + bufferSize = 0; + for (level = 0; level < max_lod; level++) { + nx = (width + (1 << tileShiftX) - 1) >> tileShiftX; + ny = (height + (1 << tileShiftY) - 1) >> tileShiftY; + bufferSize += tileBytes * (nx * ny); + if (width == 1 && height == 1) { + break; + } + width = (width > 1) ? width >> 1 : 1; + height = (height > 1) ? height >> 1 : 1; + } + } + else { + nx = (width + (1 << tileShiftX) - 1) >> tileShiftX; + ny = (height + (1 << tileShiftY) - 1) >> tileShiftY; + bufferSize = nx * ny * tileBytes; + } + return bufferSize; +} + +void __GetImageTileCount(GXTexFmt fmt, u16 wd, u16 ht, u32 *rowTiles, u32 *colTiles, u32 *cmpTiles) +{ + u32 texRowShift; + u32 texColShift; + + __GXGetTexTileShift(fmt, &texRowShift, &texColShift); + if (wd == 0) { + wd = 1; + } + if (ht == 0) { + ht = 1; + } + *rowTiles = (wd + (1 << texRowShift) - 1) >> texRowShift; + *colTiles = (ht + (1 << texColShift) - 1) >> texColShift; + *cmpTiles = (fmt == GX_TF_RGBA8 || fmt == GX_TF_Z24X8) ? 2 : 1; +} + +#define SOME_SET_REG_MACRO(reg, val) \ + do { \ + (reg) = (u32)__rlwinm((u32)(reg), 0, 27, 23) | val; \ + } while (0); + +void GXInitTexObj(GXTexObj *obj, void *image_ptr, u16 width, u16 height, GXTexFmt format, GXTexWrapMode wrap_s, GXTexWrapMode wrap_t, u8 mipmap) +{ + u32 imageBase; + u32 maxLOD; + u16 rowT; + u16 colT; + u32 rowC; + u32 colC; + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x235, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x237, "GXInitTexObj"); + ASSERTMSGLINEV(0x238, width <= 1024, "%s: width too large", "GXInitTexObj"); + ASSERTMSGLINEV(0x239, height <= 1024, "%s: height too large", "GXInitTexObj"); + ASSERTMSGLINEV(0x23B, !(format & 0x20), "%s: invalid texture format", "GXInitTexObj"); + memset(t, 0, 0x20); + SET_REG_FIELD(0x258, t->mode0, 2, 0, wrap_s); + SET_REG_FIELD(0x259, t->mode0, 2, 2, wrap_t); + SET_REG_FIELD(0x25A, t->mode0, 1, 4, 1); + if (mipmap != 0) { + u8 lmax; + t->flags |= 1; + + if (format == 8 || format == 9 || format == 10) { + SOME_SET_REG_MACRO(t->mode0, 0xa0); + } + else { + SOME_SET_REG_MACRO(t->mode0, 0xc0); + } + + if (width > height) { + maxLOD = 31 - __cntlzw(width); + } + else { + maxLOD = 31 - __cntlzw(height); + } + lmax = 16.0f * maxLOD; + SET_REG_FIELD(0x278, t->mode1, 8, 8, lmax); + } + else { + SOME_SET_REG_MACRO(t->mode0, 0x80); + } + t->fmt = format; + SET_REG_FIELD(0x286, t->image0, 10, 0, width - 1); + SET_REG_FIELD(0x287, t->image0, 10, 10, height - 1); + SET_REG_FIELD(0x288, t->image0, 4, 20, format & 0xF); + ASSERTMSGLINEV(0x28E, ((u32)image_ptr & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexObj", "image"); + imageBase = (u32)((u32)image_ptr >> 5) & 0x01FFFFFF; + SET_REG_FIELD(0x290, t->image3, 21, 0, imageBase); + switch (format & 0xF) { + case 0: + case 8: + t->loadFmt = 1; + rowT = 3; + colT = 3; + break; + case 1: + case 2: + case 9: + t->loadFmt = 2; + rowT = 3; + colT = 2; + break; + case 3: + case 4: + case 5: + case 10: + t->loadFmt = 2; + rowT = 2; + colT = 2; + break; + case 6: + t->loadFmt = 3; + rowT = 2; + colT = 2; + break; + case 14: + t->loadFmt = 0; + rowT = 3; + colT = 3; + break; + default: + ASSERTMSGLINEV(0x2BB, 0, "%s: invalid texture format", "GXPreLoadEntireTexture"); + t->loadFmt = 2; + rowT = 2; + colT = 2; + break; + } + rowC = (width + (1 << rowT) - 1) >> rowT; + colC = (height + (1 << colT) - 1) >> colT; + t->loadCnt = (rowC * colC) & 0x7FFF; + t->flags |= 2; +} + +void GXInitTexObjCI( + GXTexObj *obj, void *image_ptr, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrap_s, GXTexWrapMode wrap_t, u8 mipmap, u32 tlut_name) +{ + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x2E1, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x2E3, "GXInitTexObjCI"); + GXInitTexObj(obj, image_ptr, width, height, format, wrap_s, wrap_t, mipmap); + t->flags &= 0xFFFFFFFD; + t->tlutName = tlut_name; +} + +void GXInitTexObjLOD(GXTexObj *obj, GXTexFilter min_filt, GXTexFilter mag_filt, f32 min_lod, f32 max_lod, f32 lod_bias, u8 bias_clamp, u8 do_edge_lod, + GXAnisotropy max_aniso) +{ + u8 lbias; + u8 lmin; + u8 lmax; + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x308, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x30A, "GXInitTexObjLOD"); + + if (lod_bias < -4.0f) { + lod_bias = -4.0f; + } + else if (lod_bias >= 4.0f) { + lod_bias = 3.99f; + } + lbias = 32.0f * lod_bias; + SET_REG_FIELD(0x314, t->mode0, 8, 9, lbias); + ASSERTMSG1LINE(0x317, (u32)mag_filt <= 1, "%s: invalid mag_filt value", "GXInitTexObjLOD"); + SET_REG_FIELD(0x318, t->mode0, 1, 4, (mag_filt == GX_LINEAR) ? 1 : 0); + ASSERTMSG1LINE(0x31B, (u32)min_filt <= 5, "%s: invalid min_filt value", "GXInitTexObjLOD"); + SET_REG_FIELD(0x31C, t->mode0, 3, 5, GX2HWFiltConv[min_filt]); + SET_REG_FIELD(0x31E, t->mode0, 1, 8, do_edge_lod ? 0 : 1); + SET_REG_FIELD(0x321, t->mode0, 1, 17, 0); + SET_REG_FIELD(0x321, t->mode0, 1, 18, 0); + SET_REG_FIELD(0x321, t->mode0, 2, 19, max_aniso); + SET_REG_FIELD(0x322, t->mode0, 1, 21, bias_clamp); + + if (min_lod < 0.0f) { + min_lod = 0.0f; + } + else if (min_lod > 10.0f) { + min_lod = 10.0f; + } + lmin = 16.0f * min_lod; + if (max_lod < 0.0f) { + max_lod = 0.0f; + } + else if (max_lod > 10.0f) { + max_lod = 10.0f; + } + lmax = 16.0f * max_lod; + SET_REG_FIELD(0x330, t->mode1, 8, 0, lmin); + SET_REG_FIELD(0x331, t->mode1, 8, 8, lmax); +} + +void GXInitTexObjData(GXTexObj *obj, void *image_ptr) +{ + u32 imageBase; + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x343, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x345, "GXInitTexObjData"); + ASSERTMSGLINEV(0x348, ((u32)image_ptr & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexObjData", "image"); + imageBase = ((u32)image_ptr >> 5) & 0x01FFFFFF; + SET_REG_FIELD(0x34B, t->image3, 21, 0, imageBase); +} + +void GXInitTexObjWrapMode(GXTexObj *obj, GXTexWrapMode sm, GXTexWrapMode tm) +{ + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x35C, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x35E, "GXInitTexObjWrapMode"); + SET_REG_FIELD(0x360, t->mode0, 2, 0, sm); + SET_REG_FIELD(0x361, t->mode0, 2, 2, tm); +} + +void GXInitTexObjTlut(GXTexObj *obj, u32 tlut_name) +{ + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x371, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x373, "GXInitTexObjTlut"); + t->tlutName = tlut_name; +} + +void GXInitTexObjFilter(GXTexObj *obj, GXTexFilter min_filt, GXTexFilter mag_filt) +{ + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x386, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x388, "GXInitTexObjFilter"); + + ASSERTMSG1LINE(0x38B, (u32)mag_filt <= 1, "%s: invalid mag_filt value", "GXInitTexObjFilter"); + SET_REG_FIELD(0x38C, t->mode0, 1, 4, mag_filt == 1 ? 1 : 0); + + ASSERTMSG1LINE(0x38F, (u32)min_filt <= 5, "%s: invalid min_filt value", "GXInitTexObjFilter"); + SET_REG_FIELD(0x390, t->mode0, 3, 5, GX2HWFiltConv[min_filt]); +} + +void GXInitTexObjMaxLOD(GXTexObj *obj, f32 max_lod) +{ + u8 lmax; + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x3A2, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x3A4, "GXInitTexObjMaxLOD"); + + if (max_lod < 0.0f) { + max_lod = 0.0f; + } + else if (max_lod > 10.0f) { + max_lod = 10.0f; + } + lmax = 16.0f * max_lod; + SET_REG_FIELD(0x3AA, t->mode1, 8, 8, lmax); +} + +void GXInitTexObjMinLOD(GXTexObj *obj, f32 min_lod) +{ + u8 lmin; + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x3BC, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x3BE, "GXInitTexObjMinLOD"); + + if (min_lod < 0.0f) { + min_lod = 0.0f; + } + else if (min_lod > 10.0f) { + min_lod = 10.0f; + } + lmin = 16.0f * min_lod; + SET_REG_FIELD(0x3C4, t->mode1, 8, 0, lmin); +} + +void GXInitTexObjLODBias(GXTexObj *obj, f32 lod_bias) +{ + u8 lbias; // r30 + __GXTexObjInt *t = (__GXTexObjInt *)obj; // r29 + + ASSERTMSGLINE(0x3D6, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x3D8, "GXInitTexObjLODBias"); + + if (lod_bias < -4.0f) { + lod_bias = -4.0f; + } + else if (lod_bias >= 4.0f) { + lod_bias = 3.99f; + } + lbias = 32.0f * lod_bias; + SET_REG_FIELD(0x3DF, t->mode0, 8, 9, lbias); +} + +void GXInitTexObjBiasClamp(GXTexObj *obj, u8 bias_clamp) +{ + __GXTexObjInt *t = (__GXTexObjInt *)obj; // r30 + + ASSERTMSGLINE(0x3EF, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x3F1, "GXInitTexObjBiasClamp"); + + SET_REG_FIELD(0x3F3, t->mode0, 1, 21, bias_clamp); +} + +void GXInitTexObjEdgeLOD(GXTexObj *obj, u8 do_edge_lod) +{ + __GXTexObjInt *t = (__GXTexObjInt *)obj; // r30 + + ASSERTMSGLINE(0x403, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x405, "GXInitTexObjEdgeLOD"); + + SET_REG_FIELD(0x407, t->mode0, 1, 8, do_edge_lod ? 0 : 1); +} + +void GXInitTexObjMaxAniso(GXTexObj *obj, GXAnisotropy max_aniso) +{ + __GXTexObjInt *t = (__GXTexObjInt *)obj; // r30 + + ASSERTMSGLINE(0x417, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x419, "GXInitTexObjMaxAniso"); + + SET_REG_FIELD(0x41B, t->mode0, 2, 19, max_aniso); +} + +void GXInitTexObjUserData(GXTexObj *obj, void *user_data) +{ + __GXTexObjInt *t = (__GXTexObjInt *)obj; + + ASSERTMSGLINE(0x42C, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x42D, "GXInitTexObjUserData"); + t->userData = user_data; +} + +void *GXGetTexObjUserData(const GXTexObj *obj) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)obj; + + ASSERTMSGLINE(0x433, obj, "Texture Object Pointer is null"); + return t->userData; +} + +void GXGetTexObjAll( + const GXTexObj *obj, void **image_ptr, u16 *width, u16 *height, GXTexFmt *format, GXTexWrapMode *wrap_s, GXTexWrapMode *wrap_t, u8 *mipmap) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)obj; + + ASSERTMSGLINE(0x447, obj, "Texture Object Pointer is null"); + *image_ptr = (void *)(GET_REG_FIELD(t->image3, 21, 0) << 5); + *width = (u32)GET_REG_FIELD(t->image0, 10, 0) + 1; + *height = (u32)GET_REG_FIELD(t->image0, 10, 10) + 1; + *format = t->fmt; + *wrap_s = GET_REG_FIELD(t->mode0, 2, 0); + *wrap_t = GET_REG_FIELD(t->mode0, 2, 2); + *mipmap = (t->flags & 1) == 1; +} + +void *GXGetTexObjData(const GXTexObj *to) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)to; + + ASSERTMSGLINE(0x454, to, "Texture Object Pointer is null"); + return (void *)(GET_REG_FIELD(t->image3, 21, 0) << 5); +} + +u16 GXGetTexObjWidth(const GXTexObj *to) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)to; + + ASSERTMSGLINE(0x45A, to, "Texture Object Pointer is null"); + return (u32)GET_REG_FIELD(t->image0, 10, 0) + 1; +} + +u16 GXGetTexObjHeight(const GXTexObj *to) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)to; + + ASSERTMSGLINE(0x460, to, "Texture Object Pointer is null"); + return (u32)GET_REG_FIELD(t->image0, 10, 10) + 1; +} + +GXTexFmt GXGetTexObjFmt(const GXTexObj *to) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)to; + + ASSERTMSGLINE(0x466, to, "Texture Object Pointer is null"); + return t->fmt; +} + +GXTexWrapMode GXGetTexObjWrapS(const GXTexObj *to) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)to; + + ASSERTMSGLINE(0x46C, to, "Texture Object Pointer is null"); + return GET_REG_FIELD(t->mode0, 2, 0); +} + +GXTexWrapMode GXGetTexObjWrapT(const GXTexObj *to) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)to; + + ASSERTMSGLINE(0x472, to, "Texture Object Pointer is null"); + return GET_REG_FIELD(t->mode0, 2, 2); +} + +GXBool GXGetTexObjMipMap(const GXTexObj *to) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)to; + + ASSERTMSGLINE(0x478, to, "Texture Object Pointer is null"); + return (t->flags & 1) == 1; +} + +// NONMATCHING +void GXGetTexObjLODAll(const GXTexObj *tex_obj, GXTexFilter *min_filt, GXTexFilter *mag_filt, f32 *min_lod, f32 *max_lod, f32 *lod_bias, + u8 *bias_clamp, u8 *do_edge_lod, GXAnisotropy *max_aniso) +{ + s16 tmp; // r30 + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x48E, tex_obj, "Texture Object Pointer is null"); + *min_filt = HW2GXFiltConv[GET_REG_FIELD(t->mode0, 3, 5)]; + *mag_filt = GET_REG_FIELD(t->mode0, 1, 4); + *min_lod = (u8)t->mode1 / 16.0f; + *max_lod = (u32)GET_REG_FIELD(t->mode1, 8, 8) / 16.0f; + tmp = (s32)GET_REG_FIELD(t->mode0, 8, 9); + *lod_bias = (s8)tmp * 0.03125f; + *bias_clamp = (u32)GET_REG_FIELD(t->mode0, 1, 21); + *do_edge_lod = !GET_REG_FIELD(t->mode0, 1, 8); + *max_aniso = GET_REG_FIELD(t->mode0, 2, 19); +} + +GXTexFilter GXGetTexObjMinFilt(const GXTexObj *tex_obj) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x49E, tex_obj, "Texture Object Pointer is null"); + return HW2GXFiltConv[GET_REG_FIELD(t->mode0, 3, 5)]; +} + +GXTexFilter GXGetTexObjMagFilt(const GXTexObj *tex_obj) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x4A5, tex_obj, "Texture Object Pointer is null"); + return GET_REG_FIELD(t->mode0, 1, 4); +} + +f32 GXGetTexObjMinLOD(const GXTexObj *tex_obj) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x4AB, tex_obj, "Texture Object Pointer is null"); + return (u32)GET_REG_FIELD(t->mode1, 8, 0) / 16.0f; +} + +f32 GXGetTexObjMaxLOD(const GXTexObj *tex_obj) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x4B1, tex_obj, "Texture Object Pointer is null"); + return (u32)GET_REG_FIELD(t->mode1, 8, 8) / 16.0f; +} + +// NONMATCHING +f32 GXGetTexObjLODBias(const GXTexObj *tex_obj) +{ + s16 tmp; + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x4B8, tex_obj, "Texture Object Pointer is null"); + tmp = (s32)GET_REG_FIELD(t->mode0, 8, 9); + return (s8)tmp * 0.03125f; +} + +GXBool GXGetTexObjBiasClamp(const GXTexObj *tex_obj) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x4BF, tex_obj, "Texture Object Pointer is null"); + return (u32)GET_REG_FIELD(t->mode0, 1, 21); +} + +GXBool GXGetTexObjEdgeLOD(const GXTexObj *tex_obj) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x4C5, tex_obj, "Texture Object Pointer is null"); + return !GET_REG_FIELD(t->mode0, 1, 8); +} + +GXAnisotropy GXGetTexObjMaxAniso(const GXTexObj *tex_obj) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x4CB, tex_obj, "Texture Object Pointer is null"); + return GET_REG_FIELD(t->mode0, 2, 19); +} + +u32 GXGetTexObjTlut(const GXTexObj *tex_obj) +{ + const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; + + ASSERTMSGLINE(0x4D1, tex_obj, "Texture Object Pointer is null"); + return t->tlutName; +} + +void GXLoadTexObjPreLoaded(GXTexObj *obj, GXTexRegion *region, GXTexMapID id) +{ + __GXTlutRegionInt *tlr; + __GXTexObjInt *t = (__GXTexObjInt *)obj; + __GXTexRegionInt *r = (__GXTexRegionInt *)region; + + ASSERTMSGLINE(0x4E9, obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x4E9, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x4EB, "GXLoadTexObjPreLoaded"); + ASSERTMSGLINEV(0x4EC, id < 8, "%s: invalid texture map ID", "GXLoadTexObj"); + + SET_REG_FIELD(0x4F7, t->mode0, 8, 24, GXTexMode0Ids[id]); + SET_REG_FIELD(0x4F8, t->mode1, 8, 24, GXTexMode1Ids[id]); + SET_REG_FIELD(0x4F9, t->image0, 8, 24, GXTexImage0Ids[id]); + SET_REG_FIELD(0x4FA, r->image1, 8, 24, GXTexImage1Ids[id]); + SET_REG_FIELD(0x4FB, r->image2, 8, 24, GXTexImage2Ids[id]); + SET_REG_FIELD(0x4FC, t->image3, 8, 24, GXTexImage3Ids[id]); + + GX_WRITE_RAS_REG(t->mode0); + GX_WRITE_RAS_REG(t->mode1); + GX_WRITE_RAS_REG(t->image0); + GX_WRITE_RAS_REG(r->image1); + GX_WRITE_RAS_REG(r->image2); + GX_WRITE_RAS_REG(t->image3); + + if (!(t->flags & 2)) { + ASSERTMSGLINEV(0x507, gx->tlutRegionCallback, "%s: Tex/Tlut Region Callback not set", "GXLoadTexObj/PreLoaded"); + tlr = (__GXTlutRegionInt *)gx->tlutRegionCallback(t->tlutName); + ASSERTMSGLINEV(0x509, tlr, "%s: Tex/Tlut Region Callback returns NULL", "GXLoadTexObj/PreLoaded"); + + SET_REG_FIELD(0x50B, tlr->tlutObj.tlut, 8, 24, GXTexTlutIds[id]); + GX_WRITE_RAS_REG(tlr->tlutObj.tlut); + } + gx->tImage0[id] = t->image0; + gx->tMode0[id] = t->mode0; + gx->dirtyState |= 1; + gx->bpSentNot = 0; +} + +void GXLoadTexObj(GXTexObj *obj, GXTexMapID id) +{ + GXTexRegion *r; + + CHECK_GXBEGIN(0x526, "GXLoadTexObj"); + ASSERTMSGLINEV(0x527, id < 8, "%s: invalid texture map ID", "GXLoadTexObj"); + ASSERTMSGLINEV(0x52C, gx->texRegionCallback, "%s: Tex/Tlut Region Callback not set", "GXLoadTexObj"); + r = gx->texRegionCallback(obj, id); + ASSERTMSGLINEV(0x52E, r, "%s: Tex/Tlut Region Callback returns NULL", "GXLoadTexObj"); + GXLoadTexObjPreLoaded(obj, r, id); +} + +void GXInitTlutObj(GXTlutObj *tlut_obj, void *lut, GXTlutFmt fmt, u16 n_entries) +{ + __GXTlutObjInt *t = (__GXTlutObjInt *)tlut_obj; + + ASSERTMSGLINE(0x546, tlut_obj, "TLut Object Pointer is null"); + CHECK_GXBEGIN(0x547, "GXInitTlutObj"); + ASSERTMSGLINEV(0x54A, n_entries <= 0x4000, "%s: number of entries exceeds maximum", "GXInitTlutObj"); + ASSERTMSGLINEV(0x54C, ((u32)lut & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTlutObj", "Tlut"); + t->tlut = 0; + SET_REG_FIELD(0x54F, t->tlut, 2, 10, fmt); + SET_REG_FIELD(0x550, t->loadTlut0, 21, 0, ((u32)lut & 0x3FFFFFFF) >> 5); + SET_REG_FIELD(0x551, t->loadTlut0, 8, 24, 0x64); + t->numEntries = n_entries; +} + +void GXGetTlutObjAll(const GXTlutObj *tlut_obj, void **data, GXTlutFmt *format, u16 *numEntries) +{ + const __GXTlutObjInt *t = (const __GXTlutObjInt *)tlut_obj; + + ASSERTMSGLINE(0x566, tlut_obj, "TLut Object Pointer is null"); + *data = (void *)(GET_REG_FIELD(t->loadTlut0, 21, 0) << 5); + *format = GET_REG_FIELD(t->tlut, 2, 10); + *numEntries = t->numEntries; +} + +void *GXGetTlutObjData(const GXTlutObj *tlut_obj) +{ + const __GXTlutObjInt *t = (const __GXTlutObjInt *)tlut_obj; + + ASSERTMSGLINE(0x56F, tlut_obj, "TLut Object Pointer is null"); + return (void *)(GET_REG_FIELD(t->loadTlut0, 21, 0) << 5); +} + +GXTlutFmt GXGetTlutObjFmt(const GXTlutObj *tlut_obj) +{ + const __GXTlutObjInt *t = (const __GXTlutObjInt *)tlut_obj; + + ASSERTMSGLINE(0x576, tlut_obj, "TLut Object Pointer is null"); + return GET_REG_FIELD(t->tlut, 2, 10); +} + +u16 GXGetTlutObjNumEntries(const GXTlutObj *tlut_obj) +{ + const __GXTlutObjInt *t = (const __GXTlutObjInt *)tlut_obj; + + ASSERTMSGLINE(0x57D, tlut_obj, "TLut Object Pointer is null"); + return t->numEntries; +} + +void GXLoadTlut(GXTlutObj *tlut_obj, u32 tlut_name) +{ + __GXTlutRegionInt *r; + u32 tlut_offset; + __GXTlutObjInt *t = (__GXTlutObjInt *)tlut_obj; + + ASSERTMSGLINE(0x598, tlut_obj, "TLut Object Pointer is null"); + CHECK_GXBEGIN(0x59A, "GXLoadTlut"); + ASSERTMSGLINEV(0x59B, gx->tlutRegionCallback, "%s: Tex/Tlut Region Callback not set", "GXLoadTlut"); + r = (__GXTlutRegionInt *)gx->tlutRegionCallback(tlut_name); + ASSERTMSGLINEV(0x59D, r, "%s: Tex/Tlut Region Callback returns NULL", "GXLoadTlut"); + __GXFlushTextureState(); + GX_WRITE_RAS_REG(t->loadTlut0); + GX_WRITE_RAS_REG(r->loadTlut1); + __GXFlushTextureState(); + tlut_offset = r->loadTlut1 & 0x3FF; + SET_REG_FIELD(0x5AD, t->tlut, 10, 0, tlut_offset); + r->tlutObj = *t; +} + +void GXInitTexCacheRegion(GXTexRegion *region, u8 is_32b_mipmap, u32 tmem_even, GXTexCacheSize size_even, u32 tmem_odd, GXTexCacheSize size_odd) +{ + u32 WidthExp2; + __GXTexRegionInt *t = (__GXTexRegionInt *)region; + + ASSERTMSGLINE(0x5CC, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x5CE, "GXInitTexCacheRegion"); + ASSERTMSGLINEV(0x5D0, (tmem_even & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexCacheRegion", "tmem even"); + ASSERTMSGLINEV(0x5D2, (tmem_odd & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexCacheRegion", "tmem odd"); + switch (size_even) { + case GX_TEXCACHE_32K: + WidthExp2 = 3; + break; + case GX_TEXCACHE_128K: + WidthExp2 = 4; + break; + case GX_TEXCACHE_512K: + WidthExp2 = 5; + break; + default: + ASSERTMSGLINEV(0x5DA, 0, "%s: Invalid %s size", "GXInitTexCacheRegion", "tmem even"); + break; + } + t->image1 = 0; + SET_REG_FIELD(0x5DF, t->image1, 15, 0, tmem_even >> 5); + SET_REG_FIELD(0x5E0, t->image1, 3, 15, WidthExp2); + SET_REG_FIELD(0x5E1, t->image1, 3, 18, WidthExp2); + SET_REG_FIELD(0x5E2, t->image1, 1, 21, 0); + + switch (size_odd) { + case GX_TEXCACHE_32K: + WidthExp2 = 3; + break; + case GX_TEXCACHE_128K: + WidthExp2 = 4; + break; + case GX_TEXCACHE_512K: + WidthExp2 = 5; + break; + case GX_TEXCACHE_NONE: + WidthExp2 = 0; + break; + default: + ASSERTMSGLINEV(0x5EA, 0, "%s: Invalid %s size", "GXInitTexCacheRegion", "tmem odd"); + break; + } + t->image2 = 0; + SET_REG_FIELD(0x5EF, t->image2, 15, 0, tmem_odd >> 5); + SET_REG_FIELD(0x5F0, t->image2, 3, 15, WidthExp2); + SET_REG_FIELD(0x5F1, t->image2, 3, 18, WidthExp2); + t->is32bMipmap = is_32b_mipmap; + t->isCached = 1; +} + +void GXInitTexPreLoadRegion(GXTexRegion *region, u32 tmem_even, u32 size_even, u32 tmem_odd, u32 size_odd) +{ + __GXTexRegionInt *t = (__GXTexRegionInt *)region; + + ASSERTMSGLINE(0x60E, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x610, "GXInitTexPreLoadRegion"); + ASSERTMSGLINEV(0x612, (tmem_even & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "tmem even"); + ASSERTMSGLINEV(0x614, (tmem_odd & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "tmem odd"); + ASSERTMSGLINEV(0x616, (size_even & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "size even"); + ASSERTMSGLINEV(0x618, (size_odd & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "size odd"); + + t->image1 = 0; + SET_REG_FIELD(0x61C, t->image1, 15, 0, tmem_even >> 5); + SET_REG_FIELD(0x61D, t->image1, 3, 15, 0); + SET_REG_FIELD(0x61E, t->image1, 3, 18, 0); + SET_REG_FIELD(0x61F, t->image1, 1, 21, 1); + + t->image2 = 0; + SET_REG_FIELD(0x622, t->image2, 15, 0, tmem_odd >> 5); + SET_REG_FIELD(0x623, t->image2, 3, 15, 0); + SET_REG_FIELD(0x624, t->image2, 3, 18, 0); + t->is32bMipmap = 0; + t->isCached = 0; + t->sizeEven = (u16)(size_even >> 5U); + t->sizeOdd = (u16)(size_odd >> 5U); +} + +void GXGetTexRegionAll(const GXTexRegion *region, u8 *is_cached, u8 *is_32b_mipmap, u32 *tmem_even, u32 *size_even, u32 *tmem_odd, u32 *size_odd) +{ + const __GXTexRegionInt *t = (const __GXTexRegionInt *)region; + + ASSERTMSGLINE(0x641, region, "TexRegion Object Pointer is null"); + *tmem_even = GET_REG_FIELD(t->image1, 15, 0) << 5; + *tmem_odd = GET_REG_FIELD(t->image2, 15, 0) << 5; + if (t->isCached) { + switch (GET_REG_FIELD(t->image1, 3, 15)) { + case 3: + *size_even = 0x8000; + break; + case 4: + *size_even = 0x20000; + break; + case 5: + *size_even = 0x80000; + break; + default: + *size_even = 0; + break; + } + switch (GET_REG_FIELD(t->image2, 3, 15)) { + case 3: + *size_odd = 0x8000; + break; + case 4: + *size_odd = 0x20000; + break; + case 5: + *size_odd = 0x80000; + break; + default: + *size_odd = 0; + break; + } + } + else { + *size_even = t->sizeEven << 5; + *size_odd = t->sizeOdd << 5; + } + *is_32b_mipmap = t->is32bMipmap; + *is_cached = t->isCached; +} + +void GXInitTlutRegion(GXTlutRegion *region, u32 tmem_addr, GXTlutSize tlut_size) +{ + __GXTlutRegionInt *t = (__GXTlutRegionInt *)region; + + ASSERTMSGLINE(0x674, region, "TLutRegion Object Pointer is null"); + CHECK_GXBEGIN(0x676, "GXInitTlutRegion"); + ASSERTMSGLINEV(0x677, (tmem_addr & 0x1FF) == 0, "%s: tmem pointer is not aligned to 512B", "GXInitTlutRegion"); + ASSERTMSGLINEV(0x678, tlut_size <= 0x400, "%s: tlut size exceeds 16K", "GXInitTlutRegion"); + t->loadTlut1 = 0; + tmem_addr -= 0x80000; + SET_REG_FIELD(0x67C, t->loadTlut1, 10, 0, tmem_addr >> 9); + SET_REG_FIELD(0x67D, t->loadTlut1, 11, 10, tlut_size); + SET_REG_FIELD(0x67E, t->loadTlut1, 8, 24, 0x65); +} + +void GXGetTlutRegionAll(const GXTlutRegion *region, u32 *tmem_addr, GXTlutSize *tlut_size) +{ + const __GXTlutRegionInt *t = (const __GXTlutRegionInt *)region; + + ASSERTMSGLINE(0x692, region, "TLutRegion Object Pointer is null"); + *tmem_addr = (GET_REG_FIELD(t->loadTlut1, 10, 0) << 9) + 0x80000; + *tlut_size = GET_REG_FIELD(t->loadTlut1, 11, 10); +} + +void GXInvalidateTexRegion(GXTexRegion *region) +{ + s32 wle; + s32 hle; + s32 wlo; + s32 hlo; + s32 count; + u32 reg0; + u32 reg1; + __GXTexRegionInt *r = (__GXTexRegionInt *)region; + + ASSERTMSGLINE(0x6A9, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x6AB, "GXInvalidateTexRegion"); + + wle = GET_REG_FIELD(r->image1, 3, 15) - 1; + hle = GET_REG_FIELD(r->image1, 3, 18) - 1; + wlo = GET_REG_FIELD(r->image2, 3, 15) - 1; + hlo = GET_REG_FIELD(r->image2, 3, 18) - 1; + if (wle < 0) { + wle = 0; + } + if (hle < 0) { + hle = 0; + } + if (wlo < 0) { + wlo = 0; + } + if (hlo < 0) { + hlo = 0; + } + count = wle + hle; + if (r->is32bMipmap) { + count = wlo + hlo - 2 + count; + } + reg0 = 0; + SET_REG_FIELD(0x6BC, reg0, 9, 0, GET_REG_FIELD(r->image1, 9, 6)); + SET_REG_FIELD(0x6BD, reg0, 4, 9, count); + SET_REG_FIELD(0x6BC, reg0, 8, 24, 0x66); + if (wlo != 0) { + count = wlo + hlo; + if (r->is32bMipmap) { + count = wle + hle - 2 + count; + } + reg1 = 0; + SET_REG_FIELD(0x6C8, reg1, 9, 0, GET_REG_FIELD(r->image2, 9, 6)); + SET_REG_FIELD(0x6C9, reg1, 4, 9, count); + SET_REG_FIELD(0x6CA, reg1, 8, 24, 0x66); + } + __GXFlushTextureState(); + GX_WRITE_RAS_REG(reg0); + if (wlo != 0) { + GX_WRITE_RAS_REG(reg1); + } + __GXFlushTextureState(); + + reg0; + reg1; + r; // needed to match +} + +void GXInvalidateTexAll(void) +{ + u32 reg0; + u32 reg1; + + CHECK_GXBEGIN(0x6DB, "GXInvalidateTexAll"); + reg0 = 0x66001000; + reg1 = 0x66001100; + __GXFlushTextureState(); + GX_WRITE_RAS_REG(reg0); + GX_WRITE_RAS_REG(reg1); + __GXFlushTextureState(); +} + +GXTexRegionCallback GXSetTexRegionCallback(GXTexRegionCallback f) +{ + GXTexRegionCallback oldcb = gx->texRegionCallback; + + gx->texRegionCallback = f; + return oldcb; +} + +GXTlutRegionCallback GXSetTlutRegionCallback(GXTlutRegionCallback f) +{ + GXTlutRegionCallback oldcb = gx->tlutRegionCallback; + + gx->tlutRegionCallback = f; + return oldcb; +} + +void GXPreLoadEntireTexture(GXTexObj *tex_obj, GXTexRegion *region) +{ + u8 isMipMap; + u8 is32bit; + u32 wd; + u32 ht; + u32 maxLevelIndex; + u32 loadImage0; + u32 loadImage1; + u32 loadImage2; + u32 loadImage3; + u32 base; + u32 tmem1; + u32 tmem2; + u32 tmemAR; + u32 tmemGB; + u32 nTiles; + u32 rowTiles; + u32 colTiles; + u32 cmpTiles; + u32 i; + __GXTexObjInt *t = (__GXTexObjInt *)tex_obj; + __GXTexRegionInt *r = (__GXTexRegionInt *)region; + + ASSERTMSGLINE(0x71C, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x71C, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x71E, "GXPreLoadEntireTexture"); + isMipMap = (t->flags & 1) == 1; + is32bit = GET_REG_FIELD(t->image0, 4, 20) == 6; + + loadImage0 = 0; + SET_REG_FIELD(0, loadImage0, 8, 24, 0x60); + base = t->image3 & 0x1FFFFF; + SET_REG_FIELD(0x727, loadImage0, 21, 0, base); + + loadImage1 = 0; + SET_REG_FIELD(0, loadImage1, 8, 24, 0x61); + tmem1 = r->image1 & 0x7FFF; + SET_REG_FIELD(0x72D, loadImage1, 15, 0, tmem1); + + loadImage2 = 0; + SET_REG_FIELD(0, loadImage2, 8, 24, 0x62); + tmem2 = r->image2 & 0x7FFF; + SET_REG_FIELD(0x733, loadImage2, 15, 0, tmem2); + + loadImage3 = 0; + SET_REG_FIELD(0, loadImage3, 8, 24, 0x63); + SET_REG_FIELD(0x738, loadImage3, 15, 0, t->loadCnt); + SET_REG_FIELD(0x739, loadImage3, 2, 15, t->loadFmt); + maxLevelIndex = 0; + nTiles = t->loadCnt; + if (isMipMap != 0) { + wd = GET_REG_FIELD(t->image0, 10, 0) + 1; + ht = GET_REG_FIELD(t->image0, 10, 10) + 1; + if (wd > ht) { + maxLevelIndex = (u16)(31 - __cntlzw(wd)); + } + else { + maxLevelIndex = (u16)(31 - __cntlzw(ht)); + } + } + __GXFlushTextureState(); + GX_WRITE_RAS_REG(loadImage0); + GX_WRITE_RAS_REG(loadImage1); + GX_WRITE_RAS_REG(loadImage2); + GX_WRITE_RAS_REG(loadImage3); + if (maxLevelIndex != 0) { + tmemAR = tmem1; + tmemGB = tmem2; + for (i = 0; i < maxLevelIndex; i++) { + if (is32bit != 0) { + base += nTiles * 2; + tmemAR += nTiles; + tmemGB += nTiles; + } + else { + base += nTiles; + if (i & 1) { + tmemGB += nTiles; + } + else { + tmemAR += nTiles; + } + } + tmem1 = (i & 1) ? tmemAR : tmemGB; + tmem2 = (i & 1) ? tmemGB : tmemAR; + __GetImageTileCount(t->fmt, (u16)(wd >> (i + 1)), (u16)(ht >> (i + 1)), &rowTiles, &colTiles, &cmpTiles); + nTiles = rowTiles * colTiles; + SET_REG_FIELD(0x7A5, loadImage0, 21, 0, base); + SET_REG_FIELD(0x7A6, loadImage1, 15, 0, tmem1); + SET_REG_FIELD(0x7A7, loadImage2, 15, 0, tmem2); + SET_REG_FIELD(0x7A8, loadImage3, 15, 0, nTiles); + GX_WRITE_RAS_REG(loadImage0); + GX_WRITE_RAS_REG(loadImage1); + GX_WRITE_RAS_REG(loadImage2); + GX_WRITE_RAS_REG(loadImage3); + } + } + __GXFlushTextureState(); +} + +void GXSetTexCoordScaleManually(GXTexCoordID coord, u8 enable, u16 ss, u16 ts) +{ + CHECK_GXBEGIN(0x7C5, "GXSetTexCoordScaleManually"); + ASSERTMSGLINEV(0x7C7, coord < 8, "%s: bad texcoord specified", "GXSetTexCoordScaleManually"); + gx->tcsManEnab = (gx->tcsManEnab & ~(1 << coord)) | (enable << coord); + if (enable != 0) { + SET_REG_FIELD(0x7CD, gx->suTs0[coord], 16, 0, (u16)(ss - 1)); + SET_REG_FIELD(0x7CE, gx->suTs1[coord], 16, 0, (u16)(ts - 1)); + GX_WRITE_RAS_REG(gx->suTs0[coord]); + GX_WRITE_RAS_REG(gx->suTs1[coord]); + gx->bpSentNot = 0; + } +} + +void GXSetTexCoordCylWrap(GXTexCoordID coord, u8 s_enable, u8 t_enable) +{ + CHECK_GXBEGIN(0x7E7, "GXSetTexCoordCylWrap"); + ASSERTMSGLINEV(0x7E9, coord < 8, "%s: bad texcoord specified", "GXSetTexCoordCylWrap"); + SET_REG_FIELD(0x7EB, gx->suTs0[coord], 1, 17, s_enable); + SET_REG_FIELD(0x7EC, gx->suTs1[coord], 1, 17, t_enable); + if (gx->tcsManEnab & (1 << coord)) { + GX_WRITE_RAS_REG(gx->suTs0[coord]); + GX_WRITE_RAS_REG(gx->suTs1[coord]); + gx->bpSentNot = 0; + } +} + +void GXSetTexCoordBias(GXTexCoordID coord, u8 s_enable, u8 t_enable) +{ + CHECK_GXBEGIN(0x806, "GXSetTexCoordBias"); + ASSERTMSGLINEV(0x808, coord < 8, "%s: bad texcoord specified", "GXSetTexCoordBias"); + SET_REG_FIELD(0x80A, gx->suTs0[coord], 1, 16, s_enable); + SET_REG_FIELD(0x80B, gx->suTs1[coord], 1, 16, t_enable); + if (gx->tcsManEnab & (1 << coord)) { + GX_WRITE_RAS_REG(gx->suTs0[coord]); + GX_WRITE_RAS_REG(gx->suTs1[coord]); + gx->bpSentNot = 0; + } +} + +static void __SetSURegs(u32 tmap, u32 tcoord) +{ + u32 w; + u32 h; + u8 s_bias; + u8 t_bias; + + w = GET_REG_FIELD(gx->tImage0[tmap], 10, 0); + h = GET_REG_FIELD(gx->tImage0[tmap], 10, 10); + SET_REG_FIELD(0x829, gx->suTs0[tcoord], 16, 0, w); + SET_REG_FIELD(0x82A, gx->suTs1[tcoord], 16, 0, h); + s_bias = GET_REG_FIELD(gx->tMode0[tmap], 2, 0) == 1; + t_bias = GET_REG_FIELD(gx->tMode0[tmap], 2, 2) == 1; + SET_REG_FIELD(0x830, gx->suTs0[tcoord], 1, 16, s_bias); + SET_REG_FIELD(0x831, gx->suTs1[tcoord], 1, 16, t_bias); + GX_WRITE_RAS_REG(gx->suTs0[tcoord]); + GX_WRITE_RAS_REG(gx->suTs1[tcoord]); + gx->bpSentNot = 0; +} + +void __GXSetSUTexRegs(void) +{ + u32 nStages; + u32 nIndStages; + u32 i; + u32 map; + u32 tmap; + u32 coord; + u32 *ptref; + + if (gx->tcsManEnab != 0xFF) { + nStages = GET_REG_FIELD(gx->genMode, 4, 10) + 1; + nIndStages = GET_REG_FIELD(gx->genMode, 3, 16); + for (i = 0; i < nIndStages; i++) { + switch (i) { + case 0: + tmap = GET_REG_FIELD(gx->iref, 3, 0); + coord = GET_REG_FIELD(gx->iref, 3, 3); + break; + case 1: + tmap = GET_REG_FIELD(gx->iref, 3, 6); + coord = GET_REG_FIELD(gx->iref, 3, 9); + break; + case 2: + tmap = GET_REG_FIELD(gx->iref, 3, 12); + coord = GET_REG_FIELD(gx->iref, 3, 15); + break; + case 3: + tmap = GET_REG_FIELD(gx->iref, 3, 18); + coord = GET_REG_FIELD(gx->iref, 3, 21); + break; + } + if (!(gx->tcsManEnab & (1 << coord))) { + __SetSURegs(tmap, coord); + } + } + i = 0; + for (i = 0; i < nStages; i++) { + ptref = &gx->tref[i / 2]; + map = gx->texmapId[i]; + tmap = map & 0xFFFFFEFF; + if (i & 1) { + coord = GET_REG_FIELD(*ptref, 3, 15); + } + else { + coord = GET_REG_FIELD(*ptref, 3, 3); + } + if ((tmap != 0xFF) && !(gx->tcsManEnab & (1 << coord)) && (gx->tevTcEnab & (1 << i))) { + __SetSURegs(tmap, coord); + } + } + } +} + +void __GXGetSUTexSize(GXTexCoordID coord, u16 *width, u16 *height) +{ + *width = (u16)gx->suTs0[coord] + 1; + *height = (u16)gx->suTs1[coord] + 1; +} + +void __GXSetTmemConfig(u32 config) +{ + switch (config) { + case 1: + GX_WRITE_RAS_REG(0x8c0d8000); + GX_WRITE_RAS_REG(0x900dc000); + + GX_WRITE_RAS_REG(0x8d0d8800); + GX_WRITE_RAS_REG(0x910dc800); + + GX_WRITE_RAS_REG(0x8e0d9000); + GX_WRITE_RAS_REG(0x920dd000); + + GX_WRITE_RAS_REG(0x8f0d9800); + GX_WRITE_RAS_REG(0x930dd800); + + GX_WRITE_RAS_REG(0xac0da000); + GX_WRITE_RAS_REG(0xb00de000); + + GX_WRITE_RAS_REG(0xad0da800); + GX_WRITE_RAS_REG(0xb10de800); + + GX_WRITE_RAS_REG(0xae0db000); + GX_WRITE_RAS_REG(0xb20df000); + + GX_WRITE_RAS_REG(0xaf0db800); + GX_WRITE_RAS_REG(0xb30df800); + + break; + case 0: + default: + GX_WRITE_RAS_REG(0x8c0d8000); + GX_WRITE_RAS_REG(0x900dc000); + + GX_WRITE_RAS_REG(0x8d0d8400); + GX_WRITE_RAS_REG(0x910dc400); + + GX_WRITE_RAS_REG(0x8e0d8800); + GX_WRITE_RAS_REG(0x920dc800); + + GX_WRITE_RAS_REG(0x8f0d8c00); + GX_WRITE_RAS_REG(0x930dcc00); + + GX_WRITE_RAS_REG(0xac0d9000); + GX_WRITE_RAS_REG(0xb00dd000); + + GX_WRITE_RAS_REG(0xad0d9400); + GX_WRITE_RAS_REG(0xb10dd400); + + GX_WRITE_RAS_REG(0xae0d9800); + GX_WRITE_RAS_REG(0xb20dd800); + + GX_WRITE_RAS_REG(0xaf0d9c00); + GX_WRITE_RAS_REG(0xb30ddc00); + + break; + } +} diff --git a/src/dolphin/gx/GXTransform.c b/src/dolphin/gx/GXTransform.c new file mode 100644 index 00000000..dbe9d5d1 --- /dev/null +++ b/src/dolphin/gx/GXTransform.c @@ -0,0 +1,372 @@ +#include +#include +#include + +#include + +void GXProject(f32 x, f32 y, f32 z, const f32 mtx[3][4], const f32 *pm, const f32 *vp, f32 *sx, f32 *sy, f32 *sz) +{ + Vec peye; + f32 xc; + f32 yc; + f32 zc; + f32 wc; + + ASSERTMSGLINE(0xA8, pm && vp && sx && sy && sz, "GXGet*: invalid null pointer"); + + peye.x = mtx[0][3] + ((mtx[0][2] * z) + ((mtx[0][0] * x) + (mtx[0][1] * y))); + peye.y = mtx[1][3] + ((mtx[1][2] * z) + ((mtx[1][0] * x) + (mtx[1][1] * y))); + peye.z = mtx[2][3] + ((mtx[2][2] * z) + ((mtx[2][0] * x) + (mtx[2][1] * y))); + if (pm[0] == 0.0f) { + xc = (peye.x * pm[1]) + (peye.z * pm[2]); + yc = (peye.y * pm[3]) + (peye.z * pm[4]); + zc = pm[6] + (peye.z * pm[5]); + wc = 1.0f / -peye.z; + } + else { + xc = pm[2] + (peye.x * pm[1]); + yc = pm[4] + (peye.y * pm[3]); + zc = pm[6] + (peye.z * pm[5]); + wc = 1.0f; + } + *sx = (vp[2] / 2.0f) + (vp[0] + (wc * (xc * vp[2] / 2.0f))); + *sy = (vp[3] / 2.0f) + (vp[1] + (wc * (-yc * vp[3] / 2.0f))); + *sz = vp[5] + (wc * (zc * (vp[5] - vp[4]))); +} + +static void WriteProjPS(const register f32 proj[6], register volatile void *dest) +{ + register f32 p01, p23, p45; + + asm { + psq_l p01, 0(proj), 0, 0 + psq_l p23, 8(proj), 0, 0 + psq_l p45, 16(proj), 0, 0 + psq_st p01, 0(dest), 0, 0 + psq_st p23, 0(dest), 0, 0 + psq_st p45, 0(dest), 0, 0 + } +} + +static void __GXSetProjection(void) +{ + u32 reg = 0x00061020; + GX_WRITE_U8(0x10); + GX_WRITE_U32(reg); + GX_WRITE_XF_REG_F(32, gx->projMtx[0]); + GX_WRITE_XF_REG_F(33, gx->projMtx[1]); + GX_WRITE_XF_REG_F(34, gx->projMtx[2]); + GX_WRITE_XF_REG_F(35, gx->projMtx[3]); + GX_WRITE_XF_REG_F(36, gx->projMtx[4]); + GX_WRITE_XF_REG_F(37, gx->projMtx[5]); + GX_WRITE_XF_REG_2(38, gx->projType); +} + +void GXSetProjection(f32 mtx[4][4], GXProjectionType type) +{ + CHECK_GXBEGIN(0x127, "GXSetProjection"); + + gx->projType = type; + gx->projMtx[0] = mtx[0][0]; + gx->projMtx[2] = mtx[1][1]; + gx->projMtx[4] = mtx[2][2]; + gx->projMtx[5] = mtx[2][3]; + if (type == GX_ORTHOGRAPHIC) { + gx->projMtx[1] = mtx[0][3]; + gx->projMtx[3] = mtx[1][3]; + } + else { + gx->projMtx[1] = mtx[0][2]; + gx->projMtx[3] = mtx[1][2]; + } + + __GXSetProjection(); + gx->bpSentNot = 1; +} + +#define qr0 0 + +void GXGetProjectionv(f32 *ptr) +{ + ASSERTMSGLINE(0x172, ptr, "GXGet*: invalid null pointer"); + + ptr[0] = gx->projType; + + ptr[1] = gx->projMtx[0]; + ptr[2] = gx->projMtx[1]; + ptr[3] = gx->projMtx[2]; + ptr[4] = gx->projMtx[3]; + ptr[5] = gx->projMtx[4]; + ptr[6] = gx->projMtx[5]; +} + +static void WriteMTXPS4x3(const register f32 mtx[3][4], register volatile f32 *dest) +{ + register f32 a00_a01; + register f32 a02_a03; + register f32 a10_a11; + register f32 a12_a13; + register f32 a20_a21; + register f32 a22_a23; + + asm { + psq_l a00_a01, 0x00(mtx), 0, qr0 + psq_l a02_a03, 0x08(mtx), 0, qr0 + psq_l a10_a11, 0x10(mtx), 0, qr0 + psq_l a12_a13, 0x18(mtx), 0, qr0 + psq_l a20_a21, 0x20(mtx), 0, qr0 + psq_l a22_a23, 0x28(mtx), 0, qr0 + psq_st a00_a01, 0(dest), 0, qr0 + psq_st a02_a03, 0(dest), 0, qr0 + psq_st a10_a11, 0(dest), 0, qr0 + psq_st a12_a13, 0(dest), 0, qr0 + psq_st a20_a21, 0(dest), 0, qr0 + psq_st a22_a23, 0(dest), 0, qr0 + } +} + +static void WriteMTXPS3x3from3x4(register f32 mtx[3][4], register volatile f32 *dest) +{ + register f32 a00_a01; + register f32 a02_a03; + register f32 a10_a11; + register f32 a12_a13; + register f32 a20_a21; + register f32 a22_a23; + + asm { + psq_l a00_a01, 0x00(mtx), 0, qr0 + lfs a02_a03, 0x08(mtx) + psq_l a10_a11, 0x10(mtx), 0, qr0 + lfs a12_a13, 0x18(mtx) + psq_l a20_a21, 0x20(mtx), 0, qr0 + lfs a22_a23, 0x28(mtx) + psq_st a00_a01, 0(dest), 0, qr0 + stfs a02_a03, 0(dest) + psq_st a10_a11, 0(dest), 0, qr0 + stfs a12_a13, 0(dest) + psq_st a20_a21, 0(dest), 0, qr0 + stfs a22_a23, 0(dest) + } +} + +static void WriteMTXPS4x2(const register f32 mtx[2][4], register volatile f32 *dest) +{ + register f32 a00_a01; + register f32 a02_a03; + register f32 a10_a11; + register f32 a12_a13; + + asm { + psq_l a00_a01, 0x00(mtx), 0, qr0 + psq_l a02_a03, 0x08(mtx), 0, qr0 + psq_l a10_a11, 0x10(mtx), 0, qr0 + psq_l a12_a13, 0x18(mtx), 0, qr0 + psq_st a00_a01, 0(dest), 0, qr0 + psq_st a02_a03, 0(dest), 0, qr0 + psq_st a10_a11, 0(dest), 0, qr0 + psq_st a12_a13, 0(dest), 0, qr0 + } +} + +#pragma peephole off +#pragma dont_inline on +void GXLoadPosMtxImm(f32 mtx[3][4], u32 id) +{ + u32 reg; + u32 addr; + + CHECK_GXBEGIN(0x1FB, "GXLoadPosMtxImm"); + + addr = id * 4; + reg = addr | 0xB0000; + + GX_WRITE_U8(0x10); + GX_WRITE_U32(reg); + WriteMTXPS4x3(mtx, &GXWGFifo.f32); +} + +void GXLoadNrmMtxImm(f32 mtx[3][4], u32 id) +{ + u32 reg; + u32 addr; + + CHECK_GXBEGIN(0x24C, "GXLoadNrmMtxImm"); + + addr = id * 3 + 0x400; + reg = addr | 0x80000; + + GX_WRITE_U8(0x10); + GX_WRITE_U32(reg); + WriteMTXPS3x3from3x4((void *)mtx, &GXWGFifo.f32); +} + +void GXSetCurrentMtx(u32 id) +{ + CHECK_GXBEGIN(0x2C4, "GXSetCurrentMtx"); + SET_REG_FIELD(0x2C8, gx->matIdxA, 6, 0, id); + __GXSetMatrixIndex(GX_VA_PNMTXIDX); +} + +void GXLoadTexMtxImm(f32 mtx[][4], u32 id, GXTexMtxType type) +{ + u32 reg; + u32 addr; + u32 count; + + CHECK_GXBEGIN(0x2E5, "GXLoadTexMtxImm"); + + if (id >= GX_PTTEXMTX0) { + addr = (id - GX_PTTEXMTX0) * 4 + 0x500; + ASSERTMSGLINE(0x2EF, type == GX_MTX3x4, "GXLoadTexMtx: Invalid matrix type"); + } + else { + addr = id * 4; + } + count = (type == GX_MTX2x4) ? 8 : 12; + reg = addr | ((count - 1) << 16); + + GX_WRITE_U8(0x10); + GX_WRITE_U32(reg); + if (type == GX_MTX3x4) { + WriteMTXPS4x3(mtx, &GXWGFifo.f32); + } + else { + WriteMTXPS4x2(mtx, &GXWGFifo.f32); + } +} +#pragma dont_inline reset + +void GXSetViewportJitter(f32 left, f32 top, f32 wd, f32 ht, f32 nearz, f32 farz, u32 field) +{ + f32 sx; + f32 sy; + f32 sz; + f32 ox; + f32 oy; + f32 oz; + f32 zmin; + f32 zmax; + u32 reg; + + CHECK_GXBEGIN(0x387, "GXSetViewport"); // not the correct function name + + if (field == 0) { + top -= 0.5f; + } + sx = wd / 2.0f; + sy = -ht / 2.0f; + ox = 342.0f + (left + (wd / 2.0f)); + oy = 342.0f + (top + (ht / 2.0f)); + zmin = 1.6777215e7f * nearz; + zmax = 1.6777215e7f * farz; + sz = zmax - zmin; + oz = zmax; + gx->vpLeft = left; + gx->vpTop = top; + gx->vpWd = wd; + gx->vpHt = ht; + gx->vpNearz = nearz; + gx->vpFarz = farz; + if (gx->fgRange != 0) { + __GXSetRange(nearz, gx->fgSideX); + } + reg = 0x5101A; + GX_WRITE_U8(0x10); + GX_WRITE_U32(reg); + GX_WRITE_XF_REG_F(26, sx); + GX_WRITE_XF_REG_F(27, sy); + GX_WRITE_XF_REG_F(28, sz); + GX_WRITE_XF_REG_F(29, ox); + GX_WRITE_XF_REG_F(30, oy); + GX_WRITE_XF_REG_F(31, oz); + gx->bpSentNot = 1; +} + +void GXSetViewport(f32 left, f32 top, f32 wd, f32 ht, f32 nearz, f32 farz) +{ + GXSetViewportJitter(left, top, wd, ht, nearz, farz, 1U); +} + +void GXGetViewportv(f32 *vp) +{ + ASSERTMSGLINE(0x3C8, vp, "GXGet*: invalid null pointer"); + + vp[0] = gx->vpLeft; + vp[1] = gx->vpTop; + vp[2] = gx->vpWd; + vp[3] = gx->vpHt; + vp[4] = gx->vpNearz; + vp[5] = gx->vpFarz; +} + +// maybe get it from melee? +void GXSetScissor(u32 left, u32 top, u32 wd, u32 ht) +{ + u32 tp; + u32 lf; + u32 bm; + u32 rt; + + CHECK_GXBEGIN(0x418, "GXSetScissor"); + ASSERTMSGLINE(0x419, left < 1706, "GXSetScissor: Left origin > 1708"); + ASSERTMSGLINE(0x41A, top < 1706, "GXSetScissor: top origin > 1708"); + ASSERTMSGLINE(0x41B, left + wd < 1706, "GXSetScissor: right edge > 1708"); + ASSERTMSGLINE(0x41C, top + ht < 1706, "GXSetScissor: bottom edge > 1708"); + + tp = top + 342; + lf = left + 342; + bm = tp + ht - 1; + rt = lf + wd - 1; + + SET_REG_FIELD(0x423, gx->suScis0, 11, 0, tp); + SET_REG_FIELD(0x424, gx->suScis0, 11, 12, lf); + SET_REG_FIELD(0x426, gx->suScis1, 11, 0, bm); + SET_REG_FIELD(0x427, gx->suScis1, 11, 12, rt); + + GX_WRITE_RAS_REG(gx->suScis0); + GX_WRITE_RAS_REG(gx->suScis1); + gx->bpSentNot = 0; +} + +void GXSetScissorBoxOffset(s32 x_off, s32 y_off) +{ + u32 reg = 0; + u32 hx; + u32 hy; + + CHECK_GXBEGIN(0x45F, "GXSetScissorBoxOffset"); + + ASSERTMSGLINE(0x462, (u32)(x_off + 342) < 2048, "GXSetScissorBoxOffset: Invalid X offset"); + ASSERTMSGLINE(0x464, (u32)(y_off + 342) < 2048, "GXSetScissorBoxOffset: Invalid Y offset"); + + hx = (u32)(x_off + 342) >> 1; + hy = (u32)(y_off + 342) >> 1; + + SET_REG_FIELD(0x469, reg, 10, 0, hx); + SET_REG_FIELD(0x46A, reg, 10, 10, hy); + SET_REG_FIELD(0x46B, reg, 8, 24, 0x59); + GX_WRITE_RAS_REG(reg); + gx->bpSentNot = 0; +} +#pragma peephole on + +void GXSetClipMode(GXClipMode mode) +{ + CHECK_GXBEGIN(0x47F, "GXSetClipMode"); + GX_WRITE_XF_REG(5, mode); + gx->bpSentNot = 1; +} + +void __GXSetMatrixIndex(GXAttr matIdxAttr) +{ + if (matIdxAttr < GX_VA_TEX4MTXIDX) { + GX_WRITE_SOME_REG4(8, 0x30, gx->matIdxA, -12); + GX_WRITE_XF_REG(24, gx->matIdxA); + } + else { + GX_WRITE_SOME_REG4(8, 0x40, gx->matIdxB, -12); + GX_WRITE_XF_REG(25, gx->matIdxB); + } + gx->bpSentNot = 1; +} diff --git a/src/game/kerent.c b/src/game/kerent.c index e872e2ad..f97ccdce 100644 --- a/src/game/kerent.c +++ b/src/game/kerent.c @@ -27,7 +27,7 @@ void PSQUATNormalize(void); void OSTicksToCalendarTime(void); void GXWaitDrawDone(void); void GXProject(void); -void GXSetProjectionv(void); +void GXGetProjectionv(void); void GXGetViewportv(void); void GXPixModeSync(void); void GXSetIndTexOrder(void); @@ -1044,7 +1044,7 @@ extern void _kerjmp_PSQUATNormalize(void); extern void _kerjmp_OSTicksToCalendarTime(void); extern void _kerjmp_GXWaitDrawDone(void); extern void _kerjmp_GXProject(void); -extern void _kerjmp_GXSetProjectionv(void); +extern void _kerjmp_GXGetProjectionv(void); extern void _kerjmp_GXGetViewportv(void); extern void _kerjmp_GXPixModeSync(void); extern void _kerjmp_GXSetIndTexOrder(void); @@ -2093,8 +2093,8 @@ asm void _kerent(void) { b GXWaitDrawDone entry _kerjmp_GXProject b GXProject - entry _kerjmp_GXSetProjectionv - b GXSetProjectionv + entry _kerjmp_GXGetProjectionv + b GXGetProjectionv entry _kerjmp_GXGetViewportv b GXGetViewportv entry _kerjmp_GXPixModeSync