diff --git a/src/md_SC07_004/md_SC07_004.c b/src/md_SC07_004/md_SC07_004.c index 302ff6a605..3892a02c06 100644 --- a/src/md_SC07_004/md_SC07_004.c +++ b/src/md_SC07_004/md_SC07_004.c @@ -1181,7 +1181,103 @@ void func_801A3744(s32 a0) { } -INCLUDE_ASM("asm/md_SC07_004/nonmatchings/md_SC07_004", func_801A3798); +#include "common.h" + +extern void func_801A395C(s32 a0, s32 a1); +extern void func_8013240C(s32 a0); +extern void func_8001C924(s32 a0, void *a1); +extern void func_8012A860(void *a0, int a1); +extern void func_801A3A6C(u8 *s0); +extern void func_8012B2CC(s32 a0); +extern void func_801A7D18(s32 arg0); +extern s32 func_801A8564(s32 a0); +extern void func_80132288(s32 *a0, s32 *a1, s32 a2); +extern void func_801292C8(u8 *a0); + +extern s32 D_801B6E94[0x11]; +extern u8 D_801EF9A8; +extern s32 D_801F8724; +extern s32 D_801F8730; +extern s32 D_801BC9EC; +extern s32 *D_801AFB7C[]; +extern u16 D_8019FF8A; + +/* Three zero-byte levers carry this body; all three are load-bearing (single-axis A/B'd): + * + * 1. `y = arg1 + zr` with `zr` pinned to $0 (§36 "$0-add opaque copy"). The target keeps + * TWO callee-saved registers holding arg1 ($s2 = the parameter home, $s1 = a copy born + * after the jal). A plain `y = arg1;` is head-promoted by cse.c make_regs_eqv and the + * copy vanishes (LENGTH-DRIFT -1, and $s0/$s1 instead of $s0/$s1/$s2). + * 2. The non-volatile re-tie `__asm__("" : "=r"(y) : "0"(y))` gives `y` a second RTL SET, + * which kills the sched1 birthing boost on the copy and emits it BEFORE the call's + * return-value copy — so dbr steals `addu $a0,$v0,$zero` for the bltz delay slot + * instead of the arg1 copy (§47-addendum / §34 reg_n_sets==2). + * 3. `goto ret0` instead of `return 0` after the func_80132288 tail. With an in-block + * `return 0` the tail block's rare_destination flips and reorg refuses to steal + * `addiu $v0,$zero,3` into the `bnez $v0` delay slot (an unfillable +1 nop). Routing + * the exit through one shared `ret0:` tail restores the fill (§16 / §3-B shared-ret0). + * + * `t <<= 16; v1 = t >> 16;` (rather than `v1 = (s16)t;`) makes the sll reuse $v0 in place, + * which is what stops dbr from sinking `sh $v0,0xE6($s0)` into the bltz delay slot. + */ +s32 func_801A3798(s32 s0, s32 arg1) { + s32 v0; + s32 v1; + s32 y; + s32 t; + s32 p; + u16 f9; + register s32 zr __asm__("$0"); + + v0 = ((s32 (*)(s32, s32))func_801A395C)(s0, (s16)(*(u16 *)(s0 + 0x100) - 0x240)); + y = arg1 + zr; + __asm__ ("" : "=r" (y) : "0" (y)); + v1 = *(s16 *)(s0 + 0xE6); + if (v1 >= 0) { + func_8013240C((s32)&D_801F8724); + if (D_801F8730 & 0x4000) { + t = *(u16 *)(s0 + 0xE6) - 1; + *(u16 *)(s0 + 0xE6) = t; + t <<= 16; + v1 = t >> 16; + if (v1 >= 0) { + if (v1 >= 3) { + if (v1 != 3) { + goto other; + } + func_8001C924(*(s32 *)(s0 + 0x20), &D_801BC9EC); + if (*(s32 *)(s0 + 0xD4) != 0) { + func_801A7D18(*(s32 *)(s0 + 0xD4)); + *(s32 *)(s0 + 0xD4) = 0; + } + func_801A3A6C((u8 *)s0); + *(u16 *)(s0 + 0x100) = 0; + func_8012B2CC(s0); + if ((arg1 << 16) != 0) { + *(s32 *)(s0 + 0xD4) = func_801A8564(s0); + } + } + func_80132288(&D_801F8724, D_801AFB7C[*(s16 *)(s0 + 0xE6)], D_801BC9EC); + goto ret0; + } + other: + func_8001C924(*(s32 *)(s0 + 0x20), D_801B6E94); + func_8012A860((void *)s0, (int)&D_801EF9A8); + if ((y << 16) != 0) { + f9 = D_8019FF8A & 0xFFF7; + p = *(s32 *)(s0 + 0xD4); + D_8019FF8A = f9; + if (p != 0) { + func_801292C8((u8 *)p); + } + } + } + ret0: + return 0; + } + return (*(s16 *)(s0 + 0x98) == 0) && (v0 != 0); +} + #include "common.h" diff --git a/src/ov_SC07_007/ov_SC07_007_jr_8017BEBC.c b/src/ov_SC07_007/ov_SC07_007_jr_8017BEBC.c index 5a3495ea37..4fd4325c2a 100644 --- a/src/ov_SC07_007/ov_SC07_007_jr_8017BEBC.c +++ b/src/ov_SC07_007/ov_SC07_007_jr_8017BEBC.c @@ -4430,7 +4430,112 @@ s32 func_8017DF74(s32 a0, s32 a1) } -INCLUDE_ASM("asm/ov_SC07_007/nonmatchings/ov_SC07_007_jr_8017BEBC", func_8017DFB8); +// @class: schedule +// @stuck: none — MATCH (110 ins) +// +// func_8017DFB8 — per-frame entity tick: bail out through func_800D1724 when the +// pad/state guard passes, otherwise dispatch through the D_801882B8 handler table and +// rebuild the three 16-byte light records at D_800A5E88[0..2] from three rotated copies +// of the D_80187C60 source vectors (func_800139C8 = "rotate SVECTOR by angle"). +// +// Guard shape copied verbatim from the already-banked twin func_8017D3EC +// (src/ov_SC07_009/ov_SC07_009_jr_8017AE2C.c:4092-4102) — same five tests, same +// literals; ours differs only in setting D_801C79CC and RETURNING from the arm. +// +// FOUR LOAD-BEARING LEVERS (do NOT "clean these up" — each was byte-measured): +// +// (1) §249 asm-INITIALISATION of the record base. `__asm__("la %0, D_800A5E88" : "=r"(p))` +// gives one pseudo whose single SET is ASM_OPERANDS, so it is never CONSTANT_P: no +// REG_EQUIV, update_equiv_regs' absolute fold stays blocked, and the three first-field +// stores keep the target's base-relative `sw $v0,0/0x10/0x20($s0)` form. A plain +// `s32 *p = &D_800A5E88;` const-folds the +0x10/+0x20 stores back to +// `lui $at; sw %lo(D_800A5E98)($at)` (+2 ins each) — measured, closeness 45. +// +// (2) §385 PRIORITY-DONOR inputs on that same asm. The `la` insn is dependence-free, so +// sched1 hoists it to the top of the block (it landed before the `jalr`, closeness 66). +// The dead `"r"(x0),"r"(y0),"r"(z0)` inputs release it only after the three `lh`s, and +// the dead `"r"(ab)` input additionally releases it after the next call's $a1 setup — +// which is what pulls `addu $a0,$s1,$zero` / `addiu $a1,$s2,0x8` ahead of the loads +// (target idx 59-60). Dropping just `"r"(ab)` costs 8 instructions of rotation. +// +// (3) $a0/$a1 PINS (aa/ab) give the second func_800139C8 call's argument copies a source +// statement — hence an early LUID and an addressable name for lever (2). The call's +// own copies degenerate to self-moves and are deleted, so this is zero bytes. +// +// (4) §385 donor asm for the pointer bump. `p += 0x20; func_80028620(2, p);` is folded by +// combine into a single `addiu $a1,$s0,0x20` (-1 ins); spelling the bump as a one- +// instruction asm keeps `addiu $s0,$s0,0x20` + `addu $a1,$s0,$zero`, and its dead +// `"r"(aa)` input orders it AFTER `addiu $a0,$zero,0x2` (target idx 99-100). +// The trailing zero-byte use-barrier keeps p live so the bump cannot be dead-coded. +#include "common.h" + +extern s32 func_80029178(s32 arg); +extern s32 func_8002AE60(void); +extern s32 func_80014C54(s32 a0, s32 a1, s32 a2); +extern s32 func_800CF8B4(); +extern void func_800D1724(s32 a0); +extern s16 func_8012A758(void); +extern void func_800139C8(s32 a0, void *a1, void *a2); +extern void func_80028620(s32, void *); +extern u8 D_80186964[]; +extern u8 D_80187C60[]; +extern void (*D_801882B8[])(void *); +extern s32 D_801C79CC; +extern s32 D_800A5E8C; +extern s32 D_800A5E90; +extern s32 D_800A5E9C; +extern s32 D_800A5EA0; +extern s32 D_800A5EAC; +extern s32 D_800A5EB0; + +void func_8017DFB8(void *a0) { + register u8 *p __asm__("$16"); + register u8 *tbl __asm__("$18"); + register s32 aa __asm__("$4"); + register u8 *ab __asm__("$5"); + s32 idx; + s16 v[3]; + s32 x0, y0, z0; + s32 x1, y1, z1; + s32 x2, y2, z2; + + p = (u8 *)a0; + if ((u8)func_80029178(0x123) != 0 && (s16)func_8002AE60() == 0 && + ((s16)func_80014C54(0, 0, 0x800) != 0 || (s16)func_80014C54(0, 0, 0x40) != 0) && + func_800CF8B4() != 0) { + D_801C79CC = 1; + func_800D1724((s32)D_80186964); + return; + } + D_801882B8[*(u16 *)(p + 2)](p); + idx = func_8012A758(); + tbl = D_80187C60; + func_800139C8(idx, tbl, v); + aa = idx; + ab = tbl + 8; + x0 = v[0]; y0 = v[1]; z0 = v[2]; + __asm__("la %0, D_800A5E88" : "=r"(p) : "r"(x0), "r"(y0), "r"(z0), "r"(ab)); + *(s32 *)p = x0; + D_800A5E8C = y0; + D_800A5E90 = z0; + func_800139C8(aa, ab, v); + x1 = v[0]; y1 = v[1]; z1 = v[2]; + *(s32 *)(p + 0x10) = x1; + D_800A5E9C = y1; + D_800A5EA0 = z1; + func_800139C8(idx, tbl + 0x10, v); + x2 = v[0]; y2 = v[1]; z2 = v[2]; + *(s32 *)(p + 0x20) = x2; + D_800A5EAC = y2; + D_800A5EB0 = z2; + func_80028620(0, p); + func_80028620(1, p + 0x10); + aa = 2; + __asm__("addiu %0,%1,0x20" : "=r"(p) : "0"(p), "r"(aa)); + func_80028620(aa, p); + __asm__("" : : "r"(p)); +} + #include "common.h"