diff --git a/.run/P36/agents/ov_SC02_017__func_8017F768/body.c b/.run/P36/agents/ov_SC02_017__func_8017F768/body.c new file mode 100644 index 0000000000..935c2bb911 --- /dev/null +++ b/.run/P36/agents/ov_SC02_017__func_8017F768/body.c @@ -0,0 +1,63 @@ +void func_8017F768(s32 a0) { + s16 dir; + s16 dist; + s32 angle; + s32 ret; + s16 pt[4]; + + if (func_80148800((s32 *)&D_80126B58) & 3) { + u8 t = (*(u8 *)(a0 + 5) + 1) & 1; + *(u8 *)(a0 + 5) = t; + *(s32 *)(a0 + 0x14) = D_8018E1E0[t]; + } + + pt[0] = D_80126940[0]; + pt[1] = 0; + pt[2] = D_80126940[2]; + + dist = func_80013294((void *)&D_8018E1D0, (void *)pt); + + if (dist < 0x200) { + dir = 0x800; + *(s16 *)(a0 + 0x20) = 0x71; + *(s16 *)(a0 + 0x22) = 0; + *(s16 *)(a0 + 0x24) = 0; + *(s16 *)(a0 + 0x2E) = 0; + *(s16 *)(a0 + 0x30) = -0xC0; + *(s16 *)(a0 + 0x32) = 0; + } else { + *(s16 *)(a0 + 0x22) = 0; + + angle = ratan2((s32)D_80126940[0] << 16, (s32)D_80126940[2] << 16) & 0xFFF; + dir = angle; + + *(s16 *)(a0 + 0x20) = 0x1C7; + *(s16 *)(a0 + 0x30) = -0x10; + *(s16 *)(a0 + 0x22) = 0; + *(s16 *)(a0 + 0x24) = 0; + *(s16 *)(a0 + 0x2E) = 0; + /* +0x32 is stored ONCE PER ARM and, in this arm, ABOVE the inner if + (§194-M: it lands in the bnez delay slot, so it dominates the branch + and is NOT executed on the dist >= 0x801 path). Writing it once after + the outer if/else is what cross_jump then folds to 112 instructions. */ + *(s16 *)(a0 + 0x32) = 0; + + if (dist >= 0x801) { + u16 tmp[4]; + tmp[0] = 0; + tmp[1] = D_80126942; + tmp[2] = 0x800; + + func_801898A4(angle, tmp, tmp); + + D_80126940[0] = (s16)tmp[0] >> 3; + D_80126942 = (s16)tmp[1] >> 3; + D_80126940[2] = (s16)tmp[2] >> 3; + } + } + + D_801274EA = dir; + ret = func_80012DBC((s32)D_801EF9F0, dir, 0x14, 1); + D_801EF9F0 = (s16)ret; + func_8017F92C(a0, (s16)ret, D_80126940); +} diff --git a/.run/P36/agents/ov_SC02_017__func_8017F768/mechanism.md b/.run/P36/agents/ov_SC02_017__func_8017F768/mechanism.md new file mode 100644 index 0000000000..ed154f1b70 --- /dev/null +++ b/.run/P36/agents/ov_SC02_017__func_8017F768/mechanism.md @@ -0,0 +1,45 @@ +# func_8017F768 — e9 (P36 T7 S104) — score 13 (sweep best 13) -> 0, ZERO levers (was: 2 NEEDED pins `$17`, `$4`) + +(a) Residual: COUNT-class 13, two defects. (1) The ratan2 angle: target `andi a0,v0,0xfff; move s1,a0` and the +`func_801898A4` call reads the live `a0`; lever-free `andi s2,v0,0xfff` and `move a0,s2` at the call (the angle and +the heading variable merged into one pseudo). (2) The heading (`0x800` / angle) and the distance swap `$s1`/`$s2`, and +`li s1,2048` sits in the `beqz` delay slot in the target but is hoisted above `jal func_80013294` in mine. + +(b) Pass/decision (dump-verified: `scratch/dumps_base`, `dumps_w1`, `dumps_x2`, `dumps_z4`; `tools/alloc_table.py`): + 1. cse, `make_regs_eqv` (cse.c:826-862) + the `(set REG0 REG1)` swap (cse.c:7440-7474): with `s32 s1; … s1 = angle;` + the copy is a same-mode REG copy, the longer-lived `s1` becomes the class head, the andi is rewritten to set `s1` + directly (`.cse` insn 147 `(set r74 (and r115 4095))`) and the call argument reads `s1` -> `move a0,s1`. + Declared `s16`, the copy is a truncation into a HImode pseudo (a SUBREG move, not a REG-REG copy of the same mode), + so cse makes no equivalence the SImode call argument can be canonicalised to: `angle` stays its own pseudo + (z4 table: r75 refs 3 live 13 "prefers a0"), global gives it `a0` and the copy stays -> the target's + `andi a0; move s1,a0`. (w1 alone: 13 -> 10.) + 2. sched1 hoists `s1 = 0x800` (set before the `if`) above `jal func_80013294` (`.sched` insn 88 above call_insn 81), + which lengthens the heading's live range: `allocno_compare` (global.c:594-610) then ranks it BELOW the distance + (w1: heading r74 4 refs / live 55 = 1454.5 < distance 3/20 = 1500 -> distance takes `$s1`). Set inside the first arm + instead, it cannot move above the branch; its live length drops to 47 (z4: 1702.1 > 1500 -> heading `$s1`, + distance `$s2`) and reorg fills the `beqz` delay slot with it from the fall-through thread — the target's + `beqz …; li s1,2048`. + +(c) Moves (joint — each alone fails: s16 width only = 10, 0x800-in-arm with s32 = 5): + - the heading local `s32 s1` -> `s16 dir` (it is only ever stored to an `s16` global and passed on); + - `s1 = 0x800;` moved from before the `if` into the `dist < 0x200` arm (the arm that keeps the default heading). + Byte-neutral readability (all at 0): `s0 = a0` param copy deleted (d24), `dist` declared `s16` (the `(s16)` cast on the + call result dropped), `D_801274EA = dir;` without the redundant cast, `s1/s2` renamed `dir/dist`. + +(d) GENERATOR PROPOSAL: when a variable is initialised to a constant BEFORE an if/else and reassigned in one arm only +(`v = K; if (c) {…} else {… v = x; …}`) and the residual has a callee-saved swap or the constant's `li` in the wrong +place, move `v = K;` into the other arm (it stops sched1 hoisting it across a call and shortens its live length); and +when a copy `v = t;` merges `t` into `v` (a `move aN,` at a call that reads `t`), narrow `v` to the width of +its consumers (s16/u16) so the copy becomes a SUBREG move cse does not unify. + +(e) Did not work: moving `s1 = angle;` later in the arm (v1/v3: 13; after the inner if, v2: 24); `s16`/`u16` on `angle` +or on `s2` alone (w3/w4/w5: 13); `u16 s1` = `s16 s1` (w2 10, x3 0 — either narrow width works; body uses `s16`, the +global's type). The sweep's R2/R7/R8/R9/R17/R18 moves all stayed at 13. + +(f) Method: the tree's lever comments were accurate about the SYMPTOM ("coalescing kills that copy unless the value is born +in $a0"; "`s1 = 0x800` floats out of the beqz delay slot") but both causes were upstream of allocation: the copy's +mode (cse) and the constant's position (sched1). METHOD's c4 row ("a copy deleted because two locals shared a WIDTH") +was the right row; the allocation table confirmed the second move's arithmetic in one run. + +(g) Structs: no. Both decisions are about scalar locals (a same-mode copy in cse, a constant set's placement in sched1); +the object `a0` (+0x05 u8, +0x14 s32, +0x20..+0x32 s16 fields) as a struct would change spelling only. diff --git a/.run/P36/agents/ov_SC02_017__func_8017FCFC/body.c b/.run/P36/agents/ov_SC02_017__func_8017FCFC/body.c new file mode 100644 index 0000000000..4c7eb3debe --- /dev/null +++ b/.run/P36/agents/ov_SC02_017__func_8017FCFC/body.c @@ -0,0 +1,36 @@ +void func_8017FCFC(void *a0) { + s32 k; + + if (*(s16 *)((s32)a0 + 0xFE) != 0) { + *(s16 *)((s32)a0 + 0xFE) -= 1; + return; + } + k = *(u16 *)((s32)a0 + 0x5C); + if ((k & 1) == 0) { + return; + } + *(u16 *)((s32)a0 + 0x5C) = k & 0xFFFE; + if ((func_800291B4(D_8018E204[*(u16 *)((s32)a0 + 0x70) & 0xF]) & 0xFF) != 0) { + *(u16 *)((s32)a0 + 0x5E) = 0; + *(s16 *)((s32)a0 + 0xFE) = 8; + return; + } + k = *(u16 *)((s32)a0 + 0x5E); + if (k == 0xC) { + *(s32 *)((s32)a0 + 0x58) = (s32)D_8018E1F4 | 0x40000000 | 0x20000000; + func_800291A0(D_8018E204[*(u16 *)((s32)a0 + 0x70) & 0xF], 1); + *(u16 *)((s32)a0 + 0x5C) = 0x8C00; + } else { + *(s16 *)((s32)a0 + 0xFE) = 8; + if (k != 0x1D && *(s32 *)((s32)a0 + 0xDC) == 0) { + *(s32 *)((s32)a0 + 0xDC) = 1; + func_801746DC(); + ((void (*)(void))func_80178BF8)(); + *(s16 *)((s32)a0 + 0x2) = 2; + func_8002D4C8(0x59D, 0); + *(u16 *)((s32)a0 + 0x5E) = 0; + return; + } + } + *(u16 *)((s32)a0 + 0x5E) = 0; +} diff --git a/.run/P36/agents/ov_SC02_017__func_8017FCFC/mechanism.md b/.run/P36/agents/ov_SC02_017__func_8017FCFC/mechanism.md new file mode 100644 index 0000000000..fbb2d52c29 --- /dev/null +++ b/.run/P36/agents/ov_SC02_017__func_8017FCFC/mechanism.md @@ -0,0 +1,55 @@ +# func_8017FCFC (ov_SC02_017) — e9 (P36 T7 S104) — score 10 (sweep best 2) -> 0, ZERO levers +(was: NEEDED pins `$3` + `$0` on `u = t + zr`, a NEEDED `launder` on `p`, and a `(void)&frame_pad` dead pad) + +(a) Residual: COUNT 79 vs 80, two independent defects. (1) The `+0xFE` countdown: target `lh v0; beqz; move v1,v0; +addiu v0,v1,-1; j; sh v0` — a copy the lever-free text folds (`beqz; addiu v0,v0,-1`). (2) The table base +`&D_8018E204` (held in `$s1` for the `k == 0xC` arm): target `lw a0,0(at); la s1,D_8018E204; jal func_800291B4; nop`, +lever-free `jal …; nop; andi v0,v0,0xff; la s1,…; beqz` (ORDER). + +(b) Pass/decision (dump-verified: `scratch/dumps_free`, `dumps_tree`, `dumps_c1`, `dumps_e1`, `.sched` ready-list traces): + 1. The countdown as a memory decrement `*(s16 *)(a0 + 0xFE) -= 1` of the value already tested: the test reads the + halfword sign-extended into an SImode pseudo (e1 `.lreg` insn 12, `extendhisi2`) and the decrement works on a + HImode copy of it (insn 13 `(set (reg:HI 74) (subreg:HI (reg:SI 75) 0))`) — a SUBREG move, which cse's + `(set REG0 REG1)` handling (cse.c:7440-7474, it wants same-mode REGs) does not fold: the target's `move v1,v0`. + The same text also brings a pseudo with no insns that reload gives a stack slot (e1 `.lreg` r76 "dies in 0 + places", reload1.c:2327-2352), so the 48-byte frame comes out without the tree's `(void)&frame_pad` pad. + 2. sched1's lifetime heuristic `adjust_priority` (sched.c:2507-2547) raises an insn to the block's max priority when + `birthing_insn_p` (sched.c:2469-2490) holds: a SET of a REG that is live after it with `reg_n_sets == 1`. The base + pseudo (`rN = D_8018E204`, which expand makes for the array index and cse1 extends into the `k == 0xC` arm) is + always birthing. The decompiler's `t` holds the call result AND the counter AND 8 AND 0x8C00 (`reg_n_sets > 1`), + so the call result's `andi` is not: at T-2 the ready list is `base-set (7f000001), andi (3)` (c1 `.sched`) and the + base set goes last, after the call. With the result tested inline (or in its own variable) the `andi` is + birthing too: `62 (7f000001) 69 (7f000001), now 69 62` (e1 `.sched`) — the `andi` takes T-2, the base set lands + before `jal` (as `la` it is two words and cannot fill the delay slot, so the `nop` stays). The tree's launder + faked exactly this by giving `p` a second set (`reg_n_sets == 2`, not birthing). + +(c) Moves (each closes its own defect; together 0): + - the countdown `t = *(s16 *)(a0+0xFE); if (t != 0) { u = t + 0; t = u - 1; store; }` -> `if (*(s16 *)(a0 + 0xFE) != 0) + { *(s16 *)(a0 + 0xFE) -= 1; return; }`, and the `frame_pad` local and its `(void)&` statement deleted + (b2n = 0 with the launder still in; with the pad kept the frame is 56); + - the call result tested inline: `if ((func_800291B4(D_8018E204[… & 0xF]) & 0xFF) != 0)` — no shared `t` + (d2 `s32 r` / d3 `u8 r` in their own variable also 0). + Byte-neutral cleanups (e1 = 0): `p` deleted (the arm indexes `D_8018E204` directly — cse1 makes the shared base + itself, c1), every `t = 8; store t` -> `store 8`, `t = 0x8C00` -> a direct store; `t`/`u` gone. + +(d) GENERATOR PROPOSAL: when a `launder` sits on a pointer/constant local whose only other set is `p = &GLOBAL` before a +call, and the residual is ORDER (the `la` after the call instead of before it), look for a variable REUSED for the +value tested right after that call (`t = f(…) & M; if (t …)` with other `t = …` sets) and give the call result its own +single-set name or test it inline — both insns then carry sched1's birthing boost and the tie goes to the test. +Also (R-new, "countdown"): `t = *(T *)(p+K); if (t) { u = t + 0; t = u - 1; *(T *)(p+K) = t; }` with a `$0` pin -> +`if (*(T *)(p+K) != 0) *(T *)(p+K) -= 1;` for a narrow `T`. + +(e) Did not work: counter spellings with the `frame_pad` kept (b2/b3/b6: 8, frame 56 vs 48); `t - 1`, `--t`, `u = t--`, +`u = t` copies (b1/b4/b5/b7: 6); `u16 u` (b8: 2, an `andi 0xffff` instead of the move); every `p` spelling without the +launder while `t` is shared: `p` kept (c0 4), no `p` (c1 4), first call through `p` (c2 4), `p` set after the call (c3 4), +a second `p = D_8018E204;` in the arm (c4/c5/c6 4 — cse removes the redundant set, so `reg_n_sets` stays 1). +`func_80178BF8();` without the `(void (*)(void))` cast: 4 (ORDER) — keep the cast. + +(f) Method: METHOD c4 ("a copy into HImode is a SUBREG move and survives") was the counter row. Nothing in METHOD covers +the second defect: `birthing_insn_p` is named only for the width of an incremented local (d8); here the fix was a +variable's SET COUNT on a DIFFERENT insn that competes for the same ready slot. The `.sched` ready-list lines +(`ready list at T-2: … (7f000001) … (3)`) were the deciding evidence; the allocation table was irrelevant (ORDER). +The frame pad was an unlisted lever (not in sites.txt). + +(g) Structs: no. Both decisions are about scalar locals (a HImode SUBREG copy; sched1's per-register set count); +the object's `u16 +0x5C/+0x5E/+0x70`, `s16 +0xFE`, `s32 +0x58/+0xDC` fields as a struct would change spelling only. diff --git a/.run/P36/agents/ov_SC02_017__func_8018209C/body.c b/.run/P36/agents/ov_SC02_017__func_8018209C/body.c new file mode 100644 index 0000000000..5a5139dc92 --- /dev/null +++ b/.run/P36/agents/ov_SC02_017__func_8018209C/body.c @@ -0,0 +1,47 @@ +s32 func_8018209C_impl(void *arg0) __asm__("func_8018209C"); + +s32 func_8018209C_impl(void *arg0) +{ + SV_8018209C vin; + SV_8018209C w; + RES_8018209C res; + s32 t; + + func_8012F214((s32)arg0, (s32)D_8018E56C, (s32)&vin); + gte_SetRotMatrix(&D_800AF648); + gte_SetTransMatrix(&D_800AF648); + gte_ldv0(&vin); + gte_rtps(); + gte_stsxy(&res.x); + gte_stflg(&res.flag); + if (res.flag & 0xFFFFEFFF) { + return 0; + } + t = res.x; + if (t < 0) { + t = -t; + } + if (t >= 0xAB || (res.y >= 0 ? res.y >= 0x83 : -res.y >= 0x83)) { + w.vx = *(u16 *)((s32)arg0 + 6); + w.vy = *(u16 *)((s32)arg0 + 0xA); + w.vz = *(u16 *)((s32)arg0 + 0xE); + gte_ldv0(&w); + gte_rtps(); + gte_stsxy(&res.x); + gte_stflg(&res.flag); + if (res.flag & 0xFFFFEFFF) { + return 0; + } + t = res.x; + if (t < 0) { + t = -t; + } + if (t >= 0x105 || (res.y >= 0 ? res.y >= 0x8D : -res.y >= 0x8D)) { + return 0; + } + } + if (func_80013478((s32)&D_80126B5C, (s32)&vin) <= 0x41010) { + func_8002D4C8(0xB67, 0); + } + return 1; +} diff --git a/.run/P36/agents/ov_SC02_017__func_8018209C/body_minlever_void.c b/.run/P36/agents/ov_SC02_017__func_8018209C/body_minlever_void.c new file mode 100644 index 0000000000..727512811d --- /dev/null +++ b/.run/P36/agents/ov_SC02_017__func_8018209C/body_minlever_void.c @@ -0,0 +1,51 @@ +void func_8018209C(void *arg0) +{ + SV_8018209C vin; + SV_8018209C w; + RES_8018209C res; + s32 t; + s32 rv; + + func_8012F214((s32)arg0, (s32)D_8018E56C, (s32)&vin); + gte_SetRotMatrix(&D_800AF648); + gte_SetTransMatrix(&D_800AF648); + gte_ldv0(&vin); + gte_rtps(); + gte_stsxy(&res.x); + gte_stflg(&res.flag); + if (res.flag & 0xFFFFEFFF) { + rv = 0; + goto out; + } + t = res.x; + if (t < 0) { + t = -t; + } + if (t >= 0xAB || (res.y >= 0 ? res.y >= 0x83 : -res.y >= 0x83)) { + w.vx = *(u16 *)((s32)arg0 + 6); + w.vy = *(u16 *)((s32)arg0 + 0xA); + w.vz = *(u16 *)((s32)arg0 + 0xE); + gte_ldv0(&w); + gte_rtps(); + gte_stsxy(&res.x); + gte_stflg(&res.flag); + if (res.flag & 0xFFFFEFFF) { + rv = 0; + goto out; + } + t = res.x; + if (t < 0) { + t = -t; + } + if (t >= 0x105 || (res.y >= 0 ? res.y >= 0x8D : -res.y >= 0x8D)) { + rv = 0; + goto out; + } + } + if (func_80013478((s32)&D_80126B5C, (s32)&vin) <= 0x41010) { + func_8002D4C8(0xB67, 0); + } + rv = 1; +out: + __asm__ __volatile__("" : : "r"(rv)); // !FAKE: keepalive — the s32 return value under the TU's void prototype (P36 S104 e9 minimum-lever) +} diff --git a/.run/P36/agents/ov_SC02_017__func_8018209C/mechanism.md b/.run/P36/agents/ov_SC02_017__func_8018209C/mechanism.md new file mode 100644 index 0000000000..bf04bd9354 --- /dev/null +++ b/.run/P36/agents/ov_SC02_017__func_8018209C/mechanism.md @@ -0,0 +1,55 @@ +# func_8018209C — e9 (P36 T7 S104) — score 29 (sweep best 29) -> 0, ZERO levers — a SIGNATURE change (returns s32) +(was: NEEDED `$7` pin on the matrix pointer `g`, a NEEDED end-of-function `keepalive` of `rv`, and a marked +"gte direct" asm with an extra `memory` clobber) + +(a) Residual: COUNT 122 vs 129 + `v0 -> a3` on the matrix pointer. Three defects: (1) the D_800AF648 pointer is in `v0`, +the target loads it into `a3`; (2) every early-exit branch lacks the target's `move v0,zero` in its delay slot and the +final `li v0,1`s are missing — the function RETURNS 0/1 in `v0`, which a `void` definition deletes; (3) the second +`|y| < 0x8D` sign-split test is merged into a conditional negate (-5 insns), exactly func_80181E98's residual. + +(b) Pass/decision (bytes + the siblings' dumps; this function is a near-twin of func_80181E98, closed by e7 this session): + 1. `gte_SetRotMatrix(&D_800AF648)` with the address passed DIRECTLY keeps the constant in the asm_operands + (stmt.c:1556-1569 — a `general_operand` constant is not forced into a register); reload loads it into a spill + register, `a3` here (the first call-used hard register no allocated pseudo uses — `order_regs_for_reload`, reload1.c:3690-3700; a0-a2 carry func_8012F214's arguments) — the + target. Through a variable (`g = &D_800AF648`) the operand is a pseudo that local-alloc puts in `v0`; the tree + pinned it to `$7`. (The inverse holds in func_80182FD0, whose target has `v0`: there a local pointer is right.) + 2. The `v0` stores are return values: with `s32` + `return 0;` / `return 1;` every exit sets `v0`; a `void` body has + no consumer and they are deleted (the tree's `__asm__("" : : "r"(rv))` kept them alive). + 3. Post-reload cross-jump (toplev.c:3142, `find_cross_jump` jump.c:2371): with a shared `rv = 0; goto out;` the + sign-split arms end identically and merge; one `if` with a ternary condition and an INLINE `return 0;` puts the + return block between arm 2 and the pass label (`do_jump` COND_EXPR, expr.c:9124-9150), so cross-jump fails on its + first comparison (jump.c:2469-2470) — see e7's func_80181E98 mechanism.md for the dump evidence; not re-dumped here. + +(c) Moves (e7's func_80181E98 body ported: D_8018E564 -> D_8018E56C, the tail `if (func_80013478(…) <= 0x41010) +func_8002D4C8(0xB67, 0); return 1;`, the tree's `SV_8018209C`/`RES_8018209C` locals kept): + - the hand-written GTE pair + `g` -> `gte_SetRotMatrix(&D_800AF648); gte_SetTransMatrix(&D_800AF648);`; + - the goto chain -> structured `if (t >= 0xAB || (res.y >= 0 ? res.y >= 0x83 : -res.y >= 0x83)) { …second + projection…; if (…) return 0; if (t >= 0x105 || (res.y >= 0 ? res.y >= 0x8D : -res.y >= 0x8D)) return 0; }`, + with `t = res.x; if (t < 0) t = -t;` for the x axis; + - `void` -> `s32` with inline `return 0;` / `return 1;`. + + DELIVERED THREE WAYS (all `--try` 0): + - `body.c` — ZERO levers, bankable WITHOUT a TU edit: `s32 func_8018209C_impl(void *arg0) __asm__("func_8018209C");` + + the definition under that name — the same declaration alias this TU already uses for func_80181E98 (`TU RECONCILE` + at ov_SC02_017_jr_8017DF34.c:5207); it sidesteps the file-scope `extern void func_8018209C(void *a0);` (TU:5146). + - `scratch/body_s32_plain.c` + `scratch/tu_s32.c` — the PARKED signature change proper: `s32 func_8018209C(void *arg0)` + with TU:5146 changed to `extern s32 func_8018209C(void *a0);` (whole-TU `--try`: func_8018209C 0 and its only + caller func_80181CF0 0). ov_SC02_017_jr_80186C64.c:2913/2923 carry the same stale `void` extern (another TU, no + bytes depend on it). + - `body_minlever_void.c` — the minimum-lever body under the current `void` prototype: 1 marked keepalive + (`// !FAKE: keepalive — the s32 return value under the TU's void prototype (P36 S104 e9 minimum-lever)`), 3 -> 1. + +(d) GENERATOR PROPOSAL: when a function's text is a near-copy of an already-closed sibling in the same TU (here: same +callees func_8012F214/func_80013478/func_8002D4C8, same GTE sequence, only a `D_` table and the tail differ), port the +sibling's closed body first (R27 "port" already does this across TUs; it should also take same-TU twins closed in the +current session); and a `keepalive` of a result variable at the end of a `void` function = an `s32` return. + +(e) Did not work / not tried: the sweep's 184 compiles all stayed at 29 (no generator changes the return type or the +goto structure). The `g` variable spelling (body_free) puts the pointer in `v0` — the residual's `v0 -> a3`; only the direct constant gives a3. + +(f) Method: METHOD d29 ("a `void` function whose last statement is a keepalive of `v0` RETURNS it") + S104 (d11) and e7's +inline-return finding covered it; the time went into noticing the twin. A same-TU "closed this session" list in the +pack (e7's mechanism.md paths were in my brief) is what made it a two-compile close. + +(g) Structs: no. The decisions are asm-operand expansion/reload (the matrix pointer), the return type, and block +layout/cross-jump; `res`/`vin`/`w` are already struct-typed locals. diff --git a/.run/P36/agents/ov_SC02_017__func_80182FD0/body.c b/.run/P36/agents/ov_SC02_017__func_80182FD0/body.c new file mode 100644 index 0000000000..c4f0019628 --- /dev/null +++ b/.run/P36/agents/ov_SC02_017__func_80182FD0/body.c @@ -0,0 +1,38 @@ +void func_80182FD0(int param) +{ + struct { + s16 v[4]; + s32 flag; + } w; + u8 *s0; + u8 *m = &D_800AF648; + s32 lim; + s32 lim2; + + s0 = ((u8 **)D_8018E8DC)[*(s16 *)(param + 0xFC)]; + + gte_SetRotMatrix(m); + gte_SetTransMatrix(m); + + func_80015978(param + 4, (s32 *)w.v); + gte_ldv0(w.v); + gte_rtps(); + gte_stsxy(w.v); + gte_stflg(&w.flag); + + lim = (D_800AF7BC >> 1) + 0x20; + if (w.v[0] > -lim && w.v[0] < lim) { + lim2 = (D_800AF7BE >> 1) + 0x20; + if (w.v[1] > -lim2 && w.v[1] < lim2 && w.flag >= 0) { + if (*(s32 *)(param + 0x1C) == 0) { + while (*(s16 *)(s0 + 6) != 0xFF) { + func_80183168((u8 *)param, s0); + s0 += 8; + } + *(s32 *)(param + 0x1C) = *(s32 *)(param + 0xDC); + } + *(s32 *)(param + 0x1C) -= 1; + } + } + func_801831FC(param); +} diff --git a/.run/P36/agents/ov_SC02_017__func_80182FD0/mechanism.md b/.run/P36/agents/ov_SC02_017__func_80182FD0/mechanism.md new file mode 100644 index 0000000000..bbc75a321c --- /dev/null +++ b/.run/P36/agents/ov_SC02_017__func_80182FD0/mechanism.md @@ -0,0 +1,53 @@ +# func_80182FD0 — e9 (P36 T7 S104) — score 10 (sweep best 2) -> 0, ZERO levers +(was: 2 NEEDED `keepalive`s + a NEEDED `volatile s32 *` cast + a REMOVED `$3` pin; ALSO gone: the hand-written GTE asm +with a hard-coded `lui $2,%hi(D_800AF648)` and the hand-merged `lwc2;lwc2;nop;nop;rtps;swc2` block — every GTE op is now +a Sony macro from include/gte_inline.h) + +(a) Residual: REG, a v1/a0 permutation in the two screen-bounds tests — the target keeps the projected coordinate `x` +in `v1` and the bound `lim` in `a0`; lever-free swaps them (counts equal, 102/102). + +(b) Pass/decision (dump-verified: `scratch/dumps_free`, `dumps_a2`, `dumps_a3`; `tools/alloc_table.py`): + 1. Both tests span a block boundary (the second `slt` sits after the first `beqz`), so `x` and `lim` are global + allocnos ranked by `allocno_compare` (global.c:594-610, priority = floor_log2(refs)·refs/live). The decompiler + REUSES `x` and `lim` for both axes: free r76 (`lim`) 6 refs / live 10 = 12000 > r75 (`x`) 6/14 = 8571 -> `lim` is + allocated first and takes `v1`. One bound per axis (`lim`, `lim2`): each 3 refs / live 5 = 6000 < `x` 8571 -> + `x` first -> `v1`, the bounds `a0` (a3 table). Splitting `x` instead (a2) leaves `lim` at 12000: 10. + 2. The `volatile` re-read of `+0x1C`: the countdown is `if (t == 0) { walk; t = reload; } t -= 1;` — the join block + re-reads `+0x1C` (the store in the zero arm is in another basic block, so cse does not forward it), and reorg + (`fill_slots_from_thread`, reorg.c:3270; `redundant_insn` skips the join's `lw` on the taken path, where `v0` + already holds it) steals the `addiu -1` into the `bnez` slot — the target's two decrements. Proven on bytes + (b1/b2/b3 = 0); the reorg reading is from the bytes' shape, not a `.dbr` dump. + 3. GTE setup: a Sony macro with a CONSTANT input `gte_SetRotMatrix(&D_800AF648)` keeps the constant in the + asm_operands (stmt.c:1556-1569: a `general_operand` constant is not forced into a register), so reload loads it + into a spill register (reload1.c:3690-3700, the first call-used hard reg no pseudo uses: a2 here, a3 in the siblings func_80181E98/func_8018209C, whose targets do use a3) and sched2 + hoists that `la` into the `lh` delay slot (s4: 12, COUNT 101). Through a local pointer `u8 *m = &D_800AF648;` the + operand is a pseudo, local-alloc gives it `v0` and the `la` stays right before the loads — the target. + +(c) Moves: + - one bound per axis: `lim2 = (D_800AF7BE >> 1) + 0x20;` for the second test (a3 = 0 alone — the two keepalives gone); + - the countdown `if (*(s32 *)(param + 0x1C) == 0) { …walk…; *(s32 *)(param + 0x1C) = *(s32 *)(param + 0xDC); } + *(s32 *)(param + 0x1C) -= 1;` (b1 = 0 — the `volatile` cast and the `v0`/`goto store` gone); + - the GTE asm -> `gte_SetRotMatrix(m); gte_SetTransMatrix(m);` with `u8 *m = &D_800AF648;` and + `gte_ldv0(w.v); gte_rtps(); gte_stsxy(w.v); gte_stflg(&w.flag);` (s6/s7/s8 = 0; `m` set before or after the + table read, or as an initialiser, all 0); + - readability (all 0): the goto chain -> nested `if`s with `&&` (s1), `buf[3]` -> `struct { s16 v[4]; s32 flag; } w` + (sibling func_80181E98's shape), `x` inlined as `w.v[0]` / `w.v[1]` (s2/s3), the walk as a `while`. + +(d) GENERATOR PROPOSAL: (1) when a keepalive/pin fixes a register swap between two locals that are REUSED across two +parallel statement groups (the same pair of names assigned again for the second axis), split the one with the higher +`allocno_compare` priority (or both) per group — R23 splits one variable at a time and must try each separately; +(2) when a body carries a hand-written GTE asm whose text loads a symbol into a fixed register (`lui $N,%hi(SYM)`), +replace it with the Sony macros fed by a LOCAL pointer (`T *m = &SYM;`) — a direct `&SYM` argument becomes a reload +register instead (try both: the siblings in this TU need the direct form, a3). + +(e) Did not work: splitting `x` only (a2: 10); macros with `&D_800AF648` passed directly (s4 12) or +`gte_SetRotTransMatrix(&D_800AF648)` (s5 12). The sweep's R7/R8/R9/R10/R18 moves reached 2 (COUNT) but none +touched the bound variable. + +(f) Method: METHOD S103 c1/c8 ("a local REUSED across statement groups … split it") was the row; the allocation table +named WHICH of the two to split in one run. The tree's lever note ("a HARD register that DIES in an insn becomes +local-alloc's suggestion") explained the keepalive, not the swap — the swap was a priority tie-break the pin papered over. +The GTE-macro point came from comparing this TU's three GTE users' targets (a3 vs v0 for the matrix pointer). + +(g) Structs: no for the lever (the decision is allocation priority of two scalar locals). The `buf` -> struct `w` +rewrite is byte-neutral here (the GTE macros take the addresses; no aggregate-vs-scalar aliasing decision involved). diff --git a/.run/P36/delever/calibration.json b/.run/P36/delever/calibration.json index 39d8c5e7ad..83e770d865 100644 --- a/.run/P36/delever/calibration.json +++ b/.run/P36/delever/calibration.json @@ -1,7 +1,7 @@ { - "head": "e36b612f4", + "head": "5a4a7eed0", "stamp": "15956e4a96c4", - "generated": "2026-09-11 01:43", + "generated": "2026-09-11 01:50", "aliases": [ "main", "ov_SC03_014", @@ -21,206 +21,206 @@ "main": { "objects": 85, "identical": 85, - "seconds": 6.742, - "mean_s": 0.079 + "seconds": 6.611, + "mean_s": 0.078 }, "ov_SC03_014": { "objects": 32, "identical": 32, - "seconds": 4.623, - "mean_s": 0.144 + "seconds": 4.446000000000001, + "mean_s": 0.139 }, "ov_SC03_015": { "objects": 32, "identical": 32, - "seconds": 4.488999999999999, - "mean_s": 0.14 + "seconds": 4.319, + "mean_s": 0.135 }, "ov_SC04_011": { "objects": 28, "identical": 28, - "seconds": 3.8060000000000005, - "mean_s": 0.136 + "seconds": 3.73, + "mean_s": 0.133 } }, "per_object_seconds": { - "build/src/800.o": 0.699, - "build/src/800_b.o": 0.081, - "build/src/800_b_2.o": 0.315, - "build/src/800_b_o0a.o": 0.066, - "build/src/800_c.o": 0.181, - "build/src/800b2.o": 0.106, - "build/src/apicard1.o": 0.076, - "build/src/apicard2.o": 0.08, - "build/src/apicard3.o": 0.071, - "build/src/apicard4.o": 0.094, - "build/src/apicard5.o": 0.083, - "build/src/apicard6.o": 0.064, - "build/src/apicard7.o": 0.066, - "build/src/boot.o": 0.097, - "build/src/gap.o": 0.06, - "build/src/libapi1.o": 0.056, - "build/src/libapi2.o": 0.055, + "build/src/800.o": 0.732, + "build/src/800_b.o": 0.08, + "build/src/800_b_2.o": 0.31, + "build/src/800_b_o0a.o": 0.087, + "build/src/800_c.o": 0.172, + "build/src/800b2.o": 0.07, + "build/src/apicard1.o": 0.063, + "build/src/apicard2.o": 0.064, + "build/src/apicard3.o": 0.073, + "build/src/apicard4.o": 0.11, + "build/src/apicard5.o": 0.08, + "build/src/apicard6.o": 0.07, + "build/src/apicard7.o": 0.073, + "build/src/boot.o": 0.099, + "build/src/gap.o": 0.054, + "build/src/libapi1.o": 0.091, + "build/src/libapi2.o": 0.065, "build/src/libc2_1.o": 0.063, - "build/src/libc2_2.o": 0.058, - "build/src/libcd1.o": 0.08, - "build/src/libcd2.o": 0.071, - "build/src/libetc.o": 0.061, - "build/src/libgpu.o": 0.066, - "build/src/libgpu2.o": 0.075, - "build/src/libgs1.o": 0.058, - "build/src/libgs2.o": 0.058, - "build/src/libgs3.o": 0.049, - "build/src/libgs4.o": 0.066, - "build/src/libgs5.o": 0.059, - "build/src/libgs6.o": 0.081, + "build/src/libc2_2.o": 0.057, + "build/src/libcd1.o": 0.068, + "build/src/libcd2.o": 0.059, + "build/src/libetc.o": 0.07, + "build/src/libgpu.o": 0.058, + "build/src/libgpu2.o": 0.073, + "build/src/libgs1.o": 0.047, + "build/src/libgs2.o": 0.064, + "build/src/libgs3.o": 0.065, + "build/src/libgs4.o": 0.064, + "build/src/libgs5.o": 0.057, + "build/src/libgs6.o": 0.079, "build/src/libgs7.o": 0.066, - "build/src/libgs8.o": 0.062, - "build/src/libgte1.o": 0.062, - "build/src/libgte10.o": 0.061, - "build/src/libgte11.o": 0.063, - "build/src/libgte12.o": 0.069, - "build/src/libgte13.o": 0.069, - "build/src/libgte14.o": 0.066, - "build/src/libgte15.o": 0.06, - "build/src/libgte16.o": 0.066, - "build/src/libgte17.o": 0.065, - "build/src/libgte18.o": 0.061, - "build/src/libgte19.o": 0.063, - "build/src/libgte2.o": 0.066, - "build/src/libgte20.o": 0.068, - "build/src/libgte21.o": 0.067, - "build/src/libgte22.o": 0.069, - "build/src/libgte23.o": 0.069, - "build/src/libgte24.o": 0.066, - "build/src/libgte25.o": 0.061, + "build/src/libgs8.o": 0.066, + "build/src/libgte1.o": 0.064, + "build/src/libgte10.o": 0.066, + "build/src/libgte11.o": 0.058, + "build/src/libgte12.o": 0.063, + "build/src/libgte13.o": 0.067, + "build/src/libgte14.o": 0.061, + "build/src/libgte15.o": 0.059, + "build/src/libgte16.o": 0.06, + "build/src/libgte17.o": 0.059, + "build/src/libgte18.o": 0.059, + "build/src/libgte19.o": 0.054, + "build/src/libgte2.o": 0.062, + "build/src/libgte20.o": 0.061, + "build/src/libgte21.o": 0.061, + "build/src/libgte22.o": 0.06, + "build/src/libgte23.o": 0.063, + "build/src/libgte24.o": 0.06, + "build/src/libgte25.o": 0.071, "build/src/libgte26.o": 0.062, - "build/src/libgte27.o": 0.069, - "build/src/libgte28.o": 0.063, - "build/src/libgte29.o": 0.059, - "build/src/libgte3.o": 0.063, - "build/src/libgte30.o": 0.062, - "build/src/libgte4.o": 0.062, - "build/src/libgte5.o": 0.066, + "build/src/libgte27.o": 0.059, + "build/src/libgte28.o": 0.062, + "build/src/libgte29.o": 0.063, + "build/src/libgte3.o": 0.067, + "build/src/libgte30.o": 0.068, + "build/src/libgte4.o": 0.061, + "build/src/libgte5.o": 0.065, "build/src/libgte6.o": 0.063, - "build/src/libgte7.o": 0.06, - "build/src/libgte8.o": 0.06, - "build/src/libgte9.o": 0.063, - "build/src/libmcrd1.o": 0.07, - "build/src/libmcrd2.o": 0.059, - "build/src/libpad1.o": 0.068, - "build/src/libpad2.o": 0.062, - "build/src/sgap.o": 0.078, - "build/src/sgap_2.o": 0.069, - "build/src/sgap_3.o": 0.06, - "build/src/sgap_4.o": 0.079, - "build/src/sgap_5.o": 0.063, - "build/src/sgap_6.o": 0.07, + "build/src/libgte7.o": 0.065, + "build/src/libgte8.o": 0.066, + "build/src/libgte9.o": 0.066, + "build/src/libmcrd1.o": 0.068, + "build/src/libmcrd2.o": 0.049, + "build/src/libpad1.o": 0.071, + "build/src/libpad2.o": 0.076, + "build/src/sgap.o": 0.068, + "build/src/sgap_2.o": 0.062, + "build/src/sgap_3.o": 0.066, + "build/src/sgap_4.o": 0.062, + "build/src/sgap_5.o": 0.062, + "build/src/sgap_6.o": 0.069, "build/src/sgap_8.o": 0.069, - "build/src/snd1.o": 0.066, - "build/src/snd10.o": 0.083, - "build/src/snd11.o": 0.064, + "build/src/snd1.o": 0.063, + "build/src/snd10.o": 0.062, + "build/src/snd11.o": 0.063, "build/src/snd12.o": 0.065, - "build/src/snd2.o": 0.075, + "build/src/snd2.o": 0.069, "build/src/snd3.o": 0.062, "build/src/snd4.o": 0.067, - "build/src/snd5.o": 0.069, - "build/src/snd6.o": 0.086, - "build/src/snd7.o": 0.07, + "build/src/snd5.o": 0.061, + "build/src/snd6.o": 0.069, + "build/src/snd7.o": 0.061, "build/src/snd8.o": 0.062, - "build/src/snd9.o": 0.08, - "build/src/ov_SC03_014/ov_SC03_014.o": 0.122, - "build/src/ov_SC03_014/ov_SC03_014_after.o": 0.505, - "build/src/ov_SC03_014/ov_SC03_014_jr_8012ACE0.o": 0.398, + "build/src/snd9.o": 0.061, + "build/src/ov_SC03_014/ov_SC03_014.o": 0.119, + "build/src/ov_SC03_014/ov_SC03_014_after.o": 0.483, + "build/src/ov_SC03_014/ov_SC03_014_jr_8012ACE0.o": 0.369, "build/src/ov_SC03_014/ov_SC03_014_jr_80135888.o": 0.056, - "build/src/ov_SC03_014/ov_SC03_014_jr_80135A4C.o": 0.063, - "build/src/ov_SC03_014/ov_SC03_014_jr_80135D20.o": 0.13, - "build/src/ov_SC03_014/ov_SC03_014_jr_801380E0.o": 0.16, - "build/src/ov_SC03_014/ov_SC03_014_jr_8013C98C.o": 0.114, - "build/src/ov_SC03_014/ov_SC03_014_jr_8013F350.o": 0.077, - "build/src/ov_SC03_014/ov_SC03_014_jr_8013FFD8.o": 0.072, - "build/src/ov_SC03_014/ov_SC03_014_jr_80140608.o": 0.19, - "build/src/ov_SC03_014/ov_SC03_014_jr_8015444C.o": 0.073, - "build/src/ov_SC03_014/ov_SC03_014_jr_80154C24.o": 0.163, - "build/src/ov_SC03_014/ov_SC03_014_jr_801588CC.o": 0.095, - "build/src/ov_SC03_014/ov_SC03_014_jr_80159C84.o": 0.067, - "build/src/ov_SC03_014/ov_SC03_014_jr_8015A3C8.o": 0.068, - "build/src/ov_SC03_014/ov_SC03_014_jr_8015AE2C.o": 0.095, - "build/src/ov_SC03_014/ov_SC03_014_jr_8015C32C.o": 0.442, - "build/src/ov_SC03_014/ov_SC03_014_jr_8016AB6C.o": 0.282, - "build/src/ov_SC03_014/ov_SC03_014_jr_80171B4C.o": 0.094, - "build/src/ov_SC03_014/ov_SC03_014_jr_801734BC.o": 0.213, - "build/src/ov_SC03_014/ov_SC03_014_jr_801789AC.o": 0.057, - "build/src/ov_SC03_014/ov_SC03_014_jr_80178D40.o": 0.102, - "build/src/ov_SC03_014/ov_SC03_014_jr_8017A4AC.o": 0.061, - "build/src/ov_SC03_014/ov_SC03_014_jr_8017AE2C.o": 0.16, - "build/src/ov_SC03_014/ov_SC03_014_jr_8017EB7C.o": 0.204, - "build/src/ov_SC03_014/ov_SC03_014_jr_80184440.o": 0.047, - "build/src/ov_SC03_014/ov_SC03_014_jr_801848E4.o": 0.274, - "build/src/ov_SC03_014/ov_SC03_014_o0b.o": 0.058, - "build/src/ov_SC03_014/ov_SC03_014_o0c.o": 0.056, - "build/src/ov_SC03_014/ov_SC03_014_o0d.o": 0.056, - "build/src/ov_SC03_014/ov_SC03_014_o0e.o": 0.069, - "build/src/ov_SC03_015/ov_SC03_015.o": 0.13, - "build/src/ov_SC03_015/ov_SC03_015_after.o": 0.488, - "build/src/ov_SC03_015/ov_SC03_015_jr_8012ACE0.o": 0.392, - "build/src/ov_SC03_015/ov_SC03_015_jr_80135888.o": 0.047, - "build/src/ov_SC03_015/ov_SC03_015_jr_80135A4C.o": 0.057, - "build/src/ov_SC03_015/ov_SC03_015_jr_80135D20.o": 0.115, - "build/src/ov_SC03_015/ov_SC03_015_jr_801380E0.o": 0.15, - "build/src/ov_SC03_015/ov_SC03_015_jr_8013C98C.o": 0.12, - "build/src/ov_SC03_015/ov_SC03_015_jr_8013F350.o": 0.074, - "build/src/ov_SC03_015/ov_SC03_015_jr_8013FFD8.o": 0.063, - "build/src/ov_SC03_015/ov_SC03_015_jr_80140608.o": 0.161, - "build/src/ov_SC03_015/ov_SC03_015_jr_8015444C.o": 0.07, - "build/src/ov_SC03_015/ov_SC03_015_jr_80154C24.o": 0.161, - "build/src/ov_SC03_015/ov_SC03_015_jr_801588CC.o": 0.092, - "build/src/ov_SC03_015/ov_SC03_015_jr_80159C84.o": 0.062, - "build/src/ov_SC03_015/ov_SC03_015_jr_8015A3C8.o": 0.071, - "build/src/ov_SC03_015/ov_SC03_015_jr_8015AE2C.o": 0.092, - "build/src/ov_SC03_015/ov_SC03_015_jr_8015C32C.o": 0.448, - "build/src/ov_SC03_015/ov_SC03_015_jr_8016AB6C.o": 0.267, - "build/src/ov_SC03_015/ov_SC03_015_jr_80171B4C.o": 0.091, - "build/src/ov_SC03_015/ov_SC03_015_jr_801734BC.o": 0.198, - "build/src/ov_SC03_015/ov_SC03_015_jr_801789AC.o": 0.053, - "build/src/ov_SC03_015/ov_SC03_015_jr_80178D40.o": 0.102, - "build/src/ov_SC03_015/ov_SC03_015_jr_8017A4AC.o": 0.065, - "build/src/ov_SC03_015/ov_SC03_015_jr_8017AE2C.o": 0.166, - "build/src/ov_SC03_015/ov_SC03_015_jr_8017EB7C.o": 0.183, - "build/src/ov_SC03_015/ov_SC03_015_jr_80184440.o": 0.051, - "build/src/ov_SC03_015/ov_SC03_015_jr_801848E4.o": 0.277, - "build/src/ov_SC03_015/ov_SC03_015_o0b.o": 0.06, - "build/src/ov_SC03_015/ov_SC03_015_o0c.o": 0.061, - "build/src/ov_SC03_015/ov_SC03_015_o0d.o": 0.051, - "build/src/ov_SC03_015/ov_SC03_015_o0e.o": 0.071, - "build/src/ov_SC04_011/ov_SC04_011.o": 0.112, - "build/src/ov_SC04_011/ov_SC04_011_after.o": 0.417, - "build/src/ov_SC04_011/ov_SC04_011_jr_8012ACE0.o": 0.349, - "build/src/ov_SC04_011/ov_SC04_011_jr_80135888.o": 0.045, - "build/src/ov_SC04_011/ov_SC04_011_jr_80135A4C.o": 0.05, - "build/src/ov_SC04_011/ov_SC04_011_jr_80135D20.o": 0.12, - "build/src/ov_SC04_011/ov_SC04_011_jr_801380E0.o": 0.152, - "build/src/ov_SC04_011/ov_SC04_011_jr_8013C98C.o": 0.11, - "build/src/ov_SC04_011/ov_SC04_011_jr_8013F350.o": 0.071, - "build/src/ov_SC04_011/ov_SC04_011_jr_8013FFD8.o": 0.061, - "build/src/ov_SC04_011/ov_SC04_011_jr_80140608.o": 0.158, - "build/src/ov_SC04_011/ov_SC04_011_jr_8015444C.o": 0.064, - "build/src/ov_SC04_011/ov_SC04_011_jr_80154C24.o": 0.149, - "build/src/ov_SC04_011/ov_SC04_011_jr_801588CC.o": 0.078, - "build/src/ov_SC04_011/ov_SC04_011_jr_80159C84.o": 0.061, + "build/src/ov_SC03_014/ov_SC03_014_jr_80135A4C.o": 0.062, + "build/src/ov_SC03_014/ov_SC03_014_jr_80135D20.o": 0.121, + "build/src/ov_SC03_014/ov_SC03_014_jr_801380E0.o": 0.158, + "build/src/ov_SC03_014/ov_SC03_014_jr_8013C98C.o": 0.123, + "build/src/ov_SC03_014/ov_SC03_014_jr_8013F350.o": 0.079, + "build/src/ov_SC03_014/ov_SC03_014_jr_8013FFD8.o": 0.067, + "build/src/ov_SC03_014/ov_SC03_014_jr_80140608.o": 0.179, + "build/src/ov_SC03_014/ov_SC03_014_jr_8015444C.o": 0.075, + "build/src/ov_SC03_014/ov_SC03_014_jr_80154C24.o": 0.155, + "build/src/ov_SC03_014/ov_SC03_014_jr_801588CC.o": 0.097, + "build/src/ov_SC03_014/ov_SC03_014_jr_80159C84.o": 0.068, + "build/src/ov_SC03_014/ov_SC03_014_jr_8015A3C8.o": 0.06, + "build/src/ov_SC03_014/ov_SC03_014_jr_8015AE2C.o": 0.086, + "build/src/ov_SC03_014/ov_SC03_014_jr_8015C32C.o": 0.465, + "build/src/ov_SC03_014/ov_SC03_014_jr_8016AB6C.o": 0.244, + "build/src/ov_SC03_014/ov_SC03_014_jr_80171B4C.o": 0.091, + "build/src/ov_SC03_014/ov_SC03_014_jr_801734BC.o": 0.194, + "build/src/ov_SC03_014/ov_SC03_014_jr_801789AC.o": 0.056, + "build/src/ov_SC03_014/ov_SC03_014_jr_80178D40.o": 0.088, + "build/src/ov_SC03_014/ov_SC03_014_jr_8017A4AC.o": 0.06, + "build/src/ov_SC03_014/ov_SC03_014_jr_8017AE2C.o": 0.155, + "build/src/ov_SC03_014/ov_SC03_014_jr_8017EB7C.o": 0.188, + "build/src/ov_SC03_014/ov_SC03_014_jr_80184440.o": 0.05, + "build/src/ov_SC03_014/ov_SC03_014_jr_801848E4.o": 0.275, + "build/src/ov_SC03_014/ov_SC03_014_o0b.o": 0.054, + "build/src/ov_SC03_014/ov_SC03_014_o0c.o": 0.057, + "build/src/ov_SC03_014/ov_SC03_014_o0d.o": 0.055, + "build/src/ov_SC03_014/ov_SC03_014_o0e.o": 0.057, + "build/src/ov_SC03_015/ov_SC03_015.o": 0.125, + "build/src/ov_SC03_015/ov_SC03_015_after.o": 0.493, + "build/src/ov_SC03_015/ov_SC03_015_jr_8012ACE0.o": 0.358, + "build/src/ov_SC03_015/ov_SC03_015_jr_80135888.o": 0.049, + "build/src/ov_SC03_015/ov_SC03_015_jr_80135A4C.o": 0.043, + "build/src/ov_SC03_015/ov_SC03_015_jr_80135D20.o": 0.098, + "build/src/ov_SC03_015/ov_SC03_015_jr_801380E0.o": 0.142, + "build/src/ov_SC03_015/ov_SC03_015_jr_8013C98C.o": 0.114, + "build/src/ov_SC03_015/ov_SC03_015_jr_8013F350.o": 0.064, + "build/src/ov_SC03_015/ov_SC03_015_jr_8013FFD8.o": 0.062, + "build/src/ov_SC03_015/ov_SC03_015_jr_80140608.o": 0.148, + "build/src/ov_SC03_015/ov_SC03_015_jr_8015444C.o": 0.065, + "build/src/ov_SC03_015/ov_SC03_015_jr_80154C24.o": 0.152, + "build/src/ov_SC03_015/ov_SC03_015_jr_801588CC.o": 0.085, + "build/src/ov_SC03_015/ov_SC03_015_jr_80159C84.o": 0.067, + "build/src/ov_SC03_015/ov_SC03_015_jr_8015A3C8.o": 0.069, + "build/src/ov_SC03_015/ov_SC03_015_jr_8015AE2C.o": 0.096, + "build/src/ov_SC03_015/ov_SC03_015_jr_8015C32C.o": 0.437, + "build/src/ov_SC03_015/ov_SC03_015_jr_8016AB6C.o": 0.242, + "build/src/ov_SC03_015/ov_SC03_015_jr_80171B4C.o": 0.093, + "build/src/ov_SC03_015/ov_SC03_015_jr_801734BC.o": 0.196, + "build/src/ov_SC03_015/ov_SC03_015_jr_801789AC.o": 0.049, + "build/src/ov_SC03_015/ov_SC03_015_jr_80178D40.o": 0.103, + "build/src/ov_SC03_015/ov_SC03_015_jr_8017A4AC.o": 0.062, + "build/src/ov_SC03_015/ov_SC03_015_jr_8017AE2C.o": 0.147, + "build/src/ov_SC03_015/ov_SC03_015_jr_8017EB7C.o": 0.196, + "build/src/ov_SC03_015/ov_SC03_015_jr_80184440.o": 0.053, + "build/src/ov_SC03_015/ov_SC03_015_jr_801848E4.o": 0.264, + "build/src/ov_SC03_015/ov_SC03_015_o0b.o": 0.062, + "build/src/ov_SC03_015/ov_SC03_015_o0c.o": 0.06, + "build/src/ov_SC03_015/ov_SC03_015_o0d.o": 0.057, + "build/src/ov_SC03_015/ov_SC03_015_o0e.o": 0.068, + "build/src/ov_SC04_011/ov_SC04_011.o": 0.108, + "build/src/ov_SC04_011/ov_SC04_011_after.o": 0.401, + "build/src/ov_SC04_011/ov_SC04_011_jr_8012ACE0.o": 0.332, + "build/src/ov_SC04_011/ov_SC04_011_jr_80135888.o": 0.052, + "build/src/ov_SC04_011/ov_SC04_011_jr_80135A4C.o": 0.052, + "build/src/ov_SC04_011/ov_SC04_011_jr_80135D20.o": 0.107, + "build/src/ov_SC04_011/ov_SC04_011_jr_801380E0.o": 0.142, + "build/src/ov_SC04_011/ov_SC04_011_jr_8013C98C.o": 0.108, + "build/src/ov_SC04_011/ov_SC04_011_jr_8013F350.o": 0.068, + "build/src/ov_SC04_011/ov_SC04_011_jr_8013FFD8.o": 0.057, + "build/src/ov_SC04_011/ov_SC04_011_jr_80140608.o": 0.175, + "build/src/ov_SC04_011/ov_SC04_011_jr_8015444C.o": 0.066, + "build/src/ov_SC04_011/ov_SC04_011_jr_80154C24.o": 0.157, + "build/src/ov_SC04_011/ov_SC04_011_jr_801588CC.o": 0.082, + "build/src/ov_SC04_011/ov_SC04_011_jr_80159C84.o": 0.057, "build/src/ov_SC04_011/ov_SC04_011_jr_8015A3C8.o": 0.06, - "build/src/ov_SC04_011/ov_SC04_011_jr_8015AE2C.o": 0.095, - "build/src/ov_SC04_011/ov_SC04_011_jr_8015C32C.o": 0.357, - "build/src/ov_SC04_011/ov_SC04_011_jr_8016AB6C.o": 0.198, - "build/src/ov_SC04_011/ov_SC04_011_jr_80171B4C.o": 0.088, - "build/src/ov_SC04_011/ov_SC04_011_jr_801734BC.o": 0.168, - "build/src/ov_SC04_011/ov_SC04_011_jr_801789AC.o": 0.057, - "build/src/ov_SC04_011/ov_SC04_011_jr_80178D40.o": 0.082, - "build/src/ov_SC04_011/ov_SC04_011_jr_8017A4AC.o": 0.065, - "build/src/ov_SC04_011/ov_SC04_011_jr_8017AE2C.o": 0.103, - "build/src/ov_SC04_011/ov_SC04_011_jr_8017D494.o": 0.432, - "build/src/ov_SC04_011/ov_SC04_011_o0b.o": 0.052, - "build/src/ov_SC04_011/ov_SC04_011_o0c.o": 0.052 + "build/src/ov_SC04_011/ov_SC04_011_jr_8015AE2C.o": 0.081, + "build/src/ov_SC04_011/ov_SC04_011_jr_8015C32C.o": 0.339, + "build/src/ov_SC04_011/ov_SC04_011_jr_8016AB6C.o": 0.219, + "build/src/ov_SC04_011/ov_SC04_011_jr_80171B4C.o": 0.093, + "build/src/ov_SC04_011/ov_SC04_011_jr_801734BC.o": 0.157, + "build/src/ov_SC04_011/ov_SC04_011_jr_801789AC.o": 0.058, + "build/src/ov_SC04_011/ov_SC04_011_jr_80178D40.o": 0.08, + "build/src/ov_SC04_011/ov_SC04_011_jr_8017A4AC.o": 0.063, + "build/src/ov_SC04_011/ov_SC04_011_jr_8017AE2C.o": 0.089, + "build/src/ov_SC04_011/ov_SC04_011_jr_8017D494.o": 0.424, + "build/src/ov_SC04_011/ov_SC04_011_o0b.o": 0.047, + "build/src/ov_SC04_011/ov_SC04_011_o0c.o": 0.056 }, "ok": true, "seconds": 2.2 diff --git a/.run/P36/delever/ledger.jsonl b/.run/P36/delever/ledger.jsonl index 3fca37c30b..57dbc10f33 100644 --- a/.run/P36/delever/ledger.jsonl +++ b/.run/P36/delever/ledger.jsonl @@ -29398,3 +29398,4 @@ {"ts": "2026-09-11 01:43:00", "label": "s104_e8", "rung": "E", "calib": {"head": "04cf4c616", "stamp": "15956e4a96c4"}, "tu": "src/md_SC07_004/md_SC07_004.c", "fn": "func_801A3B18", "addr": 2149202712, "aliases": null, "header": false, "includers": 0, "nhash_before": "180a8819ffab26b8147e15678eb853ae368cc4cd", "nhash_after": "1cfda3a96f68c9409977a00d2b3a0fd1b17c7ef7", "source": ".run/P36/agents/md_SC07_004__func_801A3B18/body.c", "verdict": "LEVER-FREE", "sites": [], "compiles": 1, "seconds": 0.317, "objects": ["build/src/md_SC07_004/md_SC07_004.o"], "before_text": "void func_801A3B18(s32 param_1)\n{\n Mtx32_801A3B18 mtx; /* sp+0x10 */\n SVec_801A3B18 sv; /* sp+0x30 */\n SVec_801A3B18 sv2; /* sp+0x38 */\n s32 vec[4]; /* sp+0x40 */\n s32 flag; /* sp+0x50 */\n s32 v0;\n s32 amt;\n s32 d;\n s32 e;\n s32 ang;\n s32 mag;\n register s32 zr __asm__(\"$0\"); // !FAKE: pin $0 \u2014 NEEDED DIFFERS (P36 rung B tus9)\n s32 *p;\n /* D_800AE620 is the shared 32-byte matrix global; this TU already declares it\n * later as `extern Mtx32_801A90D8 D_800AE620;` (md_SC07_004.c:1569). Declared\n * here at BLOCK scope on purpose: a second file-scope spelling is a hard\n * `conflicting types` error in gcc-2.7.2, while a block-scope one is only a\n * warning \u2014 and re-typedef'ing Mtx32_801A90D8 above line 1565 would break the\n * definition that already lives there. */\n extern s32 D_800AE620[8];\n\n mtx = *(Mtx32_801A3B18 *)&D_800AE620;\n\n RotMatrixY(*(s16 *)(*(s32 *)(param_1 + 0x20) + 0x12), &mtx);\n\n mtx.t[0] = *(s16 *)(param_1 + 0x6);\n mtx.t[1] = *(s16 *)(param_1 + 0xA);\n mtx.t[2] = *(s16 *)(param_1 + 0xE);\n func_8004914C(&mtx);\n func_800491AC(&mtx);\n\n sv.vy = 0;\n sv.vx = 0;\n sv.vz = 0x80;\n RotTransSV((s32)&sv, (s32)&sv, &flag);\n\n sv2.vx = (u16)D_80126B5E;\n sv2.vy = (u16)D_80126B62;\n sv2.vz = (u16)D_80126B66;\n\n p = D_80126B58;\n d = func_8012B70C((s16 *)&sv, (s16 *)&sv2) -\n *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12);\n e = d & 0xFFF;\n ang = e + zr;\n if (e >= 0x800) {\n ang = e | 0xF000;\n }\n mag = ang + zr;\n if ((s16)ang < 0) {\n mag = -ang;\n }\n\n v0 = ((s32 (*)(s32))func_8012BE54)(param_1);\n\n if (func_8014CB8C() == 0 && v0 <= 0x23FFF && (s16)mag < 0x200 &&\n func_8017267C(p) == 0) {\n if (D_801F8864 > -0x1E0000) {\n D_801F8864 -= 0xC000;\n }\n } else {\n if (D_801F8864 < 0) {\n D_801F8864 += 0x10000;\n if (D_801F8864 > 0) {\n D_801F8864 = 0;\n }\n }\n }\n\n amt = D_801F8864;\n if (amt != 0) {\n vec[1] = 0;\n vec[0] = 0;\n vec[2] = amt;\n ApplyRotMatrixLV(vec, vec);\n p[1] += vec[0];\n p[3] += vec[2];\n }\n}\n", "after_text": "void func_801A3B18(s32 param_1)\n{\n Mtx32_801A3B18 mtx; /* sp+0x10 */\n SVec_801A3B18 sv; /* sp+0x30 */\n SVec_801A3B18 sv2; /* sp+0x38 */\n s32 vec[4]; /* sp+0x40 */\n s32 flag; /* sp+0x50 */\n s32 v0;\n s32 amt;\n s16 ang;\n s16 mag;\n s32 *p;\n /* D_800AE620 is the shared 32-byte matrix global; this TU already declares it\n * later as `extern Mtx32_801A90D8 D_800AE620;` (md_SC07_004.c:1569). Declared\n * here at BLOCK scope on purpose: a second file-scope spelling is a hard\n * `conflicting types` error in gcc-2.7.2, while a block-scope one is only a\n * warning \u2014 and re-typedef'ing Mtx32_801A90D8 above line 1565 would break the\n * definition that already lives there. */\n extern s32 D_800AE620[8];\n\n mtx = *(Mtx32_801A3B18 *)&D_800AE620;\n\n RotMatrixY(*(s16 *)(*(s32 *)(param_1 + 0x20) + 0x12), &mtx);\n\n mtx.t[0] = *(s16 *)(param_1 + 0x6);\n mtx.t[1] = *(s16 *)(param_1 + 0xA);\n mtx.t[2] = *(s16 *)(param_1 + 0xE);\n func_8004914C(&mtx);\n func_800491AC(&mtx);\n\n sv.vy = 0;\n sv.vx = 0;\n sv.vz = 0x80;\n RotTransSV((s32)&sv, (s32)&sv, &flag);\n\n sv2.vx = (u16)D_80126B5E;\n sv2.vy = (u16)D_80126B62;\n sv2.vz = (u16)D_80126B66;\n\n p = D_80126B58;\n ang = (func_8012B70C((s16 *)&sv, (s16 *)&sv2) -\n *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12)) & 0xFFF;\n if (ang >= 0x800) {\n ang |= 0xF000;\n }\n if (ang < 0) {\n mag = -ang;\n } else {\n mag = ang;\n }\n\n v0 = ((s32 (*)(s32))func_8012BE54)(param_1);\n\n if (func_8014CB8C() == 0 && v0 <= 0x23FFF && mag < 0x200 &&\n func_8017267C(p) == 0) {\n if (D_801F8864 > -0x1E0000) {\n D_801F8864 -= 0xC000;\n }\n } else {\n if (D_801F8864 < 0) {\n D_801F8864 += 0x10000;\n if (D_801F8864 > 0) {\n D_801F8864 = 0;\n }\n }\n }\n\n amt = D_801F8864;\n if (amt != 0) {\n vec[1] = 0;\n vec[0] = 0;\n vec[2] = amt;\n ApplyRotMatrixLV(vec, vec);\n p[1] += vec[0];\n p[3] += vec[2];\n }\n}\n"} {"ts": "2026-09-11 01:43:18", "label": "s104_e8", "rung": "E", "calib": {"head": "626725c07", "stamp": "15956e4a96c4"}, "tu": "src/md_SC07_004/md_SC07_004.c", "fn": "func_801AB54C", "addr": 2149233996, "aliases": null, "header": false, "includers": 0, "nhash_before": "96ba6c3170d30d0ccf6032b63cb9692ab5a624a5", "nhash_after": "c47470667a053091e0e2dcabfb6495be832518af", "source": ".run/P36/agents/md_SC07_004__func_801AB54C/body.c", "verdict": "LEVER-FREE", "sites": [], "compiles": 1, "seconds": 0.316, "objects": ["build/src/md_SC07_004/md_SC07_004.o"], "before_text": "void func_801AB54C(void *a0) {\n s32 v;\n s32 c;\n s32 p;\n s32 frame_pad[4];\n register s32 z __asm__(\"$0\"); // !FAKE: pin $0 \u2014 NEEDED DIFFERS (P36 rung B tus9)\n\n func_801A8494(a0);\n\n if (*(s32 *)((s32)a0 + 0x1C) != 0) {\n *(s32 *)((s32)a0 + 0x1C) -= 1;\n return;\n }\n\n p = *(s32 *)((s32)a0 + 0x20);\n v = *(s16 *)(p + 0x18);\n c = v + z;\n if (v < 0x600) {\n v = c + 0x100;\n *(s16 *)(p + 0x18) = v;\n }\n\n p = *(s32 *)((s32)a0 + 0x20);\n v = *(s16 *)(p + 0x1A);\n c = v + z;\n if (v < 0xA00) {\n v = c + 0x140;\n *(s16 *)(p + 0x1A) = v;\n }\n\n (void)&frame_pad;\n}\n", "after_text": "void func_801AB54C(void *a0) {\n func_801A8494(a0);\n\n if (*(s32 *)((s32)a0 + 0x1C) != 0) {\n *(s32 *)((s32)a0 + 0x1C) -= 1;\n return;\n }\n\n if (*(s16 *)(*(s32 *)((s32)a0 + 0x20) + 0x18) < 0x600) {\n *(s16 *)(*(s32 *)((s32)a0 + 0x20) + 0x18) += 0x100;\n }\n\n if (*(s16 *)(*(s32 *)((s32)a0 + 0x20) + 0x1A) < 0xA00) {\n *(s16 *)(*(s32 *)((s32)a0 + 0x20) + 0x1A) += 0x140;\n }\n}\n"} {"ts": "2026-09-11 01:43:37", "label": "s104_e8", "rung": "E", "calib": {"head": "e36b612f4", "stamp": "15956e4a96c4"}, "tu": "src/md_SC07_004/md_SC07_004.c", "fn": "func_801AB78C", "addr": 2149234572, "aliases": null, "header": false, "includers": 0, "nhash_before": "c4afac9feacd09d5fe6e93671e12870dee3bbcef", "nhash_after": "c0238ece5a288cf9f6a7aad6814fc3d9b0d3ce43", "source": ".run/P36/agents/md_SC07_004__func_801AB78C/body.c", "verdict": "LEVER-FREE", "sites": [], "compiles": 1, "seconds": 0.317, "objects": ["build/src/md_SC07_004/md_SC07_004.o"], "before_text": "void func_801AB78C(void *a0) {\n volatile u8 *p = &D_801F88BA;\n register s32 b __asm__(\"$3\"); // !FAKE: pin $3 \u2014 NEEDED DIFFERS (P36 rung B tus9)\n s32 t;\n if (*p == 0) {\n func_801292C8((u8 *)a0);\n } else {\n *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x18) += 0x200;\n *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x1A) = *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x18);\n b = *p;\n t = b - 0x10;\n if (b != 0) {\n b = t;\n if (t < 0) {\n b = 0;\n }\n *p = (u8)b;\n }\n }\n}\n", "after_text": "void func_801AB78C(void *a0) {\n volatile u8 *p = &D_801F88BA;\n u8 b;\n s16 t;\n if (*p == 0) {\n func_801292C8((u8 *)a0);\n } else {\n *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x18) += 0x200;\n *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x1A) = *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x18);\n b = *p;\n if (b != 0) {\n t = b - 0x10;\n b = t;\n if (t < 0) {\n b = 0;\n }\n *p = b;\n }\n }\n}\n"} +{"ts": "2026-09-11 01:50:14", "label": "s104_e9", "rung": "E", "calib": {"head": "5a4a7eed0", "stamp": "15956e4a96c4"}, "tu": "src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c", "fn": "func_80182FD0", "addr": 2149068752, "aliases": null, "header": false, "includers": 0, "nhash_before": "2eca4a3dae8ed526544c69ae6988b20a412e0a93", "nhash_after": "7e24c878055bfd382e58a69b9381c4118c7fb3be", "source": ".run/P36/agents/ov_SC02_017__func_80182FD0/body.c", "verdict": "LEVER-FREE", "sites": [], "compiles": 1, "seconds": 0.195, "objects": ["build/src/ov_SC02_017/ov_SC02_017_jr_8017DF34.o"], "before_text": "void func_80182FD0(int param)\n{\n u32 buf[3];\n u8 *s0;\n int v0;\n int x;\n int lim;\n\n s0 = ((u8 **)D_8018E8DC)[*(s16 *)(param + 0xFC)];\n\n /* gte_SetRotMatrix(&D_800AF648); gte_SetTransMatrix(&D_800AF648); */\n __asm__ volatile(\n \"lui $2,%%hi(D_800AF648);addiu $2,$2,%%lo(D_800AF648);\"\n \"lw $12,0($2);lw $13,4($2);ctc2 $12,$0;ctc2 $13,$1;\"\n \"lw $12,8($2);lw $13,12($2);lw $14,16($2);\"\n \"ctc2 $12,$2;ctc2 $13,$3;ctc2 $14,$4;\"\n \"lw $12,20($2);lw $13,24($2);ctc2 $12,$5;\"\n \"lw $14,28($2);ctc2 $13,$6;ctc2 $14,$7\"\n : : : \"$12\", \"$13\", \"$14\", \"$2\", \"memory\");\n\n func_80015978(param + 4, (s32 *)buf);\n\n /* gte_ldv0(buf); gte_rtps(); gte_stsxy(buf); */\n __asm__ volatile(\"lwc2 $0,0(%0);lwc2 $1,4(%0);nop;nop;rtps;swc2 $14,0(%0)\"\n : : \"r\"(buf) : \"memory\");\n /* gte_stflg(&buf[2]); */\n gte_stflg(buf + 2);\n\n lim = (D_800AF7BC >> 1) + 0x20;\n x = (int)(s16)buf[0];\n if (x <= -lim) goto done;\n if (x >= lim) goto done;\n __asm__ volatile(\"\" : : \"r\"(x)); /* keep $v1 live: see LEVER above */ // !FAKE: keepalive \u2014 NEEDED DIFFERS (P36 rung B tus8)\n\n lim = (D_800AF7BE >> 1) + 0x20;\n x = (int)(s16)((s16 *)buf)[1];\n if (x <= -lim) goto done;\n if (x >= lim) goto done;\n __asm__ volatile(\"\" : : \"r\"(x)); /* keep $v1 live: see LEVER above */ // !FAKE: keepalive \u2014 NEEDED DIFFERS (P36 rung B tus8)\n\n if ((int)buf[2] < 0) goto done;\n\n v0 = *(s32 *)(param + 0x1C);\n if (v0 != 0) { v0--; goto store; }\n\n if (*(s16 *)(s0 + 6) != 0xFF) {\n do {\n func_80183168((u8 *)param, s0);\n s0 += 8;\n } while (*(s16 *)(s0 + 6) != 0xFF);\n }\n v0 = *(s32 *)(param + 0xDC);\n *(s32 *)(param + 0x1C) = v0;\n v0 = *(volatile s32 *)(param + 0x1C);\n v0--;\nstore:\n *(s32 *)(param + 0x1C) = v0;\ndone:\n func_801831FC(param);\n}\n", "after_text": "void func_80182FD0(int param)\n{\n struct {\n s16 v[4];\n s32 flag;\n } w;\n u8 *s0;\n u8 *m = &D_800AF648;\n s32 lim;\n s32 lim2;\n\n s0 = ((u8 **)D_8018E8DC)[*(s16 *)(param + 0xFC)];\n\n gte_SetRotMatrix(m);\n gte_SetTransMatrix(m);\n\n func_80015978(param + 4, (s32 *)w.v);\n gte_ldv0(w.v);\n gte_rtps();\n gte_stsxy(w.v);\n gte_stflg(&w.flag);\n\n lim = (D_800AF7BC >> 1) + 0x20;\n if (w.v[0] > -lim && w.v[0] < lim) {\n lim2 = (D_800AF7BE >> 1) + 0x20;\n if (w.v[1] > -lim2 && w.v[1] < lim2 && w.flag >= 0) {\n if (*(s32 *)(param + 0x1C) == 0) {\n while (*(s16 *)(s0 + 6) != 0xFF) {\n func_80183168((u8 *)param, s0);\n s0 += 8;\n }\n *(s32 *)(param + 0x1C) = *(s32 *)(param + 0xDC);\n }\n *(s32 *)(param + 0x1C) -= 1;\n }\n }\n func_801831FC(param);\n}\n"} diff --git a/src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c b/src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c index da6397702c..0b1c86eece 100644 --- a/src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c +++ b/src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c @@ -5890,62 +5890,40 @@ extern u16 D_800AF7BE; void func_80182FD0(int param) { - u32 buf[3]; + struct { + s16 v[4]; + s32 flag; + } w; u8 *s0; - int v0; - int x; - int lim; + u8 *m = &D_800AF648; + s32 lim; + s32 lim2; s0 = ((u8 **)D_8018E8DC)[*(s16 *)(param + 0xFC)]; - /* gte_SetRotMatrix(&D_800AF648); gte_SetTransMatrix(&D_800AF648); */ - __asm__ volatile( - "lui $2,%%hi(D_800AF648);addiu $2,$2,%%lo(D_800AF648);" - "lw $12,0($2);lw $13,4($2);ctc2 $12,$0;ctc2 $13,$1;" - "lw $12,8($2);lw $13,12($2);lw $14,16($2);" - "ctc2 $12,$2;ctc2 $13,$3;ctc2 $14,$4;" - "lw $12,20($2);lw $13,24($2);ctc2 $12,$5;" - "lw $14,28($2);ctc2 $13,$6;ctc2 $14,$7" - : : : "$12", "$13", "$14", "$2", "memory"); + gte_SetRotMatrix(m); + gte_SetTransMatrix(m); - func_80015978(param + 4, (s32 *)buf); - - /* gte_ldv0(buf); gte_rtps(); gte_stsxy(buf); */ - __asm__ volatile("lwc2 $0,0(%0);lwc2 $1,4(%0);nop;nop;rtps;swc2 $14,0(%0)" - : : "r"(buf) : "memory"); - /* gte_stflg(&buf[2]); */ - gte_stflg(buf + 2); + func_80015978(param + 4, (s32 *)w.v); + gte_ldv0(w.v); + gte_rtps(); + gte_stsxy(w.v); + gte_stflg(&w.flag); lim = (D_800AF7BC >> 1) + 0x20; - x = (int)(s16)buf[0]; - if (x <= -lim) goto done; - if (x >= lim) goto done; - __asm__ volatile("" : : "r"(x)); /* keep $v1 live: see LEVER above */ // !FAKE: keepalive — NEEDED DIFFERS (P36 rung B tus8) - - lim = (D_800AF7BE >> 1) + 0x20; - x = (int)(s16)((s16 *)buf)[1]; - if (x <= -lim) goto done; - if (x >= lim) goto done; - __asm__ volatile("" : : "r"(x)); /* keep $v1 live: see LEVER above */ // !FAKE: keepalive — NEEDED DIFFERS (P36 rung B tus8) - - if ((int)buf[2] < 0) goto done; - - v0 = *(s32 *)(param + 0x1C); - if (v0 != 0) { v0--; goto store; } - - if (*(s16 *)(s0 + 6) != 0xFF) { - do { - func_80183168((u8 *)param, s0); - s0 += 8; - } while (*(s16 *)(s0 + 6) != 0xFF); + if (w.v[0] > -lim && w.v[0] < lim) { + lim2 = (D_800AF7BE >> 1) + 0x20; + if (w.v[1] > -lim2 && w.v[1] < lim2 && w.flag >= 0) { + if (*(s32 *)(param + 0x1C) == 0) { + while (*(s16 *)(s0 + 6) != 0xFF) { + func_80183168((u8 *)param, s0); + s0 += 8; + } + *(s32 *)(param + 0x1C) = *(s32 *)(param + 0xDC); + } + *(s32 *)(param + 0x1C) -= 1; + } } - v0 = *(s32 *)(param + 0xDC); - *(s32 *)(param + 0x1C) = v0; - v0 = *(volatile s32 *)(param + 0x1C); - v0--; -store: - *(s32 *)(param + 0x1C) = v0; -done: func_801831FC(param); }