From a1221881a00682dd58339ff5fd38bc68fefdec26 Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Tue, 11 Aug 2026 15:50:47 -0600 Subject: [PATCH] =?UTF-8?q?feat(phase-30=20S48-0b):=20jtbl=20family=20func?= =?UTF-8?q?=5F80135D20=20=E2=80=94=203/3=20blocked-binary=20siblings=20ban?= =?UTF-8?q?ked?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/overlays.mk | 3 + config/splat.ov_MAIN_012.yaml | 2 +- config/splat.ov_SC02_037.yaml | 2 +- config/splat.ov_SC03_107.yaml | 2 +- src/ov_MAIN_012/ov_MAIN_012_jr_80135A4C.c | 108 +++++++++++++++++++++- src/ov_SC02_037/ov_SC02_037_jr_80135A4C.c | 108 +++++++++++++++++++++- src/ov_SC03_107/ov_SC03_107_jr_80135A4C.c | 108 +++++++++++++++++++++- 7 files changed, 327 insertions(+), 6 deletions(-) diff --git a/config/overlays.mk b/config/overlays.mk index 21721dfa3..c2cb27fa7 100644 --- a/config/overlays.mk +++ b/config/overlays.mk @@ -4918,6 +4918,7 @@ ov_MAIN_012_SPLAT_YAML := config/splat.ov_MAIN_012.yaml ov_MAIN_012_JTBL_INTERLEAVE := --order tail.data.o,ov_MAIN_012.o,tail2.data.o,ov_MAIN_012_jr_80131340.o,tail3.data.o,ov_MAIN_012_jr_80135A4C.o,tail4.data.o,ov_MAIN_012_jr_80135EB0.o,tail5.data.o,ov_MAIN_012_jr_801380E0.o,tail6.data.o,ov_MAIN_012_jr_8013F350.o,tail7.data.o,ov_MAIN_012_jr_801555F4.o,tail8.data.o,ov_MAIN_012_jr_80159C84.o,tail9.data.o,ov_MAIN_012_jr_8015A3C8.o,tail10.data.o,ov_MAIN_012_jr_801789AC.o,tail11.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_MAIN_012/ov_MAIN_012.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_MAIN_012/ov_MAIN_012_jr_80131340.o: JTBL_PADS := 0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14,+0x2c +build/src/ov_MAIN_012/ov_MAIN_012_jr_80135A4C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 build/src/ov_MAIN_012/ov_MAIN_012_jr_8013F350.o: JTBL_PADS := 0,0,4,0,4,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20,+0x38,+0x58,+0x70,+0x90,+0xa8 build/src/ov_MAIN_012/ov_MAIN_012_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_MAIN_012/ov_MAIN_012_jr_801789AC.o: JTBL_PADS := 0,0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18,+0x190,+0x220 @@ -4945,6 +4946,7 @@ ov_SC02_037_SPLAT_YAML := config/splat.ov_SC02_037.yaml ov_SC02_037_JTBL_INTERLEAVE := --order tail.data.o,ov_SC02_037.o,tail2.data.o,ov_SC02_037_jr_80131340.o,tail3.data.o,ov_SC02_037_jr_80135A4C.o,tail4.data.o,ov_SC02_037_jr_80135EB0.o,tail5.data.o,ov_SC02_037_jr_801380E0.o,tail6.data.o,ov_SC02_037_jr_8013F350.o,tail7.data.o,ov_SC02_037_jr_801555F4.o,tail8.data.o,ov_SC02_037_jr_80159C84.o,tail9.data.o,ov_SC02_037_jr_8015A3C8.o,tail10.data.o,ov_SC02_037_jr_801789AC.o,tail11.data.o,ov_SC02_037_jr_8017AE2C.o,tail12.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_SC02_037/ov_SC02_037.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC02_037/ov_SC02_037_jr_80131340.o: JTBL_PADS := 0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14,+0x2c +build/src/ov_SC02_037/ov_SC02_037_jr_80135A4C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 build/src/ov_SC02_037/ov_SC02_037_jr_8013F350.o: JTBL_PADS := 0,0,4,0,4,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20,+0x38,+0x58,+0x70,+0x90,+0xa8 build/src/ov_SC02_037/ov_SC02_037_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC02_037/ov_SC02_037_jr_8015A3C8.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20,+0x40,+0x60 @@ -4973,6 +4975,7 @@ ov_SC03_107_SPLAT_YAML := config/splat.ov_SC03_107.yaml ov_SC03_107_JTBL_INTERLEAVE := --order tail.data.o,ov_SC03_107.o,tail2.data.o,ov_SC03_107_jr_80131340.o,tail3.data.o,ov_SC03_107_jr_80135A4C.o,tail4.data.o,ov_SC03_107_jr_80135EB0.o,tail5.data.o,ov_SC03_107_jr_801380E0.o,tail6.data.o,ov_SC03_107_jr_8013F350.o,tail7.data.o,ov_SC03_107_jr_801555F4.o,tail8.data.o,ov_SC03_107_jr_80159C84.o,tail9.data.o,ov_SC03_107_jr_8015A3C8.o,tail10.data.o,ov_SC03_107_jr_801789AC.o,tail11.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_SC03_107/ov_SC03_107.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC03_107/ov_SC03_107_jr_80131340.o: JTBL_PADS := 0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14,+0x2c +build/src/ov_SC03_107/ov_SC03_107_jr_80135A4C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 build/src/ov_SC03_107/ov_SC03_107_jr_8013F350.o: JTBL_PADS := 0,0,4,0,4,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20,+0x38,+0x58,+0x70,+0x90,+0xa8 build/src/ov_SC03_107/ov_SC03_107_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC03_107/ov_SC03_107_jr_801789AC.o: JTBL_PADS := 0,0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18,+0x190,+0x220 diff --git a/config/splat.ov_MAIN_012.yaml b/config/splat.ov_MAIN_012.yaml index 9e703f445..05e9ea452 100644 --- a/config/splat.ov_MAIN_012.yaml +++ b/config/splat.ov_MAIN_012.yaml @@ -109,7 +109,7 @@ segments: - [0x5ad78, .rodata, ov_MAIN_012_jr_80131340] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x5adb8, data, tail3] - [0x5adbc, .rodata, ov_MAIN_012_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x5add0, data, tail4] + - [0x5ade8, data, tail4] - [0x5adec, .rodata, ov_MAIN_012_jr_80135EB0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x5ae18, data, tail5] - [0x5ae24, .rodata, ov_MAIN_012_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) diff --git a/config/splat.ov_SC02_037.yaml b/config/splat.ov_SC02_037.yaml index b3a46d4a4..9c56a3851 100644 --- a/config/splat.ov_SC02_037.yaml +++ b/config/splat.ov_SC02_037.yaml @@ -110,7 +110,7 @@ segments: - [0x9f25c, .rodata, ov_SC02_037_jr_80131340] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x9f29c, data, tail3] - [0x9f2a0, .rodata, ov_SC02_037_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x9f2b4, data, tail4] + - [0x9f2cc, data, tail4] - [0x9f2d0, .rodata, ov_SC02_037_jr_80135EB0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x9f2fc, data, tail5] - [0x9f308, .rodata, ov_SC02_037_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) diff --git a/config/splat.ov_SC03_107.yaml b/config/splat.ov_SC03_107.yaml index 9d08c9fcb..569a6a9f4 100644 --- a/config/splat.ov_SC03_107.yaml +++ b/config/splat.ov_SC03_107.yaml @@ -109,7 +109,7 @@ segments: - [0x71590, .rodata, ov_SC03_107_jr_80131340] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x715d0, data, tail3] - [0x715d4, .rodata, ov_SC03_107_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x715e8, data, tail4] + - [0x71600, data, tail4] - [0x71604, .rodata, ov_SC03_107_jr_80135EB0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x71630, data, tail5] - [0x7163c, .rodata, ov_SC03_107_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) diff --git a/src/ov_MAIN_012/ov_MAIN_012_jr_80135A4C.c b/src/ov_MAIN_012/ov_MAIN_012_jr_80135A4C.c index d3abc1006..360a22a58 100644 --- a/src/ov_MAIN_012/ov_MAIN_012_jr_80135A4C.c +++ b/src/ov_MAIN_012/ov_MAIN_012_jr_80135A4C.c @@ -716,5 +716,111 @@ out: return 0; } -INCLUDE_ASM("asm/ov_MAIN_012/nonmatchings/ov_MAIN_012_jr_80135A4C", func_80135D20); + + + +// @class: regalloc-order +// @stuck: none — MATCH (match_one 100/100 + rtu_match real-TU); needs the PAIRED //@EDIT on ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(return s16->s32 + `s32 result;`->`s16 result;`, whole-TU byte-neutral, verified) + one $s1 pin on `flag` +//@EDIT s16 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4)||s32 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4) +//@EDIT s32 result;|| s16 result; + +/* func_80135D20 — "is visible/hittable from " gate (100 ins, ov_SC06_018 jr_8012ACE0). + * + * Builds a second probe point 0x300 above the caller's point on the stack, asks func_80135480 to + * cull/transform it, then dispatches on that result (jtbl_801D2A90, cases 0..4; default falls + * through with p/flag/q UNINITIALISED — reproduced by leaving the switch without a default). + * + * Load-bearing details (do not "clean up"): + * - `u8 dead[96];` is a DEAD aggregate whose only job is the frame layout: it forces the probe + * buffer to sp+0x70 and the frame to 0x98 (gcc-2.7.2 assign_stack_local runs at expand time, so + * an unreferenced aggregate still owns its slot). Remove it and every sp offset shifts by 0x60. + * - `__asm__ __volatile__("")` is the §5a CROSS-JUMP BARRIER: without it jump.c merges the peeled + * first func_80135EB0 probe into the list loop (100 ins -> 88). + * - the explicit goto layout (loop / hit / body / elsepath) reproduces the target's basic-block + * ORDER: the `hit` block sits physically between the loop test and the loop body. A structured + * while/do-while emits the inverted layout (-3 ins, 39 diffs). + * - `register s32 flag __asm__("$17")` is a §17 pin. WITHOUT it gcc ties `arg1`->$s1 / `flag`->$s2, + * the reverse of the target (12 diffs, everything else already byte-exact). Pin-free attempts + * (declaring `flag` before `p`; assigning `flag` first in every case body) were both tried and + * do NOT flip the tie-break. The pin's live range does cross calls, so prefer ×1 banking. + * - func_80135480 must be declared INT-returning here: the target does NOT re-extend the callee's + * result before the switch (`addu $v1,$v0,$zero` only), while an s16-returning prototype costs a + * `sll/sra 16` pair. The two //@EDIT lines flip the in-TU definition s16->s32 and narrow its local + * `result` to s16 instead — the narrowing simply moves from the return-type conversion to the + * assignment, so the WHOLE TU compiles byte-identically (objdump-diffed: only the filename line + * changes). Both edits are required; flipping the return type alone drops func_80135480's tail + * `sll/sra` and shortens it by one instruction. + */ +extern s16 func_80135480(void*, s32, s16*, s16*); +extern s32 func_80135EB0(void *arg0, s32 arg1_); +extern s32 func_801345F8(s32 arg); +extern s32 func_80136A94(s32 a0, s32 a1, s32 a2, s32 a3); +extern s32 D_80184134; +extern s32 D_80184154; + +s32 func_80135D20(s32 arg0, s32 arg1, u16 *arg2) +{ + u8 dead[96]; + u16 sp[3]; + s32 *p; + register s32 flag __asm__("$17"); + s32 q; + + sp[0] = arg2[0]; + sp[1] = arg2[1] + 0x300; + sp[2] = arg2[2]; + switch (((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)((void *)arg0, arg1, (s16 *)arg2, (s16 *)sp)) { + case 0: + return 0; + case 1: + q = arg0 + 0x34; + p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000); + flag = 0; + break; + case 2: + q = arg0 + 0x34; + p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000); + flag = 1; + break; + case 3: + q = arg0 + 0x34; + p = &D_80184154; + flag = 0; + break; + case 4: + q = (s32)&D_80184134; + p = &D_80184154; + flag = 1; + break; + } + if (arg1 >= 0) { + goto elsepath; + } + if (func_80135EB0(p, 0) != 0) { + goto hit; + } + p = (s32 *)*p; + if (p == NULL) { + return 0; + } + __asm__ __volatile__(""); +loop: + if (func_80135EB0(p, 0) == 0) { + goto body; + } +hit: + func_80136A94(flag, arg0, (s32)arg2, q); + return 1; +body: + p = (s32 *)*p; + if (p != NULL) { + goto loop; + } + return 0; +elsepath: + if (func_801345F8(arg1) != 0) { + goto hit; + } + return 0; +} diff --git a/src/ov_SC02_037/ov_SC02_037_jr_80135A4C.c b/src/ov_SC02_037/ov_SC02_037_jr_80135A4C.c index 2d4066c8e..e1a7d0a1d 100644 --- a/src/ov_SC02_037/ov_SC02_037_jr_80135A4C.c +++ b/src/ov_SC02_037/ov_SC02_037_jr_80135A4C.c @@ -716,5 +716,111 @@ out: return 0; } -INCLUDE_ASM("asm/ov_SC02_037/nonmatchings/ov_SC02_037_jr_80135A4C", func_80135D20); + + + +// @class: regalloc-order +// @stuck: none — MATCH (match_one 100/100 + rtu_match real-TU); needs the PAIRED //@EDIT on ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(return s16->s32 + `s32 result;`->`s16 result;`, whole-TU byte-neutral, verified) + one $s1 pin on `flag` +//@EDIT s16 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4)||s32 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4) +//@EDIT s32 result;|| s16 result; + +/* func_80135D20 — "is visible/hittable from " gate (100 ins, ov_SC06_018 jr_8012ACE0). + * + * Builds a second probe point 0x300 above the caller's point on the stack, asks func_80135480 to + * cull/transform it, then dispatches on that result (jtbl_801D2A90, cases 0..4; default falls + * through with p/flag/q UNINITIALISED — reproduced by leaving the switch without a default). + * + * Load-bearing details (do not "clean up"): + * - `u8 dead[96];` is a DEAD aggregate whose only job is the frame layout: it forces the probe + * buffer to sp+0x70 and the frame to 0x98 (gcc-2.7.2 assign_stack_local runs at expand time, so + * an unreferenced aggregate still owns its slot). Remove it and every sp offset shifts by 0x60. + * - `__asm__ __volatile__("")` is the §5a CROSS-JUMP BARRIER: without it jump.c merges the peeled + * first func_80135EB0 probe into the list loop (100 ins -> 88). + * - the explicit goto layout (loop / hit / body / elsepath) reproduces the target's basic-block + * ORDER: the `hit` block sits physically between the loop test and the loop body. A structured + * while/do-while emits the inverted layout (-3 ins, 39 diffs). + * - `register s32 flag __asm__("$17")` is a §17 pin. WITHOUT it gcc ties `arg1`->$s1 / `flag`->$s2, + * the reverse of the target (12 diffs, everything else already byte-exact). Pin-free attempts + * (declaring `flag` before `p`; assigning `flag` first in every case body) were both tried and + * do NOT flip the tie-break. The pin's live range does cross calls, so prefer ×1 banking. + * - func_80135480 must be declared INT-returning here: the target does NOT re-extend the callee's + * result before the switch (`addu $v1,$v0,$zero` only), while an s16-returning prototype costs a + * `sll/sra 16` pair. The two //@EDIT lines flip the in-TU definition s16->s32 and narrow its local + * `result` to s16 instead — the narrowing simply moves from the return-type conversion to the + * assignment, so the WHOLE TU compiles byte-identically (objdump-diffed: only the filename line + * changes). Both edits are required; flipping the return type alone drops func_80135480's tail + * `sll/sra` and shortens it by one instruction. + */ +extern s16 func_80135480(void*, s32, s16*, s16*); +extern s32 func_80135EB0(void *arg0, s32 arg1_); +extern s32 func_801345F8(s32 arg); +extern s32 func_80136A94(s32 a0, s32 a1, s32 a2, s32 a3); +extern s32 D_801C842C; +extern s32 D_801C844C; + +s32 func_80135D20(s32 arg0, s32 arg1, u16 *arg2) +{ + u8 dead[96]; + u16 sp[3]; + s32 *p; + register s32 flag __asm__("$17"); + s32 q; + + sp[0] = arg2[0]; + sp[1] = arg2[1] + 0x300; + sp[2] = arg2[2]; + switch (((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)((void *)arg0, arg1, (s16 *)arg2, (s16 *)sp)) { + case 0: + return 0; + case 1: + q = arg0 + 0x34; + p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000); + flag = 0; + break; + case 2: + q = arg0 + 0x34; + p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000); + flag = 1; + break; + case 3: + q = arg0 + 0x34; + p = &D_801C844C; + flag = 0; + break; + case 4: + q = (s32)&D_801C842C; + p = &D_801C844C; + flag = 1; + break; + } + if (arg1 >= 0) { + goto elsepath; + } + if (func_80135EB0(p, 0) != 0) { + goto hit; + } + p = (s32 *)*p; + if (p == NULL) { + return 0; + } + __asm__ __volatile__(""); +loop: + if (func_80135EB0(p, 0) == 0) { + goto body; + } +hit: + func_80136A94(flag, arg0, (s32)arg2, q); + return 1; +body: + p = (s32 *)*p; + if (p != NULL) { + goto loop; + } + return 0; +elsepath: + if (func_801345F8(arg1) != 0) { + goto hit; + } + return 0; +} diff --git a/src/ov_SC03_107/ov_SC03_107_jr_80135A4C.c b/src/ov_SC03_107/ov_SC03_107_jr_80135A4C.c index 78e2f054c..105db22ca 100644 --- a/src/ov_SC03_107/ov_SC03_107_jr_80135A4C.c +++ b/src/ov_SC03_107/ov_SC03_107_jr_80135A4C.c @@ -717,5 +717,111 @@ out: return 0; } -INCLUDE_ASM("asm/ov_SC03_107/nonmatchings/ov_SC03_107_jr_80135A4C", func_80135D20); + + + +// @class: regalloc-order +// @stuck: none — MATCH (match_one 100/100 + rtu_match real-TU); needs the PAIRED //@EDIT on ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(return s16->s32 + `s32 result;`->`s16 result;`, whole-TU byte-neutral, verified) + one $s1 pin on `flag` +//@EDIT s16 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4)||s32 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4) +//@EDIT s32 result;|| s16 result; + +/* func_80135D20 — "is visible/hittable from " gate (100 ins, ov_SC06_018 jr_8012ACE0). + * + * Builds a second probe point 0x300 above the caller's point on the stack, asks func_80135480 to + * cull/transform it, then dispatches on that result (jtbl_801D2A90, cases 0..4; default falls + * through with p/flag/q UNINITIALISED — reproduced by leaving the switch without a default). + * + * Load-bearing details (do not "clean up"): + * - `u8 dead[96];` is a DEAD aggregate whose only job is the frame layout: it forces the probe + * buffer to sp+0x70 and the frame to 0x98 (gcc-2.7.2 assign_stack_local runs at expand time, so + * an unreferenced aggregate still owns its slot). Remove it and every sp offset shifts by 0x60. + * - `__asm__ __volatile__("")` is the §5a CROSS-JUMP BARRIER: without it jump.c merges the peeled + * first func_80135EB0 probe into the list loop (100 ins -> 88). + * - the explicit goto layout (loop / hit / body / elsepath) reproduces the target's basic-block + * ORDER: the `hit` block sits physically between the loop test and the loop body. A structured + * while/do-while emits the inverted layout (-3 ins, 39 diffs). + * - `register s32 flag __asm__("$17")` is a §17 pin. WITHOUT it gcc ties `arg1`->$s1 / `flag`->$s2, + * the reverse of the target (12 diffs, everything else already byte-exact). Pin-free attempts + * (declaring `flag` before `p`; assigning `flag` first in every case body) were both tried and + * do NOT flip the tie-break. The pin's live range does cross calls, so prefer ×1 banking. + * - func_80135480 must be declared INT-returning here: the target does NOT re-extend the callee's + * result before the switch (`addu $v1,$v0,$zero` only), while an s16-returning prototype costs a + * `sll/sra 16` pair. The two //@EDIT lines flip the in-TU definition s16->s32 and narrow its local + * `result` to s16 instead — the narrowing simply moves from the return-type conversion to the + * assignment, so the WHOLE TU compiles byte-identically (objdump-diffed: only the filename line + * changes). Both edits are required; flipping the return type alone drops func_80135480's tail + * `sll/sra` and shortens it by one instruction. + */ +extern s16 func_80135480(void*, s32, s16*, s16*); +extern s32 func_80135EB0(void *arg0, s32 arg1_); +extern s32 func_801345F8(s32 arg); +extern s32 func_80136A94(s32 a0, s32 a1, s32 a2, s32 a3); +extern s32 D_8019A78C; +extern s32 D_8019A7AC; + +s32 func_80135D20(s32 arg0, s32 arg1, u16 *arg2) +{ + u8 dead[96]; + u16 sp[3]; + s32 *p; + register s32 flag __asm__("$17"); + s32 q; + + sp[0] = arg2[0]; + sp[1] = arg2[1] + 0x300; + sp[2] = arg2[2]; + switch (((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)((void *)arg0, arg1, (s16 *)arg2, (s16 *)sp)) { + case 0: + return 0; + case 1: + q = arg0 + 0x34; + p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000); + flag = 0; + break; + case 2: + q = arg0 + 0x34; + p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000); + flag = 1; + break; + case 3: + q = arg0 + 0x34; + p = &D_8019A7AC; + flag = 0; + break; + case 4: + q = (s32)&D_8019A78C; + p = &D_8019A7AC; + flag = 1; + break; + } + if (arg1 >= 0) { + goto elsepath; + } + if (func_80135EB0(p, 0) != 0) { + goto hit; + } + p = (s32 *)*p; + if (p == NULL) { + return 0; + } + __asm__ __volatile__(""); +loop: + if (func_80135EB0(p, 0) == 0) { + goto body; + } +hit: + func_80136A94(flag, arg0, (s32)arg2, q); + return 1; +body: + p = (s32 *)*p; + if (p != NULL) { + goto loop; + } + return 0; +elsepath: + if (func_801345F8(arg1) != 0) { + goto hit; + } + return 0; +}