diff --git a/config/overlays.mk b/config/overlays.mk index 3245c65d9..4dbfef8af 100644 --- a/config/overlays.mk +++ b/config/overlays.mk @@ -4759,7 +4759,7 @@ ov_SC07_007_ELF := $(ov_SC07_007_OUT).elf ov_SC07_007_MAPFILE := $(ov_SC07_007_OUT).map ov_SC07_007_LD_SCRIPT := $(ov_SC07_007_OUT).ld ov_SC07_007_SPLAT_YAML := config/splat.ov_SC07_007.yaml -ov_SC07_007_JTBL_INTERLEAVE := --order tail.data.o,ov_SC07_007.o,tail2.data.o,ov_SC07_007_jr_80131340.o,tail3.data.o,ov_SC07_007_jr_80135888.o,tail4.data.o,ov_SC07_007_jr_80135A4C.o,tail5.data.o,ov_SC07_007_jr_80135D20.o,tail6.data.o,ov_SC07_007_o0c.o,tail7.data.o,ov_SC07_007_jr_8013F350.o,tail8.data.o,ov_SC07_007_jr_8014032C.o,tail9.data.o,ov_SC07_007_jr_80140608.o,tail10.data.o,ov_SC07_007_jr_8015444C.o,ov_SC07_007_jr_80154C24.o,ov_SC07_007_jr_801588CC.o,ov_SC07_007_jr_80159C84.o,tail11.data.o,ov_SC07_007_jr_8015A3C8.o,tail12.data.o,ov_SC07_007_jr_8015B950.o,tail13.data.o,ov_SC07_007_jr_8015C32C.o,tail14.data.o,ov_SC07_007_jr_8016AE5C.o,tail15.data.o,ov_SC07_007_jr_80171B4C.o,tail16.data.o,ov_SC07_007_jr_801789AC.o,tail17.data.o,ov_SC07_007_jr_80179B74.o,tail18.data.o,ov_SC07_007_jr_8017AE2C.o,ov_SC07_007_jr_8017BEBC.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve +ov_SC07_007_JTBL_INTERLEAVE := --order tail.data.o,ov_SC07_007.o,tail2.data.o,ov_SC07_007_jr_80131340.o,tail3.data.o,ov_SC07_007_jr_80135888.o,tail4.data.o,ov_SC07_007_jr_80135A4C.o,tail5.data.o,ov_SC07_007_jr_80135D20.o,tail6.data.o,ov_SC07_007_o0c.o,tail7.data.o,ov_SC07_007_jr_8013F350.o,tail8.data.o,ov_SC07_007_jr_8014032C.o,tail9.data.o,ov_SC07_007_jr_80140608.o,tail10.data.o,ov_SC07_007_jr_8015444C.o,ov_SC07_007_jr_80154C24.o,ov_SC07_007_jr_801588CC.o,ov_SC07_007_jr_80159C84.o,tail11.data.o,ov_SC07_007_jr_8015A3C8.o,tail12.data.o,ov_SC07_007_jr_8015B950.o,tail13.data.o,ov_SC07_007_jr_8015C32C.o,tail14.data.o,ov_SC07_007_jr_8016AE5C.o,tail15.data.o,ov_SC07_007_jr_80171B4C.o,tail16.data.o,ov_SC07_007_jr_801789AC.o,ov_SC07_007_jr_80179B74.o,tail17.data.o,ov_SC07_007_jr_8017AE2C.o,ov_SC07_007_jr_8017BEBC.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_SC07_007/ov_SC07_007.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC07_007/ov_SC07_007_jr_80131340.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC07_007/ov_SC07_007_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 @@ -4770,6 +4770,7 @@ build/src/ov_SC07_007/ov_SC07_007_jr_80154C24.o: JTBL_PADS := 0,0 # §8e pads ( build/src/ov_SC07_007/ov_SC07_007_jr_801588CC.o: JTBL_PADS := 0,4,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x28,+0x48 build/src/ov_SC07_007/ov_SC07_007_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC07_007/ov_SC07_007_jr_8015A3C8.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 +build/src/ov_SC07_007/ov_SC07_007_jr_801789AC.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 build/src/ov_SC07_007/ov_SC07_007_jr_80179B74.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x90 build/src/ov_SC07_007/ov_SC07_007_o0c.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x38,+0xa8,+0x118 ov_SC07_007_CHECK_SHA := config/check.ov_SC07_007.sha @@ -4793,7 +4794,7 @@ ov_SC07_010_ELF := $(ov_SC07_010_OUT).elf ov_SC07_010_MAPFILE := $(ov_SC07_010_OUT).map ov_SC07_010_LD_SCRIPT := $(ov_SC07_010_OUT).ld ov_SC07_010_SPLAT_YAML := config/splat.ov_SC07_010.yaml -ov_SC07_010_JTBL_INTERLEAVE := --order tail.data.o,ov_SC07_010.o,tail2.data.o,ov_SC07_010_jr_80131340.o,tail3.data.o,ov_SC07_010_jr_80135888.o,tail4.data.o,ov_SC07_010_jr_80135A4C.o,tail5.data.o,ov_SC07_010_jr_80135D20.o,tail6.data.o,ov_SC07_010_o0.o,tail7.data.o,ov_SC07_010_jr_8013F350.o,tail8.data.o,ov_SC07_010_jr_8014032C.o,tail9.data.o,ov_SC07_010_jr_80140608.o,tail10.data.o,ov_SC07_010_jr_8015444C.o,ov_SC07_010_jr_80154C24.o,ov_SC07_010_jr_801588CC.o,ov_SC07_010_jr_80159C84.o,tail11.data.o,ov_SC07_010_jr_8015A3C8.o,tail12.data.o,ov_SC07_010_jr_8015B950.o,tail13.data.o,ov_SC07_010_jr_8015C32C.o,tail14.data.o,ov_SC07_010_jr_8016AE5C.o,tail15.data.o,ov_SC07_010_jr_80171B4C.o,tail16.data.o,ov_SC07_010_jr_801789AC.o,tail17.data.o,ov_SC07_010_jr_80179B74.o,tail18.data.o,ov_SC07_010_jr_8017AE2C.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve +ov_SC07_010_JTBL_INTERLEAVE := --order tail.data.o,ov_SC07_010.o,tail2.data.o,ov_SC07_010_jr_80131340.o,tail3.data.o,ov_SC07_010_jr_80135888.o,tail4.data.o,ov_SC07_010_jr_80135A4C.o,tail5.data.o,ov_SC07_010_jr_80135D20.o,tail6.data.o,ov_SC07_010_o0.o,tail7.data.o,ov_SC07_010_jr_8013F350.o,tail8.data.o,ov_SC07_010_jr_8014032C.o,tail9.data.o,ov_SC07_010_jr_80140608.o,tail10.data.o,ov_SC07_010_jr_8015444C.o,ov_SC07_010_jr_80154C24.o,ov_SC07_010_jr_801588CC.o,ov_SC07_010_jr_80159C84.o,tail11.data.o,ov_SC07_010_jr_8015A3C8.o,tail12.data.o,ov_SC07_010_jr_8015B950.o,tail13.data.o,ov_SC07_010_jr_8015C32C.o,tail14.data.o,ov_SC07_010_jr_8016AE5C.o,tail15.data.o,ov_SC07_010_jr_80171B4C.o,tail16.data.o,ov_SC07_010_jr_801789AC.o,ov_SC07_010_jr_80179B74.o,tail17.data.o,ov_SC07_010_jr_8017AE2C.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_SC07_010/ov_SC07_010.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC07_010/ov_SC07_010_jr_80131340.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC07_010/ov_SC07_010_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 @@ -4803,6 +4804,7 @@ build/src/ov_SC07_010/ov_SC07_010_jr_80154C24.o: JTBL_PADS := 0,0 # §8e pads ( build/src/ov_SC07_010/ov_SC07_010_jr_801588CC.o: JTBL_PADS := 0,4,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x28,+0x48 build/src/ov_SC07_010/ov_SC07_010_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC07_010/ov_SC07_010_jr_8015A3C8.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 +build/src/ov_SC07_010/ov_SC07_010_jr_801789AC.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 build/src/ov_SC07_010/ov_SC07_010_jr_80179B74.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x90 build/src/ov_SC07_010/ov_SC07_010_o0.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x38,+0xa8,+0x118 ov_SC07_010_CHECK_SHA := config/check.ov_SC07_010.sha @@ -4826,7 +4828,7 @@ ov_SC07_011_ELF := $(ov_SC07_011_OUT).elf ov_SC07_011_MAPFILE := $(ov_SC07_011_OUT).map ov_SC07_011_LD_SCRIPT := $(ov_SC07_011_OUT).ld ov_SC07_011_SPLAT_YAML := config/splat.ov_SC07_011.yaml -ov_SC07_011_JTBL_INTERLEAVE := --order tail.data.o,ov_SC07_011.o,tail2.data.o,ov_SC07_011_jr_80131340.o,tail3.data.o,ov_SC07_011_jr_80135888.o,tail4.data.o,ov_SC07_011_jr_80135A4C.o,tail5.data.o,ov_SC07_011_jr_80135D20.o,tail6.data.o,ov_SC07_011_o0c.o,tail7.data.o,ov_SC07_011_jr_8013F350.o,tail8.data.o,ov_SC07_011_jr_8014032C.o,tail9.data.o,ov_SC07_011_jr_80140608.o,tail10.data.o,ov_SC07_011_jr_8015444C.o,ov_SC07_011_jr_80154C24.o,ov_SC07_011_jr_801588CC.o,ov_SC07_011_jr_80159C84.o,tail11.data.o,ov_SC07_011_jr_8015A3C8.o,tail12.data.o,ov_SC07_011_jr_8015B950.o,tail13.data.o,ov_SC07_011_jr_8015C32C.o,tail14.data.o,ov_SC07_011_jr_8016AE5C.o,tail15.data.o,ov_SC07_011_jr_80171B4C.o,tail16.data.o,ov_SC07_011_jr_801789AC.o,tail17.data.o,ov_SC07_011_jr_80179B74.o,tail18.data.o,ov_SC07_011_jr_8017AE2C.o,ov_SC07_011_jr_8017BEBC.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve +ov_SC07_011_JTBL_INTERLEAVE := --order tail.data.o,ov_SC07_011.o,tail2.data.o,ov_SC07_011_jr_80131340.o,tail3.data.o,ov_SC07_011_jr_80135888.o,tail4.data.o,ov_SC07_011_jr_80135A4C.o,tail5.data.o,ov_SC07_011_jr_80135D20.o,tail6.data.o,ov_SC07_011_o0c.o,tail7.data.o,ov_SC07_011_jr_8013F350.o,tail8.data.o,ov_SC07_011_jr_8014032C.o,tail9.data.o,ov_SC07_011_jr_80140608.o,tail10.data.o,ov_SC07_011_jr_8015444C.o,ov_SC07_011_jr_80154C24.o,ov_SC07_011_jr_801588CC.o,ov_SC07_011_jr_80159C84.o,tail11.data.o,ov_SC07_011_jr_8015A3C8.o,tail12.data.o,ov_SC07_011_jr_8015B950.o,tail13.data.o,ov_SC07_011_jr_8015C32C.o,tail14.data.o,ov_SC07_011_jr_8016AE5C.o,tail15.data.o,ov_SC07_011_jr_80171B4C.o,tail16.data.o,ov_SC07_011_jr_801789AC.o,ov_SC07_011_jr_80179B74.o,tail17.data.o,ov_SC07_011_jr_8017AE2C.o,ov_SC07_011_jr_8017BEBC.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_SC07_011/ov_SC07_011.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC07_011/ov_SC07_011_jr_80131340.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC07_011/ov_SC07_011_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 @@ -4837,6 +4839,7 @@ build/src/ov_SC07_011/ov_SC07_011_jr_80154C24.o: JTBL_PADS := 0,0 # §8e pads ( build/src/ov_SC07_011/ov_SC07_011_jr_801588CC.o: JTBL_PADS := 0,4,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x28,+0x48 build/src/ov_SC07_011/ov_SC07_011_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC07_011/ov_SC07_011_jr_8015A3C8.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 +build/src/ov_SC07_011/ov_SC07_011_jr_801789AC.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 build/src/ov_SC07_011/ov_SC07_011_jr_80179B74.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x90 build/src/ov_SC07_011/ov_SC07_011_o0c.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x38,+0xa8,+0x118 ov_SC07_011_CHECK_SHA := config/check.ov_SC07_011.sha diff --git a/config/splat.ov_SC07_007.yaml b/config/splat.ov_SC07_007.yaml index 428d198ce..fbfadd76b 100644 --- a/config/splat.ov_SC07_007.yaml +++ b/config/splat.ov_SC07_007.yaml @@ -151,12 +151,11 @@ segments: - [0x9dea8, .rodata, ov_SC07_007_jr_80171B4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x9dec8, data, tail16] - [0x9e06c, .rodata, ov_SC07_007_jr_801789AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x9e084, data, tail17] - [0x9e1fc, .rodata, ov_SC07_007_jr_80179B74] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x9e318, data, tail18] + - [0x9e318, data, tail17] - [0x9e31c, .rodata, ov_SC07_007_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x9e330, .rodata, ov_SC07_007_jr_8017BEBC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x9e350, data, tail19] + - [0x9e350, data, tail18] - [0x9F9DC, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word) - [0x9F9DF] # EOF marker = the 0.4.dec byte length # @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes diff --git a/config/splat.ov_SC07_010.yaml b/config/splat.ov_SC07_010.yaml index 664071155..574bb7e63 100644 --- a/config/splat.ov_SC07_010.yaml +++ b/config/splat.ov_SC07_010.yaml @@ -150,11 +150,10 @@ segments: - [0x7e388, .rodata, ov_SC07_010_jr_80171B4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x7e3a8, data, tail16] - [0x7e54c, .rodata, ov_SC07_010_jr_801789AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x7e564, data, tail17] - [0x7e6dc, .rodata, ov_SC07_010_jr_80179B74] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x7e7f8, data, tail18] + - [0x7e7f8, data, tail17] - [0x7e7fc, .rodata, ov_SC07_010_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x7e810, data, tail19] + - [0x7e810, data, tail18] - [0x813EC, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word) - [0x813EF] # EOF marker = the 0.4.dec byte length # @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes diff --git a/config/splat.ov_SC07_011.yaml b/config/splat.ov_SC07_011.yaml index 372187537..ea00373a9 100644 --- a/config/splat.ov_SC07_011.yaml +++ b/config/splat.ov_SC07_011.yaml @@ -151,12 +151,11 @@ segments: - [0x66a50, .rodata, ov_SC07_011_jr_80171B4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x66a70, data, tail16] - [0x66c14, .rodata, ov_SC07_011_jr_801789AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x66c2c, data, tail17] - [0x66da4, .rodata, ov_SC07_011_jr_80179B74] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x66ec0, data, tail18] + - [0x66ec0, data, tail17] - [0x66ec4, .rodata, ov_SC07_011_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x66ed8, .rodata, ov_SC07_011_jr_8017BEBC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x66ef8, data, tail19] + - [0x66ef8, data, tail18] - [0x683A4, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word) - [0x683A7] # EOF marker = the 0.4.dec byte length # @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes diff --git a/src/ov_SC07_007/ov_SC07_007_jr_801789AC.c b/src/ov_SC07_007/ov_SC07_007_jr_801789AC.c index de06c42cf..42e595fb0 100644 --- a/src/ov_SC07_007/ov_SC07_007_jr_801789AC.c +++ b/src/ov_SC07_007/ov_SC07_007_jr_801789AC.c @@ -3442,7 +3442,746 @@ void func_80178D18(void) { } -INCLUDE_ASM("asm/ov_SC07_007/nonmatchings/ov_SC07_007_jr_801789AC", func_80178D40); +extern void func_8002D4C8(s32 a0, s32 a1); +extern void func_8012E8E0(s32 a0, s32 a1); +extern void func_80175414(s32); +extern void func_80175454(void); + +/* func_80178D40 - 890 ins, 94-case jr switch (jtbl_801D8E24). + * STATUS: **MATCH** -- 890/890 ins, byte-exact (masked). PIN-FREE (this body is + * templated across 134 overlays; a pinned body would crash the sibling TUs). + * python3 tools/match_one.py func_80178D40 --c .run/phase26-cracks/func_80178D40.c \ + * --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC + * => MATCH (890 ins) + * Jump table VERIFIED: 94 entries (= the sltiu 0x5E bound, no trailing zero pad), + * 93 unique blocks, cases 0xF/0x3F share one block; my case->block sequence is + * identical to jtbl_801D8E24's. + * + * Byte-derived structure (the levers that cracked it): + * 1. NO status variable. Every case stores `(*(s16*)&D_801C7B34) = K` DIRECTLY. The shared + * `sh $v0, (*(s16*)&D_801C7B34)` at .L80179AEC is a jump2 CROSS-JUMP merge of those stores: + * find_cross_jump's FIRST call (minimum=1, vs the code before the target label) + * matches that 1 insn, and because it succeeds the jump_chain loop (minimum=2) is + * SKIPPED -- which is what BLOCKS the deeper, wrong 3-insn merges of the identical + * func_80137614 tails (cases 0/0x45/0x32). reorg then steals the `li K` back into + * each `j` delay slot, so it looks un-merged. A `status` pseudo instead of direct + * stores loses that block and costs 6 insns. + * 2. after-switch = `D_801C7348 += 8;` (.L80179AF4) -> the out-of-range default lands + * there with NO explicit `default:` label. + * 3. arg0/arg1/pv are STRUCT pointers. gcc-2.7.2 sched alias (sched.c true_dependence) + * only lets a MEM_IN_STRUCT varying-address load hoist above a non-MEM_IN_STRUCT + * fixed-address store (the (*(s16*)&D_801C7B34) store). Raw `*(T *)(int + off)` casts get + * MEM_IN_STRUCT_P = 0 and block that hoist -> stray nops. + * 4. g = &D_801C7A90 stays a plain `s16 *` (NOT a struct ptr) so its varying, + * non-in-struct stores keep their order w.r.t. the loads. + * 5. Statement order inside the D_801C7A90 cases is load-bearing (sched LUID/priority): + * g[0],g[2],g[1] in 0x25/0x48/0x26; g[7],g[8],g[1],g[3] in 0x4F/0x28. + * 6. Cases 0x5B/0x5C: the loops "found" bodies are emitted BEFORE the case label -> + * source-level labels placed between cases + `goto`. + * 7. Per-case temporaries are BLOCK-LOCAL (local-alloc), not function-scope. + * 8. stack locals declared in slot order (0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48, + * 0x50,0x58,0x60) -> frame 0x78. + * + * Case 0x5C -- the last 39 residuals. Four levers, all generalizable: + * + * 9. NO-PEEL: a `break` out of a do-while whose target COINCIDES with the loop's own + * natural fall-through exit makes NOTE_INSN_LOOP_BEG be followed by an + * unconditional jump -> jump.c `duplicate_loop_exit_test` (jump.c:599/2131) rotates + * the loop and peels iteration 1 (here `i` was provably 0, so the peeled `i++` + * const-folded to `li $a2,1` and dragged an extra lui/addiu/lw address block with + * it). Writing `goto L5D;` instead of `break;` -- SAME destination, different + * construct -- keeps the loop a plain do-while and the peel disappears. + * RULE: never let a loop's `break` land on the loop's own fall-through label. + * + * 10. SURVIVING REG-REG COPY (residual #1, `addu $v1,$v0,$zero`). A source-level + * `fp = q;` copy ALWAYS dies: cse.c `canon_reg` rewrites every later use of `fp` + * to `q` (qty_first_reg keeps the older reg) and flow deletes the now-dead set. + * To make a copy SURVIVE, its def and its uses must sit in different extended basic + * blocks -- cse resets its hash table at a label with >1 predecessor (a loop top). + * So: TEST THE MEM DIRECTLY, then assign the variable inside the branch body: + * if (arg1->a.w != 0) { fp5c = arg1->a.w; ... do { ... fp5c ... } while (); } + * cse folds the redundant 2nd load into `fp5c = ` (a copy) in the guard + * block, but CANNOT propagate it into the loop body -> the copy is emitted. + * (Assigning `fp5c` BEFORE the test gives one pseudo and no copy -- what we had.) + * + * 11. CROSS-JUMP-MERGED `(*(s16*)&D_801C7B34) = 3` (residual #2). `if (i != 10) { (*(s16*)&D_801C7B34) = 3; + * break; }` lets jump2 tail-merge the `lui/sh` into the shared .L80179AEC tail and + * reorg steal the `li 3` into the `bne` delay slot. Storing it unconditionally + * BEFORE the `if` blocks the merge and costs 3 inline insns. + * + * 12. THE UN-COALESCED LOOP COPY (residual #3, `addu $v1,$a0,$zero` + `addiu $a0,$v1,4`). + * This is loop.c's NON-REPLACEABLE DEST_REG GIV, not a source-level copy (see #10: + * those always die). Recipe -- BOTH halves are needed: + * a) make the pointer an INDEX GIV: `p5c = &D_801C77A4[i5c];` (a DEST_REG giv) + * b) make it NON-replaceable so loop.c emits `emit_insn_after(move dest,new_reg)` + * (loop.c:3945): record_giv (loop.c:4437) needs the giv used OUTSIDE the loop + * -- so the "found" body goes AFTER the loop and stores through `p5c`. + * c) put the BIV increment (`i5c++`) LAST in the body. loop.c inserts the reduced + * giv's `addiu` immediately BEFORE the biv's increment insn, so `i5c++` at the + * bottom puts `addiu $a0,$v1,4` in the loop-back delay slot. With `i5c++` at + * the TOP the giv-add lands at the top, nothing is left to fill the delay slot, + * and reorg STEALS the loop-top `move` into it (duplicating it: +1 insn). + * + * 13. Loop3 needs its OWN pointer pseudo (`r5c`, not `q5c`). `q5c` is loop1's pointer, + * and in loop1 $v1 is held by `fp5c` -> q5c is forced to $a0, and loop3 inherits it. + * Both "found" bodies then read $a0, become identical, and jump2 CROSS-JUMPS them + * into one block (-2 insns). A distinct pseudo frees loop3 into $v1, so found3 + * (`sw $zero,0($v1)`) differs from found2 (`sw $zero,0($a0)`) and they stay separate. + * RULE: two structurally identical loops must differ in REGISTER, or cross_jump + * merges their tails. + */ + + + + + + +M2C_UNK func_80178D40(s32 arg0, s32 arg1) +{ + extern void func_80179B28(s32); + extern void func_80137614(s32, s32, s32); + extern void func_8012F214(s32, s32, s32); + extern void func_8012F40C(void *, void *); + extern void func_80179D30(void *); + extern void func_80179D78(void *); + extern void func_80179EA0(void *); + extern void func_80179DCC(s32); + extern void func_80179DF8(void); + extern void func_80179E1C(s32); + extern void func_80179E48(s32); + extern void func_80179E74(s32); + extern void func_80179EE8(s32); + extern void func_80179F14(s32, s32); + extern void func_80179F44(void); + extern void func_80179F6C(s32); + extern void func_80179F98(s32); + extern void func_80179FEC(s32); + extern void func_8017A040(s32); + extern void func_8017A094(s32); + extern void func_8017A0C4(s32); + extern void func_8017A0F4(void); + extern void func_8017A11C(void); + extern void func_8017A144(s32); + extern void func_8017A180(void); + extern void func_8017A1A8(void); + extern void func_8017A1D0(void); + extern void func_8017A1F8(void); + extern void func_8017A220(void); + extern void func_8017A248(void); + extern void func_8017A270(void); + extern void func_8017A298(void); + extern void func_8017A2C0(void); + extern void func_8017A2E8(void); + extern void func_8017A310(void); + extern void func_8017A338(void); + extern void func_8017A360(void); + extern void func_8017A388(void); + extern void func_8017A3B0(void); + extern void func_8017A3D8(void); + extern void func_8017AD0C(s32); + extern void func_8017B238(void *, s32); + extern void func_8017B614(void *, s32); + extern void func_8017B7A8(void *); + extern void func_8017B824(void); + extern void func_8017B880(void); + extern void func_8017B940(void *); + extern void func_8017BA3C(void *, s32); + extern void func_8017BB34(void *, s32); + extern void func_8012A828(s32, void*); + extern s32 func_8012B8A4(s16*); + extern void func_8012E88C(u8*); + extern void func_8012E8A8(u8*); + extern void func_8001AAD0(s32, s32); + extern s16 D_801C7764; + extern s16 D_801C7768; + extern s16 D_801C776C; + extern s16 D_801C7770; + extern s32 D_801C7778; + extern s32 D_801C777C; + extern s16 D_801C7790; + extern s16 D_801C7794; + extern s32 D_801C7798; + extern s32 D_801C77A0; + extern s32 D_801C77A4[10]; + extern s32 D_801C79C8; + extern s16 D_801C7A90; + extern s32 D_801C7ABC; + + + SV3_80178D40 v10, v18, v20, v28, v30, v38, v40, v48; + s32 out50[2]; + SV3_80178D40 v58, v60; + Actor_80178D40 *pv = &(*(Actor_80178D40*)&D_80126B58); + s32 i5b, i5c, fp5b, fp5c; + s32 *q5b, *q5c, *p5c, *r5c; + s16 *g = &D_801C7A90; + + switch (((Cmd_80178D40 *)arg1)->op) { + case 1: + func_80179B28(D_801C7760); + D_801C7760 = ((s32 (*)(s32, s32, s32))func_80137614)(((Cmd_80178D40 *)arg1)->a.w, D_801C776C, D_801C7770 ? 0x48 : 0x40); + (*(s16*)&D_801C7B34) = 2; + break; + case 0: + func_80179B28(D_801C7760); + D_801C7760 = ((s32 (*)(s32, s32, s32))func_80137614)(((Cmd_80178D40 *)arg1)->a.w, D_801C7764, D_801C7768 ? 0x48 : 0x40); + (*(s16*)&D_801C7B34) = 1; + break; + case 0x45: + ((void (*)(s32))((Cmd_80178D40 *)arg1)->a.w)(((Actor_80178D40 *)arg0)); + if (D_801C79C8 != 0) { + func_80179B28(D_801C7760); + D_801C7760 = ((s32 (*)(s32, s32, s32))func_80137614)(((Actor_80178D40 *)arg0)->unkDC[1], D_801C7764, D_801C7768 ? 0x48 : 0x40); + (*(s16*)&D_801C7B34) = 1; + } else { + (*(s16*)&D_801C7B34) = 3; + } + break; + case 0x32: + func_80179B28(D_801C7760); + D_801C7760 = ((s32 (*)(s32, s32, s32))func_80137614)(((Actor_80178D40 *)arg0)->unkDC[((Cmd_80178D40 *)arg1)->a.w], D_801C7764, + D_801C7768 ? 0x48 : 0x40); + (*(s16*)&D_801C7B34) = 1; + break; + case 2: + func_80179B28(D_801C7760); + if (D_801C7778 != 0) { + D_801C7348 = D_801C7778; + D_801C7778 = 0; + (*(s16*)&D_801C7B34) = 3; + return; + } + (*(s16*)&D_801C7B34) = 6; + break; + case 6: + func_80179DF8(); + (*(s16*)&D_801C7B34) = 3; + break; + case 3: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_80179D30(&v10); + (*(s16*)&D_801C7B34) = 3; + break; + case 4: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0), &v10, &v18); + func_80179D30(&v18); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x4C: + func_80179D78((void *)((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x4D: + v10.vx = ((Blk_80178D40 *)((Cmd_80178D40 *)arg1)->a.p)->f0; + v10.vy = 0; + v10.vz = ((Blk_80178D40 *)((Cmd_80178D40 *)arg1)->a.p)->f4; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0), &v10, &v18); + v18.pad = ((Blk_80178D40 *)((Cmd_80178D40 *)arg1)->a.p)->f6; + func_80179D78(&v18); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x15: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0)->unkD4, &v10, &v18); + func_80179D30(&v18); + (*(s16*)&D_801C7B34) = 3; + break; + case 5: + func_80179DCC(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801C7B34) = 3; + break; + case 7: + func_80179E1C(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801C7B34) = 3; + break; + case 8: + func_80179E74(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801C7B34) = 3; + break; + case 9: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_80179EA0(&v10); + (*(s16*)&D_801C7B34) = 3; + break; + case 0xA: + v10.vx = ((Actor_80178D40 *)arg0)->unk6; + v10.vy = ((Actor_80178D40 *)arg0)->unkA; + v10.vz = ((Actor_80178D40 *)arg0)->unkE; + func_80179EA0(&v10); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x16: { + Actor_80178D40 *p = ((Actor_80178D40 *)arg0)->unkD4; + v10.vx = p->unk6; + v10.vy = p->unkA; + v10.vz = p->unkE; + func_80179EA0(&v10); + (*(s16*)&D_801C7B34) = 3; + break; + } + case 0xB: + func_8017A0F4(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0xC: + func_8017A11C(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0xD: + func_8017A180(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0xE: + func_8017A1A8(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x10: + func_8017A1D0(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x46: + func_8017A1F8(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x59: + func_8017A220(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x5A: + func_8017A248(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x49: + func_8017A144(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x47: + func_8017A270(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x17: + func_80179EE8(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x18: + func_80179F14(((Cmd_80178D40 *)arg1)->a.h[0], ((Cmd_80178D40 *)arg1)->a.h[1]); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x19: + func_80179F6C(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x1A: + func_80179F98(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x51: + func_8017A040(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x1B: + D_801C7798 = ((Cmd_80178D40 *)arg1)->a.w; + func_80179F44(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x1C: + func_8017A338(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x52: + func_8017A360(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x1D: + func_8017A388(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x3B: + func_8017A094(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x3C: + func_8017A0C4(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0xF: + case 0x3F: + (*(s16*)&D_801C7B34) = 4; + D_801C734C = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x3E: + (*(s16*)&D_801C7B34) = 5; + D_801C778C = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x40: + D_801C778C = (s32)func_8017A3B0; + (*(s16*)&D_801C7B34) = 5; + break; + case 0x23: + ((void (*)(void *, s32))func_8012A828)(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x31: + ((void (*)(void *, s32))func_8012A828)(((Actor_80178D40 *)arg0), ((Actor_80178D40 *)arg0)->unkDC[((Cmd_80178D40 *)arg1)->a.w]); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x24: + (*(s16*)&D_801C7B34) = 3; + ((Actor_80178D40 *)arg0)->unk20->unk12 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x25: + g[0] = 1; + g[2] = ((Actor_80178D40 *)arg0)->unk20->unk12 + ((Cmd_80178D40 *)arg1)->a.uh[0]; + g[1] = 0x1E; + (*(s16*)&D_801C7B34) = 3; + g[3] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x48: + g[0] = 1; + g[2] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + g[1] = 0x1E; + (*(s16*)&D_801C7B34) = 3; + g[3] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x26: + g[0] = 1; + g[2] = ((s32 (*)(void *))func_8012B8A4)(((Actor_80178D40 *)arg0)); + g[1] = 0x1E; + (*(s16*)&D_801C7B34) = 3; + g[3] = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x3D: + ((void(*)(void *, s32))func_8012E8E0)(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x27: + g[0] = 2; + g[4] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + (*(s16*)&D_801C7B34) = 3; + g[1] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x4F: + g[5] = 1; + g[0] = 3; + g[6] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + (*(s16*)&D_801C7B34) = 3; + g[7] = ((Actor_80178D40 *)arg0)->unkA; + g[8] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + g[1] = 0x10; + g[3] = 4; + /* fallthrough */ + case 0x28: + g[5] = 0; + g[0] = 3; + g[6] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + (*(s16*)&D_801C7B34) = 3; + g[7] = ((Actor_80178D40 *)arg0)->unkA; + g[8] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + g[1] = 0x10; + g[3] = 4; + break; + case 0x29: + v20.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v20.vy = ((Actor_80178D40 *)arg0)->unkA; + v20.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0), &v20, &v28); + g[5] = 0; + g[0] = 3; + *(SV3_80178D40 *)(g + 6) = v28; + g[1] = 0x10; + g[3] = 4; + (*(s16*)&D_801C7B34) = 3; + break; + case 0x50: + v30.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v30.vy = ((Actor_80178D40 *)arg0)->unkA; + v30.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0), &v30, &v38); + g[5] = 1; + g[0] = 3; + *(SV3_80178D40 *)(g + 6) = v38; + g[1] = 0x10; + g[3] = 4; + (*(s16*)&D_801C7B34) = 3; + break; + case 0x2A: + g[0] = 4; + (*(s16*)&D_801C7B34) = 3; + g[1] = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x1E: + func_8017B238(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x21: + func_8017BA3C(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B238(((Actor_80178D40 *)arg0), (s32)&D_801C777C); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x54: + func_8017BB34(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B238(((Actor_80178D40 *)arg0), (s32)&D_801C777C); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x1F: + func_8017B614(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x22: + func_8017BA3C(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B614(((Actor_80178D40 *)arg0), (s32)&D_801C777C); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x55: + func_8017BB34(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B614(((Actor_80178D40 *)arg0), (s32)&D_801C777C); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x20: + func_8017B7A8(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x4E: + D_801C77A0 = ((Cmd_80178D40 *)arg1)->a.w; + func_8017B940(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x57: + func_8017B824(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x58: + func_8017B880(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x2B: + (*(s16*)&D_801C7B34) = 3; + ((Actor_80178D40 *)arg0)->unk2 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2C: + (*(s16*)&D_801C7B34) = 3; + ((Actor_80178D40 *)arg0)->unk34 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2D: + (*(s16*)&D_801C7B34) = 3; + ((Actor_80178D40 *)arg0)->unkD8 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2F: + (*(s16*)&D_801C7B34) = 3; + ((Actor_80178D40 *)arg0)->unk10A = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2E: + (*(s16*)&D_801C7B34) = 3; + ((Actor_80178D40 *)arg0)->unkF8 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x11: + func_8017A298(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x12: + func_8017A2C0(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x13: + func_8017A2E8(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x14: + func_8017A310(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x33: { + void (*f)(Actor_80178D40 *) = (void (*)(Actor_80178D40 *))((Cmd_80178D40 *)arg1)->a.w; + D_801C7ABC = (s32)&((Cmd_80178D40 *)arg1)[1]; + f(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801C7B34) = 3; + break; + } + case 0x30: + if (((Cmd_80178D40 *)arg1)->a.w == 0) { + ((void (*)(void *))func_8012E8A8)(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801C7B34) = 3; + } else { + ((void (*)(void *))func_8012E88C)(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801C7B34) = 3; + } + break; + case 0x4A: + ((void(*)())func_80175414)(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x4B: + func_80175454(); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x34: + (*(s16*)&D_801C7B34) = 3; + D_801C7348 = ((Cmd_80178D40 *)arg1)->a.w; + return; + case 0x35: + D_801C7778 = (s32)&((Cmd_80178D40 *)arg1)[1]; + (*(s16*)&D_801C7B34) = 3; + D_801C7348 = ((Cmd_80178D40 *)arg1)->a.w; + return; + case 0x36: + (*(s16*)&D_801C7B34) = 3; + D_801C7348 += 8; + if (((s32 (*)(s32))((Cmd_80178D40 *)arg1)->a.w)(((Actor_80178D40 *)arg0)) == 0) { + break; + } + D_801C7348 = *(s32 *)(D_801C7348 + 4); + return; + case 0x37: + (*(s16*)&D_801C7B34) = 3; + D_801C7764 = ((Cmd_80178D40 *)arg1)->a.uh[0]; + D_801C7768 = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x38: + (*(s16*)&D_801C7B34) = 3; + D_801C776C = ((Cmd_80178D40 *)arg1)->a.uh[0]; + D_801C7770 = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x39: { + s32 w1, w2; + v40.vx = ((Actor_80178D40 *)arg0)->unk6; + v40.vy = ((Actor_80178D40 *)arg0)->unkA; + v40.vz = ((Actor_80178D40 *)arg0)->unkE; + v48.vx = pv->unk6; + v48.vy = pv->unkA; + v48.vz = pv->unkE; + func_8012F40C(out50, &v40); + w1 = out50[0]; + func_8012F40C(out50, &v48); + w2 = out50[0]; + (*(s16*)&D_801C7B34) = 3; + D_801C7764 = w1; + D_801C7768 = (s16)w1 >= (s16)w2; + break; + } + case 0x3A: { + s32 w1, w2; + v58.vx = ((Actor_80178D40 *)arg0)->unk6; + v58.vy = ((Actor_80178D40 *)arg0)->unkA; + v58.vz = ((Actor_80178D40 *)arg0)->unkE; + v60.vx = pv->unk6; + v60.vy = pv->unkA; + v60.vz = pv->unkE; + func_8012F40C(out50, &v58); + w1 = out50[0]; + func_8012F40C(out50, &v60); + w2 = out50[0]; + (*(s16*)&D_801C7B34) = 3; + D_801C776C = w2; + D_801C7770 = (s16)w1 < (s16)w2; + break; + } + case 0x41: + ((void(*)(s32, s32))func_8002D4C8)(((Cmd_80178D40 *)arg1)->a.uh[0], ((Cmd_80178D40 *)arg1)->a.uh[1]); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x42: + func_8017AD0C(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x43: + D_801C778C = (s32)func_8017A3D8; + D_801C7794 = 0; + (*(s16*)&D_801C7B34) = 5; + D_801C7790 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x44: + func_8001AAD0(((Cmd_80178D40 *)arg1)->a.h[0], ((Cmd_80178D40 *)arg1)->a.h[1]); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x53: + func_80179E48(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x56: + func_80179FEC(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801C7B34) = 3; + break; + L5B_found: + fp5b = ((Cmd_80178D40 *)arg1)->a.w; + *q5b = fp5b; + ((void (*)(Actor_80178D40 *))fp5b)(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801C7B34) = 3; + break; + case 0x5B: + i5b = 0; + q5b = D_801C77A4; + do { + i5b++; + if (*q5b == 0) { + goto L5B_found; + } + q5b++; + } while (i5b < 10); + (*(s16*)&D_801C7B34) = 3; + break; + L5C_found1: + *q5c = 0; + goto L5C_join; + case 0x5C: + i5c = 0; + if (((Cmd_80178D40 *)arg1)->a.w != 0) { + fp5c = ((Cmd_80178D40 *)arg1)->a.w; + q5c = D_801C77A4; + do { + if (*q5c == fp5c) { + goto L5C_found1; + } + i5c++; + q5c++; + } while (i5c < 10); + L5C_join: + if (i5c != 10) { + (*(s16*)&D_801C7B34) = 3; + break; + } + i5c = 0; + do { + p5c = &D_801C77A4[i5c]; + if (*p5c != 0) { + goto L5C_found2; + } + i5c++; + } while (i5c < 10); + (*(s16*)&D_801C7B34) = 3; + break; + L5C_found2: + *p5c = 0; + goto L5D; + } + r5c = D_801C77A4; + do { + i5c++; + if (*r5c != 0) { + *r5c = 0; + goto L5D; + } + r5c++; + } while (i5c < 10); + /* fallthrough */ + case 0x5D: + L5D: + (*(s16*)&D_801C7B34) = 3; + break; + default: + break; + } +Lend: + D_801C7348 += 8; +} DEFINE_func_80179B28() /* dedup: shared engine-core @0x80179b28 (src/shared) */ diff --git a/src/ov_SC07_010/ov_SC07_010_jr_801789AC.c b/src/ov_SC07_010/ov_SC07_010_jr_801789AC.c index 25ed56717..fb677704c 100644 --- a/src/ov_SC07_010/ov_SC07_010_jr_801789AC.c +++ b/src/ov_SC07_010/ov_SC07_010_jr_801789AC.c @@ -2903,7 +2903,746 @@ void func_80178D18(void) { } -INCLUDE_ASM("asm/ov_SC07_010/nonmatchings/ov_SC07_010_jr_801789AC", func_80178D40); +extern void func_8002D4C8(s32 a0, s32 a1); +extern void func_8012E8E0(s32 a0, s32 a1); +extern void func_80175414(s32); +extern void func_80175454(void); + +/* func_80178D40 - 890 ins, 94-case jr switch (jtbl_801D8E24). + * STATUS: **MATCH** -- 890/890 ins, byte-exact (masked). PIN-FREE (this body is + * templated across 134 overlays; a pinned body would crash the sibling TUs). + * python3 tools/match_one.py func_80178D40 --c .run/phase26-cracks/func_80178D40.c \ + * --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC + * => MATCH (890 ins) + * Jump table VERIFIED: 94 entries (= the sltiu 0x5E bound, no trailing zero pad), + * 93 unique blocks, cases 0xF/0x3F share one block; my case->block sequence is + * identical to jtbl_801D8E24's. + * + * Byte-derived structure (the levers that cracked it): + * 1. NO status variable. Every case stores `(*(s16*)&D_801A9544) = K` DIRECTLY. The shared + * `sh $v0, (*(s16*)&D_801A9544)` at .L80179AEC is a jump2 CROSS-JUMP merge of those stores: + * find_cross_jump's FIRST call (minimum=1, vs the code before the target label) + * matches that 1 insn, and because it succeeds the jump_chain loop (minimum=2) is + * SKIPPED -- which is what BLOCKS the deeper, wrong 3-insn merges of the identical + * func_80137614 tails (cases 0/0x45/0x32). reorg then steals the `li K` back into + * each `j` delay slot, so it looks un-merged. A `status` pseudo instead of direct + * stores loses that block and costs 6 insns. + * 2. after-switch = `D_801A7840 += 8;` (.L80179AF4) -> the out-of-range default lands + * there with NO explicit `default:` label. + * 3. arg0/arg1/pv are STRUCT pointers. gcc-2.7.2 sched alias (sched.c true_dependence) + * only lets a MEM_IN_STRUCT varying-address load hoist above a non-MEM_IN_STRUCT + * fixed-address store (the (*(s16*)&D_801A9544) store). Raw `*(T *)(int + off)` casts get + * MEM_IN_STRUCT_P = 0 and block that hoist -> stray nops. + * 4. g = &D_801A94A0 stays a plain `s16 *` (NOT a struct ptr) so its varying, + * non-in-struct stores keep their order w.r.t. the loads. + * 5. Statement order inside the D_801A94A0 cases is load-bearing (sched LUID/priority): + * g[0],g[2],g[1] in 0x25/0x48/0x26; g[7],g[8],g[1],g[3] in 0x4F/0x28. + * 6. Cases 0x5B/0x5C: the loops "found" bodies are emitted BEFORE the case label -> + * source-level labels placed between cases + `goto`. + * 7. Per-case temporaries are BLOCK-LOCAL (local-alloc), not function-scope. + * 8. stack locals declared in slot order (0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48, + * 0x50,0x58,0x60) -> frame 0x78. + * + * Case 0x5C -- the last 39 residuals. Four levers, all generalizable: + * + * 9. NO-PEEL: a `break` out of a do-while whose target COINCIDES with the loop's own + * natural fall-through exit makes NOTE_INSN_LOOP_BEG be followed by an + * unconditional jump -> jump.c `duplicate_loop_exit_test` (jump.c:599/2131) rotates + * the loop and peels iteration 1 (here `i` was provably 0, so the peeled `i++` + * const-folded to `li $a2,1` and dragged an extra lui/addiu/lw address block with + * it). Writing `goto L5D;` instead of `break;` -- SAME destination, different + * construct -- keeps the loop a plain do-while and the peel disappears. + * RULE: never let a loop's `break` land on the loop's own fall-through label. + * + * 10. SURVIVING REG-REG COPY (residual #1, `addu $v1,$v0,$zero`). A source-level + * `fp = q;` copy ALWAYS dies: cse.c `canon_reg` rewrites every later use of `fp` + * to `q` (qty_first_reg keeps the older reg) and flow deletes the now-dead set. + * To make a copy SURVIVE, its def and its uses must sit in different extended basic + * blocks -- cse resets its hash table at a label with >1 predecessor (a loop top). + * So: TEST THE MEM DIRECTLY, then assign the variable inside the branch body: + * if (arg1->a.w != 0) { fp5c = arg1->a.w; ... do { ... fp5c ... } while (); } + * cse folds the redundant 2nd load into `fp5c = ` (a copy) in the guard + * block, but CANNOT propagate it into the loop body -> the copy is emitted. + * (Assigning `fp5c` BEFORE the test gives one pseudo and no copy -- what we had.) + * + * 11. CROSS-JUMP-MERGED `(*(s16*)&D_801A9544) = 3` (residual #2). `if (i != 10) { (*(s16*)&D_801A9544) = 3; + * break; }` lets jump2 tail-merge the `lui/sh` into the shared .L80179AEC tail and + * reorg steal the `li 3` into the `bne` delay slot. Storing it unconditionally + * BEFORE the `if` blocks the merge and costs 3 inline insns. + * + * 12. THE UN-COALESCED LOOP COPY (residual #3, `addu $v1,$a0,$zero` + `addiu $a0,$v1,4`). + * This is loop.c's NON-REPLACEABLE DEST_REG GIV, not a source-level copy (see #10: + * those always die). Recipe -- BOTH halves are needed: + * a) make the pointer an INDEX GIV: `p5c = &D_801A7C9C[i5c];` (a DEST_REG giv) + * b) make it NON-replaceable so loop.c emits `emit_insn_after(move dest,new_reg)` + * (loop.c:3945): record_giv (loop.c:4437) needs the giv used OUTSIDE the loop + * -- so the "found" body goes AFTER the loop and stores through `p5c`. + * c) put the BIV increment (`i5c++`) LAST in the body. loop.c inserts the reduced + * giv's `addiu` immediately BEFORE the biv's increment insn, so `i5c++` at the + * bottom puts `addiu $a0,$v1,4` in the loop-back delay slot. With `i5c++` at + * the TOP the giv-add lands at the top, nothing is left to fill the delay slot, + * and reorg STEALS the loop-top `move` into it (duplicating it: +1 insn). + * + * 13. Loop3 needs its OWN pointer pseudo (`r5c`, not `q5c`). `q5c` is loop1's pointer, + * and in loop1 $v1 is held by `fp5c` -> q5c is forced to $a0, and loop3 inherits it. + * Both "found" bodies then read $a0, become identical, and jump2 CROSS-JUMPS them + * into one block (-2 insns). A distinct pseudo frees loop3 into $v1, so found3 + * (`sw $zero,0($v1)`) differs from found2 (`sw $zero,0($a0)`) and they stay separate. + * RULE: two structurally identical loops must differ in REGISTER, or cross_jump + * merges their tails. + */ + + + + + + +M2C_UNK func_80178D40(s32 arg0, s32 arg1) +{ + extern void func_80179B28(s32); + extern s32 func_80137614(s32, s32, s32); + extern void func_8012F214(void *, void *, void *); + extern void func_8012F40C(void *, void *); + extern void func_80179D30(void *); + extern void func_80179D78(void *); + extern void func_80179EA0(void *); + extern void func_80179DCC(s32); + extern void func_80179DF8(void); + extern void func_80179E1C(s32); + extern void func_80179E48(s32); + extern void func_80179E74(s32); + extern void func_80179EE8(s32); + extern void func_80179F14(s32, s32); + extern void func_80179F44(void); + extern void func_80179F6C(s32); + extern void func_80179F98(s32); + extern void func_80179FEC(s32); + extern void func_8017A040(s32); + extern void func_8017A094(s32); + extern void func_8017A0C4(s32); + extern void func_8017A0F4(void); + extern void func_8017A11C(void); + extern void func_8017A144(s32); + extern void func_8017A180(void); + extern void func_8017A1A8(void); + extern void func_8017A1D0(void); + extern void func_8017A1F8(void); + extern void func_8017A220(void); + extern void func_8017A248(void); + extern void func_8017A270(void); + extern void func_8017A298(void); + extern void func_8017A2C0(void); + extern void func_8017A2E8(void); + extern void func_8017A310(void); + extern void func_8017A338(void); + extern void func_8017A360(void); + extern void func_8017A388(void); + extern void func_8017A3B0(void); + extern void func_8017A3D8(void); + extern void func_8017AD0C(s32); + extern void func_8017B238(void *, s32); + extern void func_8017B614(void *, s32); + extern void func_8017B7A8(void *); + extern void func_8017B824(void); + extern void func_8017B880(void); + extern void func_8017B940(void *); + extern void func_8017BA3C(void *, s32); + extern void func_8017BB34(void *, s32); + extern void func_8012A828(s32, void*); + extern s32 func_8012B8A4(void *); + extern void func_8012E88C(void *); + extern void func_8012E8A8(void *); + extern void func_8001AAD0(s32, s32); + extern s16 D_801A7C5C; + extern s16 D_801A7C60; + extern s16 D_801A7C64; + extern s16 D_801A7C68; + extern s32 D_801A7C70; + extern s32 D_801A7C74; + extern s16 D_801A7C88; + extern s16 D_801A7C8C; + extern s32 D_801A7C90; + extern s32 D_801A7C98; + extern s32 D_801A7C9C[10]; + extern s32 D_801A93E8; + extern s16 D_801A94A0; + extern s32 D_801A94CC; + + + SV3_80178D40 v10, v18, v20, v28, v30, v38, v40, v48; + s32 out50[2]; + SV3_80178D40 v58, v60; + Actor_80178D40 *pv = &(*(Actor_80178D40*)&D_80126B58); + s32 i5b, i5c, fp5b, fp5c; + s32 *q5b, *q5c, *p5c, *r5c; + s16 *g = &D_801A94A0; + + switch (((Cmd_80178D40 *)arg1)->op) { + case 1: + func_80179B28(D_801A7C58); + D_801A7C58 = func_80137614(((Cmd_80178D40 *)arg1)->a.w, D_801A7C64, D_801A7C68 ? 0x48 : 0x40); + (*(s16*)&D_801A9544) = 2; + break; + case 0: + func_80179B28(D_801A7C58); + D_801A7C58 = func_80137614(((Cmd_80178D40 *)arg1)->a.w, D_801A7C5C, D_801A7C60 ? 0x48 : 0x40); + (*(s16*)&D_801A9544) = 1; + break; + case 0x45: + ((void (*)(s32))((Cmd_80178D40 *)arg1)->a.w)(((Actor_80178D40 *)arg0)); + if (D_801A93E8 != 0) { + func_80179B28(D_801A7C58); + D_801A7C58 = func_80137614(((Actor_80178D40 *)arg0)->unkDC[1], D_801A7C5C, D_801A7C60 ? 0x48 : 0x40); + (*(s16*)&D_801A9544) = 1; + } else { + (*(s16*)&D_801A9544) = 3; + } + break; + case 0x32: + func_80179B28(D_801A7C58); + D_801A7C58 = func_80137614(((Actor_80178D40 *)arg0)->unkDC[((Cmd_80178D40 *)arg1)->a.w], D_801A7C5C, + D_801A7C60 ? 0x48 : 0x40); + (*(s16*)&D_801A9544) = 1; + break; + case 2: + func_80179B28(D_801A7C58); + if (D_801A7C70 != 0) { + D_801A7840 = D_801A7C70; + D_801A7C70 = 0; + (*(s16*)&D_801A9544) = 3; + return; + } + (*(s16*)&D_801A9544) = 6; + break; + case 6: + func_80179DF8(); + (*(s16*)&D_801A9544) = 3; + break; + case 3: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_80179D30(&v10); + (*(s16*)&D_801A9544) = 3; + break; + case 4: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_8012F214(((Actor_80178D40 *)arg0), &v10, &v18); + func_80179D30(&v18); + (*(s16*)&D_801A9544) = 3; + break; + case 0x4C: + func_80179D78((void *)((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x4D: + v10.vx = ((Blk_80178D40 *)((Cmd_80178D40 *)arg1)->a.p)->f0; + v10.vy = 0; + v10.vz = ((Blk_80178D40 *)((Cmd_80178D40 *)arg1)->a.p)->f4; + func_8012F214(((Actor_80178D40 *)arg0), &v10, &v18); + v18.pad = ((Blk_80178D40 *)((Cmd_80178D40 *)arg1)->a.p)->f6; + func_80179D78(&v18); + (*(s16*)&D_801A9544) = 3; + break; + case 0x15: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_8012F214(((Actor_80178D40 *)arg0)->unkD4, &v10, &v18); + func_80179D30(&v18); + (*(s16*)&D_801A9544) = 3; + break; + case 5: + func_80179DCC(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801A9544) = 3; + break; + case 7: + func_80179E1C(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801A9544) = 3; + break; + case 8: + func_80179E74(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801A9544) = 3; + break; + case 9: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_80179EA0(&v10); + (*(s16*)&D_801A9544) = 3; + break; + case 0xA: + v10.vx = ((Actor_80178D40 *)arg0)->unk6; + v10.vy = ((Actor_80178D40 *)arg0)->unkA; + v10.vz = ((Actor_80178D40 *)arg0)->unkE; + func_80179EA0(&v10); + (*(s16*)&D_801A9544) = 3; + break; + case 0x16: { + Actor_80178D40 *p = ((Actor_80178D40 *)arg0)->unkD4; + v10.vx = p->unk6; + v10.vy = p->unkA; + v10.vz = p->unkE; + func_80179EA0(&v10); + (*(s16*)&D_801A9544) = 3; + break; + } + case 0xB: + func_8017A0F4(); + (*(s16*)&D_801A9544) = 3; + break; + case 0xC: + func_8017A11C(); + (*(s16*)&D_801A9544) = 3; + break; + case 0xD: + func_8017A180(); + (*(s16*)&D_801A9544) = 3; + break; + case 0xE: + func_8017A1A8(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x10: + func_8017A1D0(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x46: + func_8017A1F8(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x59: + func_8017A220(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x5A: + func_8017A248(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x49: + func_8017A144(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x47: + func_8017A270(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x17: + func_80179EE8(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801A9544) = 3; + break; + case 0x18: + func_80179F14(((Cmd_80178D40 *)arg1)->a.h[0], ((Cmd_80178D40 *)arg1)->a.h[1]); + (*(s16*)&D_801A9544) = 3; + break; + case 0x19: + func_80179F6C(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801A9544) = 3; + break; + case 0x1A: + func_80179F98(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x51: + func_8017A040(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x1B: + D_801A7C90 = ((Cmd_80178D40 *)arg1)->a.w; + func_80179F44(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x1C: + func_8017A338(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x52: + func_8017A360(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x1D: + func_8017A388(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x3B: + func_8017A094(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x3C: + func_8017A0C4(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0xF: + case 0x3F: + (*(s16*)&D_801A9544) = 4; + D_801A7844 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x3E: + (*(s16*)&D_801A9544) = 5; + D_801A7C84 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x40: + D_801A7C84 = (s32)func_8017A3B0; + (*(s16*)&D_801A9544) = 5; + break; + case 0x23: + ((void (*)(void *, s32))func_8012A828)(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x31: + ((void (*)(void *, s32))func_8012A828)(((Actor_80178D40 *)arg0), ((Actor_80178D40 *)arg0)->unkDC[((Cmd_80178D40 *)arg1)->a.w]); + (*(s16*)&D_801A9544) = 3; + break; + case 0x24: + (*(s16*)&D_801A9544) = 3; + ((Actor_80178D40 *)arg0)->unk20->unk12 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x25: + g[0] = 1; + g[2] = ((Actor_80178D40 *)arg0)->unk20->unk12 + ((Cmd_80178D40 *)arg1)->a.uh[0]; + g[1] = 0x1E; + (*(s16*)&D_801A9544) = 3; + g[3] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x48: + g[0] = 1; + g[2] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + g[1] = 0x1E; + (*(s16*)&D_801A9544) = 3; + g[3] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x26: + g[0] = 1; + g[2] = func_8012B8A4(((Actor_80178D40 *)arg0)); + g[1] = 0x1E; + (*(s16*)&D_801A9544) = 3; + g[3] = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x3D: + ((void(*)(void *, s32))func_8012E8E0)(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x27: + g[0] = 2; + g[4] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + (*(s16*)&D_801A9544) = 3; + g[1] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x4F: + g[5] = 1; + g[0] = 3; + g[6] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + (*(s16*)&D_801A9544) = 3; + g[7] = ((Actor_80178D40 *)arg0)->unkA; + g[8] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + g[1] = 0x10; + g[3] = 4; + /* fallthrough */ + case 0x28: + g[5] = 0; + g[0] = 3; + g[6] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + (*(s16*)&D_801A9544) = 3; + g[7] = ((Actor_80178D40 *)arg0)->unkA; + g[8] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + g[1] = 0x10; + g[3] = 4; + break; + case 0x29: + v20.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v20.vy = ((Actor_80178D40 *)arg0)->unkA; + v20.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_8012F214(((Actor_80178D40 *)arg0), &v20, &v28); + g[5] = 0; + g[0] = 3; + *(SV3_80178D40 *)(g + 6) = v28; + g[1] = 0x10; + g[3] = 4; + (*(s16*)&D_801A9544) = 3; + break; + case 0x50: + v30.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v30.vy = ((Actor_80178D40 *)arg0)->unkA; + v30.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_8012F214(((Actor_80178D40 *)arg0), &v30, &v38); + g[5] = 1; + g[0] = 3; + *(SV3_80178D40 *)(g + 6) = v38; + g[1] = 0x10; + g[3] = 4; + (*(s16*)&D_801A9544) = 3; + break; + case 0x2A: + g[0] = 4; + (*(s16*)&D_801A9544) = 3; + g[1] = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x1E: + func_8017B238(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x21: + func_8017BA3C(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B238(((Actor_80178D40 *)arg0), (s32)&D_801A7C74); + (*(s16*)&D_801A9544) = 3; + break; + case 0x54: + func_8017BB34(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B238(((Actor_80178D40 *)arg0), (s32)&D_801A7C74); + (*(s16*)&D_801A9544) = 3; + break; + case 0x1F: + func_8017B614(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x22: + func_8017BA3C(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B614(((Actor_80178D40 *)arg0), (s32)&D_801A7C74); + (*(s16*)&D_801A9544) = 3; + break; + case 0x55: + func_8017BB34(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B614(((Actor_80178D40 *)arg0), (s32)&D_801A7C74); + (*(s16*)&D_801A9544) = 3; + break; + case 0x20: + func_8017B7A8(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801A9544) = 3; + break; + case 0x4E: + D_801A7C98 = ((Cmd_80178D40 *)arg1)->a.w; + func_8017B940(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801A9544) = 3; + break; + case 0x57: + func_8017B824(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x58: + func_8017B880(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x2B: + (*(s16*)&D_801A9544) = 3; + ((Actor_80178D40 *)arg0)->unk2 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2C: + (*(s16*)&D_801A9544) = 3; + ((Actor_80178D40 *)arg0)->unk34 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2D: + (*(s16*)&D_801A9544) = 3; + ((Actor_80178D40 *)arg0)->unkD8 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2F: + (*(s16*)&D_801A9544) = 3; + ((Actor_80178D40 *)arg0)->unk10A = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2E: + (*(s16*)&D_801A9544) = 3; + ((Actor_80178D40 *)arg0)->unkF8 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x11: + func_8017A298(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x12: + func_8017A2C0(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x13: + func_8017A2E8(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x14: + func_8017A310(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x33: { + void (*f)(Actor_80178D40 *) = (void (*)(Actor_80178D40 *))((Cmd_80178D40 *)arg1)->a.w; + D_801A94CC = (s32)&((Cmd_80178D40 *)arg1)[1]; + f(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801A9544) = 3; + break; + } + case 0x30: + if (((Cmd_80178D40 *)arg1)->a.w == 0) { + func_8012E8A8(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801A9544) = 3; + } else { + func_8012E88C(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801A9544) = 3; + } + break; + case 0x4A: + ((void(*)())func_80175414)(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x4B: + func_80175454(); + (*(s16*)&D_801A9544) = 3; + break; + case 0x34: + (*(s16*)&D_801A9544) = 3; + D_801A7840 = ((Cmd_80178D40 *)arg1)->a.w; + return; + case 0x35: + D_801A7C70 = (s32)&((Cmd_80178D40 *)arg1)[1]; + (*(s16*)&D_801A9544) = 3; + D_801A7840 = ((Cmd_80178D40 *)arg1)->a.w; + return; + case 0x36: + (*(s16*)&D_801A9544) = 3; + D_801A7840 += 8; + if (((s32 (*)(s32))((Cmd_80178D40 *)arg1)->a.w)(((Actor_80178D40 *)arg0)) == 0) { + break; + } + D_801A7840 = *(s32 *)(D_801A7840 + 4); + return; + case 0x37: + (*(s16*)&D_801A9544) = 3; + D_801A7C5C = ((Cmd_80178D40 *)arg1)->a.uh[0]; + D_801A7C60 = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x38: + (*(s16*)&D_801A9544) = 3; + D_801A7C64 = ((Cmd_80178D40 *)arg1)->a.uh[0]; + D_801A7C68 = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x39: { + s32 w1, w2; + v40.vx = ((Actor_80178D40 *)arg0)->unk6; + v40.vy = ((Actor_80178D40 *)arg0)->unkA; + v40.vz = ((Actor_80178D40 *)arg0)->unkE; + v48.vx = pv->unk6; + v48.vy = pv->unkA; + v48.vz = pv->unkE; + func_8012F40C(out50, &v40); + w1 = out50[0]; + func_8012F40C(out50, &v48); + w2 = out50[0]; + (*(s16*)&D_801A9544) = 3; + D_801A7C5C = w1; + D_801A7C60 = (s16)w1 >= (s16)w2; + break; + } + case 0x3A: { + s32 w1, w2; + v58.vx = ((Actor_80178D40 *)arg0)->unk6; + v58.vy = ((Actor_80178D40 *)arg0)->unkA; + v58.vz = ((Actor_80178D40 *)arg0)->unkE; + v60.vx = pv->unk6; + v60.vy = pv->unkA; + v60.vz = pv->unkE; + func_8012F40C(out50, &v58); + w1 = out50[0]; + func_8012F40C(out50, &v60); + w2 = out50[0]; + (*(s16*)&D_801A9544) = 3; + D_801A7C64 = w2; + D_801A7C68 = (s16)w1 < (s16)w2; + break; + } + case 0x41: + ((void(*)(s32, s32))func_8002D4C8)(((Cmd_80178D40 *)arg1)->a.uh[0], ((Cmd_80178D40 *)arg1)->a.uh[1]); + (*(s16*)&D_801A9544) = 3; + break; + case 0x42: + func_8017AD0C(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + case 0x43: + D_801A7C84 = (s32)func_8017A3D8; + D_801A7C8C = 0; + (*(s16*)&D_801A9544) = 5; + D_801A7C88 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x44: + func_8001AAD0(((Cmd_80178D40 *)arg1)->a.h[0], ((Cmd_80178D40 *)arg1)->a.h[1]); + (*(s16*)&D_801A9544) = 3; + break; + case 0x53: + func_80179E48(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801A9544) = 3; + break; + case 0x56: + func_80179FEC(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801A9544) = 3; + break; + L5B_found: + fp5b = ((Cmd_80178D40 *)arg1)->a.w; + *q5b = fp5b; + ((void (*)(Actor_80178D40 *))fp5b)(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801A9544) = 3; + break; + case 0x5B: + i5b = 0; + q5b = D_801A7C9C; + do { + i5b++; + if (*q5b == 0) { + goto L5B_found; + } + q5b++; + } while (i5b < 10); + (*(s16*)&D_801A9544) = 3; + break; + L5C_found1: + *q5c = 0; + goto L5C_join; + case 0x5C: + i5c = 0; + if (((Cmd_80178D40 *)arg1)->a.w != 0) { + fp5c = ((Cmd_80178D40 *)arg1)->a.w; + q5c = D_801A7C9C; + do { + if (*q5c == fp5c) { + goto L5C_found1; + } + i5c++; + q5c++; + } while (i5c < 10); + L5C_join: + if (i5c != 10) { + (*(s16*)&D_801A9544) = 3; + break; + } + i5c = 0; + do { + p5c = &D_801A7C9C[i5c]; + if (*p5c != 0) { + goto L5C_found2; + } + i5c++; + } while (i5c < 10); + (*(s16*)&D_801A9544) = 3; + break; + L5C_found2: + *p5c = 0; + goto L5D; + } + r5c = D_801A7C9C; + do { + i5c++; + if (*r5c != 0) { + *r5c = 0; + goto L5D; + } + r5c++; + } while (i5c < 10); + /* fallthrough */ + case 0x5D: + L5D: + (*(s16*)&D_801A9544) = 3; + break; + default: + break; + } +Lend: + D_801A7840 += 8; +} DEFINE_func_80179B28() /* dedup: shared engine-core @0x80179b28 (src/shared) */ diff --git a/src/ov_SC07_011/ov_SC07_011_jr_801789AC.c b/src/ov_SC07_011/ov_SC07_011_jr_801789AC.c index 656504d02..68d412ca6 100644 --- a/src/ov_SC07_011/ov_SC07_011_jr_801789AC.c +++ b/src/ov_SC07_011/ov_SC07_011_jr_801789AC.c @@ -3445,7 +3445,746 @@ void func_80178D18(void) { } -INCLUDE_ASM("asm/ov_SC07_011/nonmatchings/ov_SC07_011_jr_801789AC", func_80178D40); +extern void func_8002D4C8(s32 a0, s32 a1); +extern void func_8012E8E0(s32 a0, s32 a1); +extern void func_80175414(s32); +extern void func_80175454(void); + +/* func_80178D40 - 890 ins, 94-case jr switch (jtbl_801D8E24). + * STATUS: **MATCH** -- 890/890 ins, byte-exact (masked). PIN-FREE (this body is + * templated across 134 overlays; a pinned body would crash the sibling TUs). + * python3 tools/match_one.py func_80178D40 --c .run/phase26-cracks/func_80178D40.c \ + * --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC + * => MATCH (890 ins) + * Jump table VERIFIED: 94 entries (= the sltiu 0x5E bound, no trailing zero pad), + * 93 unique blocks, cases 0xF/0x3F share one block; my case->block sequence is + * identical to jtbl_801D8E24's. + * + * Byte-derived structure (the levers that cracked it): + * 1. NO status variable. Every case stores `(*(s16*)&D_801904FC) = K` DIRECTLY. The shared + * `sh $v0, (*(s16*)&D_801904FC)` at .L80179AEC is a jump2 CROSS-JUMP merge of those stores: + * find_cross_jump's FIRST call (minimum=1, vs the code before the target label) + * matches that 1 insn, and because it succeeds the jump_chain loop (minimum=2) is + * SKIPPED -- which is what BLOCKS the deeper, wrong 3-insn merges of the identical + * func_80137614 tails (cases 0/0x45/0x32). reorg then steals the `li K` back into + * each `j` delay slot, so it looks un-merged. A `status` pseudo instead of direct + * stores loses that block and costs 6 insns. + * 2. after-switch = `D_8018FED8 += 8;` (.L80179AF4) -> the out-of-range default lands + * there with NO explicit `default:` label. + * 3. arg0/arg1/pv are STRUCT pointers. gcc-2.7.2 sched alias (sched.c true_dependence) + * only lets a MEM_IN_STRUCT varying-address load hoist above a non-MEM_IN_STRUCT + * fixed-address store (the (*(s16*)&D_801904FC) store). Raw `*(T *)(int + off)` casts get + * MEM_IN_STRUCT_P = 0 and block that hoist -> stray nops. + * 4. g = &D_80190458 stays a plain `s16 *` (NOT a struct ptr) so its varying, + * non-in-struct stores keep their order w.r.t. the loads. + * 5. Statement order inside the D_80190458 cases is load-bearing (sched LUID/priority): + * g[0],g[2],g[1] in 0x25/0x48/0x26; g[7],g[8],g[1],g[3] in 0x4F/0x28. + * 6. Cases 0x5B/0x5C: the loops "found" bodies are emitted BEFORE the case label -> + * source-level labels placed between cases + `goto`. + * 7. Per-case temporaries are BLOCK-LOCAL (local-alloc), not function-scope. + * 8. stack locals declared in slot order (0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48, + * 0x50,0x58,0x60) -> frame 0x78. + * + * Case 0x5C -- the last 39 residuals. Four levers, all generalizable: + * + * 9. NO-PEEL: a `break` out of a do-while whose target COINCIDES with the loop's own + * natural fall-through exit makes NOTE_INSN_LOOP_BEG be followed by an + * unconditional jump -> jump.c `duplicate_loop_exit_test` (jump.c:599/2131) rotates + * the loop and peels iteration 1 (here `i` was provably 0, so the peeled `i++` + * const-folded to `li $a2,1` and dragged an extra lui/addiu/lw address block with + * it). Writing `goto L5D;` instead of `break;` -- SAME destination, different + * construct -- keeps the loop a plain do-while and the peel disappears. + * RULE: never let a loop's `break` land on the loop's own fall-through label. + * + * 10. SURVIVING REG-REG COPY (residual #1, `addu $v1,$v0,$zero`). A source-level + * `fp = q;` copy ALWAYS dies: cse.c `canon_reg` rewrites every later use of `fp` + * to `q` (qty_first_reg keeps the older reg) and flow deletes the now-dead set. + * To make a copy SURVIVE, its def and its uses must sit in different extended basic + * blocks -- cse resets its hash table at a label with >1 predecessor (a loop top). + * So: TEST THE MEM DIRECTLY, then assign the variable inside the branch body: + * if (arg1->a.w != 0) { fp5c = arg1->a.w; ... do { ... fp5c ... } while (); } + * cse folds the redundant 2nd load into `fp5c = ` (a copy) in the guard + * block, but CANNOT propagate it into the loop body -> the copy is emitted. + * (Assigning `fp5c` BEFORE the test gives one pseudo and no copy -- what we had.) + * + * 11. CROSS-JUMP-MERGED `(*(s16*)&D_801904FC) = 3` (residual #2). `if (i != 10) { (*(s16*)&D_801904FC) = 3; + * break; }` lets jump2 tail-merge the `lui/sh` into the shared .L80179AEC tail and + * reorg steal the `li 3` into the `bne` delay slot. Storing it unconditionally + * BEFORE the `if` blocks the merge and costs 3 inline insns. + * + * 12. THE UN-COALESCED LOOP COPY (residual #3, `addu $v1,$a0,$zero` + `addiu $a0,$v1,4`). + * This is loop.c's NON-REPLACEABLE DEST_REG GIV, not a source-level copy (see #10: + * those always die). Recipe -- BOTH halves are needed: + * a) make the pointer an INDEX GIV: `p5c = &D_80190334[i5c];` (a DEST_REG giv) + * b) make it NON-replaceable so loop.c emits `emit_insn_after(move dest,new_reg)` + * (loop.c:3945): record_giv (loop.c:4437) needs the giv used OUTSIDE the loop + * -- so the "found" body goes AFTER the loop and stores through `p5c`. + * c) put the BIV increment (`i5c++`) LAST in the body. loop.c inserts the reduced + * giv's `addiu` immediately BEFORE the biv's increment insn, so `i5c++` at the + * bottom puts `addiu $a0,$v1,4` in the loop-back delay slot. With `i5c++` at + * the TOP the giv-add lands at the top, nothing is left to fill the delay slot, + * and reorg STEALS the loop-top `move` into it (duplicating it: +1 insn). + * + * 13. Loop3 needs its OWN pointer pseudo (`r5c`, not `q5c`). `q5c` is loop1's pointer, + * and in loop1 $v1 is held by `fp5c` -> q5c is forced to $a0, and loop3 inherits it. + * Both "found" bodies then read $a0, become identical, and jump2 CROSS-JUMPS them + * into one block (-2 insns). A distinct pseudo frees loop3 into $v1, so found3 + * (`sw $zero,0($v1)`) differs from found2 (`sw $zero,0($a0)`) and they stay separate. + * RULE: two structurally identical loops must differ in REGISTER, or cross_jump + * merges their tails. + */ + + + + + + +M2C_UNK func_80178D40(s32 arg0, s32 arg1) +{ + extern void func_80179B28(s32); + extern void func_80137614(s32, s32, s32); + extern void func_8012F214(s32, s32, s32); + extern void func_8012F40C(void *, void *); + extern void func_80179D30(void *); + extern void func_80179D78(void *); + extern void func_80179EA0(void *); + extern void func_80179DCC(s32); + extern void func_80179DF8(void); + extern void func_80179E1C(s32); + extern void func_80179E48(s32); + extern void func_80179E74(s32); + extern void func_80179EE8(s32); + extern void func_80179F14(s32, s32); + extern void func_80179F44(void); + extern void func_80179F6C(s32); + extern void func_80179F98(s32); + extern void func_80179FEC(s32); + extern void func_8017A040(s32); + extern void func_8017A094(s32); + extern void func_8017A0C4(s32); + extern void func_8017A0F4(void); + extern void func_8017A11C(void); + extern void func_8017A144(s32); + extern void func_8017A180(void); + extern void func_8017A1A8(void); + extern void func_8017A1D0(void); + extern void func_8017A1F8(void); + extern void func_8017A220(void); + extern void func_8017A248(void); + extern void func_8017A270(void); + extern void func_8017A298(void); + extern void func_8017A2C0(void); + extern void func_8017A2E8(void); + extern void func_8017A310(void); + extern void func_8017A338(void); + extern void func_8017A360(void); + extern void func_8017A388(void); + extern void func_8017A3B0(void); + extern void func_8017A3D8(void); + extern void func_8017AD0C(s32); + extern void func_8017B238(void *, s32); + extern void func_8017B614(void *, s32); + extern void func_8017B7A8(void *); + extern void func_8017B824(void); + extern void func_8017B880(void); + extern void func_8017B940(void *); + extern void func_8017BA3C(void *, s32); + extern void func_8017BB34(void *, s32); + extern void func_8012A828(s32, void*); + extern s32 func_8012B8A4(s16*); + extern void func_8012E88C(u8*); + extern void func_8012E8A8(u8*); + extern void func_8001AAD0(s32, s32); + extern s16 D_801902F4; + extern s16 D_801902F8; + extern s16 D_801902FC; + extern s16 D_80190300; + extern s32 D_80190308; + extern s32 D_8019030C; + extern s16 D_80190320; + extern s16 D_80190324; + extern s32 D_80190328; + extern s32 D_80190330; + extern s32 D_80190334[10]; + extern s32 D_801903A0; + extern s16 D_80190458; + extern s32 D_80190484; + + + SV3_80178D40 v10, v18, v20, v28, v30, v38, v40, v48; + s32 out50[2]; + SV3_80178D40 v58, v60; + Actor_80178D40 *pv = &(*(Actor_80178D40*)&D_80126B58); + s32 i5b, i5c, fp5b, fp5c; + s32 *q5b, *q5c, *p5c, *r5c; + s16 *g = &D_80190458; + + switch (((Cmd_80178D40 *)arg1)->op) { + case 1: + func_80179B28(D_801902F0); + D_801902F0 = ((s32 (*)(s32, s32, s32))func_80137614)(((Cmd_80178D40 *)arg1)->a.w, D_801902FC, D_80190300 ? 0x48 : 0x40); + (*(s16*)&D_801904FC) = 2; + break; + case 0: + func_80179B28(D_801902F0); + D_801902F0 = ((s32 (*)(s32, s32, s32))func_80137614)(((Cmd_80178D40 *)arg1)->a.w, D_801902F4, D_801902F8 ? 0x48 : 0x40); + (*(s16*)&D_801904FC) = 1; + break; + case 0x45: + ((void (*)(s32))((Cmd_80178D40 *)arg1)->a.w)(((Actor_80178D40 *)arg0)); + if (D_801903A0 != 0) { + func_80179B28(D_801902F0); + D_801902F0 = ((s32 (*)(s32, s32, s32))func_80137614)(((Actor_80178D40 *)arg0)->unkDC[1], D_801902F4, D_801902F8 ? 0x48 : 0x40); + (*(s16*)&D_801904FC) = 1; + } else { + (*(s16*)&D_801904FC) = 3; + } + break; + case 0x32: + func_80179B28(D_801902F0); + D_801902F0 = ((s32 (*)(s32, s32, s32))func_80137614)(((Actor_80178D40 *)arg0)->unkDC[((Cmd_80178D40 *)arg1)->a.w], D_801902F4, + D_801902F8 ? 0x48 : 0x40); + (*(s16*)&D_801904FC) = 1; + break; + case 2: + func_80179B28(D_801902F0); + if (D_80190308 != 0) { + D_8018FED8 = D_80190308; + D_80190308 = 0; + (*(s16*)&D_801904FC) = 3; + return; + } + (*(s16*)&D_801904FC) = 6; + break; + case 6: + func_80179DF8(); + (*(s16*)&D_801904FC) = 3; + break; + case 3: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_80179D30(&v10); + (*(s16*)&D_801904FC) = 3; + break; + case 4: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0), &v10, &v18); + func_80179D30(&v18); + (*(s16*)&D_801904FC) = 3; + break; + case 0x4C: + func_80179D78((void *)((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x4D: + v10.vx = ((Blk_80178D40 *)((Cmd_80178D40 *)arg1)->a.p)->f0; + v10.vy = 0; + v10.vz = ((Blk_80178D40 *)((Cmd_80178D40 *)arg1)->a.p)->f4; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0), &v10, &v18); + v18.pad = ((Blk_80178D40 *)((Cmd_80178D40 *)arg1)->a.p)->f6; + func_80179D78(&v18); + (*(s16*)&D_801904FC) = 3; + break; + case 0x15: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0)->unkD4, &v10, &v18); + func_80179D30(&v18); + (*(s16*)&D_801904FC) = 3; + break; + case 5: + func_80179DCC(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801904FC) = 3; + break; + case 7: + func_80179E1C(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801904FC) = 3; + break; + case 8: + func_80179E74(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801904FC) = 3; + break; + case 9: + v10.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v10.vy = 0; + v10.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + func_80179EA0(&v10); + (*(s16*)&D_801904FC) = 3; + break; + case 0xA: + v10.vx = ((Actor_80178D40 *)arg0)->unk6; + v10.vy = ((Actor_80178D40 *)arg0)->unkA; + v10.vz = ((Actor_80178D40 *)arg0)->unkE; + func_80179EA0(&v10); + (*(s16*)&D_801904FC) = 3; + break; + case 0x16: { + Actor_80178D40 *p = ((Actor_80178D40 *)arg0)->unkD4; + v10.vx = p->unk6; + v10.vy = p->unkA; + v10.vz = p->unkE; + func_80179EA0(&v10); + (*(s16*)&D_801904FC) = 3; + break; + } + case 0xB: + func_8017A0F4(); + (*(s16*)&D_801904FC) = 3; + break; + case 0xC: + func_8017A11C(); + (*(s16*)&D_801904FC) = 3; + break; + case 0xD: + func_8017A180(); + (*(s16*)&D_801904FC) = 3; + break; + case 0xE: + func_8017A1A8(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x10: + func_8017A1D0(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x46: + func_8017A1F8(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x59: + func_8017A220(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x5A: + func_8017A248(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x49: + func_8017A144(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x47: + func_8017A270(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x17: + func_80179EE8(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801904FC) = 3; + break; + case 0x18: + func_80179F14(((Cmd_80178D40 *)arg1)->a.h[0], ((Cmd_80178D40 *)arg1)->a.h[1]); + (*(s16*)&D_801904FC) = 3; + break; + case 0x19: + func_80179F6C(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801904FC) = 3; + break; + case 0x1A: + func_80179F98(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x51: + func_8017A040(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x1B: + D_80190328 = ((Cmd_80178D40 *)arg1)->a.w; + func_80179F44(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x1C: + func_8017A338(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x52: + func_8017A360(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x1D: + func_8017A388(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x3B: + func_8017A094(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x3C: + func_8017A0C4(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0xF: + case 0x3F: + (*(s16*)&D_801904FC) = 4; + D_8018FEDC = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x3E: + (*(s16*)&D_801904FC) = 5; + D_8019031C = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x40: + D_8019031C = (s32)func_8017A3B0; + (*(s16*)&D_801904FC) = 5; + break; + case 0x23: + ((void (*)(void *, s32))func_8012A828)(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x31: + ((void (*)(void *, s32))func_8012A828)(((Actor_80178D40 *)arg0), ((Actor_80178D40 *)arg0)->unkDC[((Cmd_80178D40 *)arg1)->a.w]); + (*(s16*)&D_801904FC) = 3; + break; + case 0x24: + (*(s16*)&D_801904FC) = 3; + ((Actor_80178D40 *)arg0)->unk20->unk12 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x25: + g[0] = 1; + g[2] = ((Actor_80178D40 *)arg0)->unk20->unk12 + ((Cmd_80178D40 *)arg1)->a.uh[0]; + g[1] = 0x1E; + (*(s16*)&D_801904FC) = 3; + g[3] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x48: + g[0] = 1; + g[2] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + g[1] = 0x1E; + (*(s16*)&D_801904FC) = 3; + g[3] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x26: + g[0] = 1; + g[2] = ((s32 (*)(void *))func_8012B8A4)(((Actor_80178D40 *)arg0)); + g[1] = 0x1E; + (*(s16*)&D_801904FC) = 3; + g[3] = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x3D: + ((void(*)(void *, s32))func_8012E8E0)(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x27: + g[0] = 2; + g[4] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + (*(s16*)&D_801904FC) = 3; + g[1] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x4F: + g[5] = 1; + g[0] = 3; + g[6] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + (*(s16*)&D_801904FC) = 3; + g[7] = ((Actor_80178D40 *)arg0)->unkA; + g[8] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + g[1] = 0x10; + g[3] = 4; + /* fallthrough */ + case 0x28: + g[5] = 0; + g[0] = 3; + g[6] = ((Cmd_80178D40 *)arg1)->a.uh[0]; + (*(s16*)&D_801904FC) = 3; + g[7] = ((Actor_80178D40 *)arg0)->unkA; + g[8] = ((Cmd_80178D40 *)arg1)->a.uh[1]; + g[1] = 0x10; + g[3] = 4; + break; + case 0x29: + v20.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v20.vy = ((Actor_80178D40 *)arg0)->unkA; + v20.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0), &v20, &v28); + g[5] = 0; + g[0] = 3; + *(SV3_80178D40 *)(g + 6) = v28; + g[1] = 0x10; + g[3] = 4; + (*(s16*)&D_801904FC) = 3; + break; + case 0x50: + v30.vx = ((Cmd_80178D40 *)arg1)->a.uh[0]; + v30.vy = ((Actor_80178D40 *)arg0)->unkA; + v30.vz = ((Cmd_80178D40 *)arg1)->a.uh[1]; + ((void (*)(void *, void *, void *))func_8012F214)(((Actor_80178D40 *)arg0), &v30, &v38); + g[5] = 1; + g[0] = 3; + *(SV3_80178D40 *)(g + 6) = v38; + g[1] = 0x10; + g[3] = 4; + (*(s16*)&D_801904FC) = 3; + break; + case 0x2A: + g[0] = 4; + (*(s16*)&D_801904FC) = 3; + g[1] = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x1E: + func_8017B238(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x21: + func_8017BA3C(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B238(((Actor_80178D40 *)arg0), (s32)&D_8019030C); + (*(s16*)&D_801904FC) = 3; + break; + case 0x54: + func_8017BB34(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B238(((Actor_80178D40 *)arg0), (s32)&D_8019030C); + (*(s16*)&D_801904FC) = 3; + break; + case 0x1F: + func_8017B614(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x22: + func_8017BA3C(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B614(((Actor_80178D40 *)arg0), (s32)&D_8019030C); + (*(s16*)&D_801904FC) = 3; + break; + case 0x55: + func_8017BB34(((Actor_80178D40 *)arg0), ((Cmd_80178D40 *)arg1)->a.w); + func_8017B614(((Actor_80178D40 *)arg0), (s32)&D_8019030C); + (*(s16*)&D_801904FC) = 3; + break; + case 0x20: + func_8017B7A8(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801904FC) = 3; + break; + case 0x4E: + D_80190330 = ((Cmd_80178D40 *)arg1)->a.w; + func_8017B940(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801904FC) = 3; + break; + case 0x57: + func_8017B824(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x58: + func_8017B880(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x2B: + (*(s16*)&D_801904FC) = 3; + ((Actor_80178D40 *)arg0)->unk2 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2C: + (*(s16*)&D_801904FC) = 3; + ((Actor_80178D40 *)arg0)->unk34 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2D: + (*(s16*)&D_801904FC) = 3; + ((Actor_80178D40 *)arg0)->unkD8 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2F: + (*(s16*)&D_801904FC) = 3; + ((Actor_80178D40 *)arg0)->unk10A = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x2E: + (*(s16*)&D_801904FC) = 3; + ((Actor_80178D40 *)arg0)->unkF8 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x11: + func_8017A298(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x12: + func_8017A2C0(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x13: + func_8017A2E8(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x14: + func_8017A310(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x33: { + void (*f)(Actor_80178D40 *) = (void (*)(Actor_80178D40 *))((Cmd_80178D40 *)arg1)->a.w; + D_80190484 = (s32)&((Cmd_80178D40 *)arg1)[1]; + f(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801904FC) = 3; + break; + } + case 0x30: + if (((Cmd_80178D40 *)arg1)->a.w == 0) { + ((void (*)(void *))func_8012E8A8)(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801904FC) = 3; + } else { + ((void (*)(void *))func_8012E88C)(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801904FC) = 3; + } + break; + case 0x4A: + ((void(*)())func_80175414)(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x4B: + func_80175454(); + (*(s16*)&D_801904FC) = 3; + break; + case 0x34: + (*(s16*)&D_801904FC) = 3; + D_8018FED8 = ((Cmd_80178D40 *)arg1)->a.w; + return; + case 0x35: + D_80190308 = (s32)&((Cmd_80178D40 *)arg1)[1]; + (*(s16*)&D_801904FC) = 3; + D_8018FED8 = ((Cmd_80178D40 *)arg1)->a.w; + return; + case 0x36: + (*(s16*)&D_801904FC) = 3; + D_8018FED8 += 8; + if (((s32 (*)(s32))((Cmd_80178D40 *)arg1)->a.w)(((Actor_80178D40 *)arg0)) == 0) { + break; + } + D_8018FED8 = *(s32 *)(D_8018FED8 + 4); + return; + case 0x37: + (*(s16*)&D_801904FC) = 3; + D_801902F4 = ((Cmd_80178D40 *)arg1)->a.uh[0]; + D_801902F8 = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x38: + (*(s16*)&D_801904FC) = 3; + D_801902FC = ((Cmd_80178D40 *)arg1)->a.uh[0]; + D_80190300 = ((Cmd_80178D40 *)arg1)->a.uh[1]; + break; + case 0x39: { + s32 w1, w2; + v40.vx = ((Actor_80178D40 *)arg0)->unk6; + v40.vy = ((Actor_80178D40 *)arg0)->unkA; + v40.vz = ((Actor_80178D40 *)arg0)->unkE; + v48.vx = pv->unk6; + v48.vy = pv->unkA; + v48.vz = pv->unkE; + func_8012F40C(out50, &v40); + w1 = out50[0]; + func_8012F40C(out50, &v48); + w2 = out50[0]; + (*(s16*)&D_801904FC) = 3; + D_801902F4 = w1; + D_801902F8 = (s16)w1 >= (s16)w2; + break; + } + case 0x3A: { + s32 w1, w2; + v58.vx = ((Actor_80178D40 *)arg0)->unk6; + v58.vy = ((Actor_80178D40 *)arg0)->unkA; + v58.vz = ((Actor_80178D40 *)arg0)->unkE; + v60.vx = pv->unk6; + v60.vy = pv->unkA; + v60.vz = pv->unkE; + func_8012F40C(out50, &v58); + w1 = out50[0]; + func_8012F40C(out50, &v60); + w2 = out50[0]; + (*(s16*)&D_801904FC) = 3; + D_801902FC = w2; + D_80190300 = (s16)w1 < (s16)w2; + break; + } + case 0x41: + ((void(*)(s32, s32))func_8002D4C8)(((Cmd_80178D40 *)arg1)->a.uh[0], ((Cmd_80178D40 *)arg1)->a.uh[1]); + (*(s16*)&D_801904FC) = 3; + break; + case 0x42: + func_8017AD0C(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + case 0x43: + D_8019031C = (s32)func_8017A3D8; + D_80190324 = 0; + (*(s16*)&D_801904FC) = 5; + D_80190320 = ((Cmd_80178D40 *)arg1)->a.w; + break; + case 0x44: + func_8001AAD0(((Cmd_80178D40 *)arg1)->a.h[0], ((Cmd_80178D40 *)arg1)->a.h[1]); + (*(s16*)&D_801904FC) = 3; + break; + case 0x53: + func_80179E48(((Cmd_80178D40 *)arg1)->a.h[0]); + (*(s16*)&D_801904FC) = 3; + break; + case 0x56: + func_80179FEC(((Cmd_80178D40 *)arg1)->a.w); + (*(s16*)&D_801904FC) = 3; + break; + L5B_found: + fp5b = ((Cmd_80178D40 *)arg1)->a.w; + *q5b = fp5b; + ((void (*)(Actor_80178D40 *))fp5b)(((Actor_80178D40 *)arg0)); + (*(s16*)&D_801904FC) = 3; + break; + case 0x5B: + i5b = 0; + q5b = D_80190334; + do { + i5b++; + if (*q5b == 0) { + goto L5B_found; + } + q5b++; + } while (i5b < 10); + (*(s16*)&D_801904FC) = 3; + break; + L5C_found1: + *q5c = 0; + goto L5C_join; + case 0x5C: + i5c = 0; + if (((Cmd_80178D40 *)arg1)->a.w != 0) { + fp5c = ((Cmd_80178D40 *)arg1)->a.w; + q5c = D_80190334; + do { + if (*q5c == fp5c) { + goto L5C_found1; + } + i5c++; + q5c++; + } while (i5c < 10); + L5C_join: + if (i5c != 10) { + (*(s16*)&D_801904FC) = 3; + break; + } + i5c = 0; + do { + p5c = &D_80190334[i5c]; + if (*p5c != 0) { + goto L5C_found2; + } + i5c++; + } while (i5c < 10); + (*(s16*)&D_801904FC) = 3; + break; + L5C_found2: + *p5c = 0; + goto L5D; + } + r5c = D_80190334; + do { + i5c++; + if (*r5c != 0) { + *r5c = 0; + goto L5D; + } + r5c++; + } while (i5c < 10); + /* fallthrough */ + case 0x5D: + L5D: + (*(s16*)&D_801904FC) = 3; + break; + default: + break; + } +Lend: + D_8018FED8 += 8; +} DEFINE_func_80179B28() /* dedup: shared engine-core @0x80179b28 (src/shared) */