diff --git a/src/ov_SC06_010/ov_SC06_010_jr_8017A4AC.c b/src/ov_SC06_010/ov_SC06_010_jr_8017A4AC.c index df9119e52..a8c94415d 100644 --- a/src/ov_SC06_010/ov_SC06_010_jr_8017A4AC.c +++ b/src/ov_SC06_010/ov_SC06_010_jr_8017A4AC.c @@ -4010,7 +4010,83 @@ void func_8017D6F8(s32 a0) INCLUDE_ASM("asm/ov_SC06_010/nonmatchings/ov_SC06_010_jr_8017A4AC", func_8017D748); -INCLUDE_ASM("asm/ov_SC06_010/nonmatchings/ov_SC06_010_jr_8017A4AC", func_8017D7CC); +#include "common.h" + +/* func_8017D7CC @ ov_SC06_010 (subseg ov_SC06_010_jr_8017A4AC) — 87 ins. + * + * SEED: func_801822E0 @ ov_SC02_016 (src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c), 91.9% skeleton-similar, + * already byte-matched. This is the near-identical sibling. + * + * Diff vs seed (byte-verified via objdump of the seed's matched .o): + * - Seed uses an explicit `s32 i = 0; do { iVar1 = func_801824AC(); if (iVar1 >= 0) {...} i++; } while (i < 3);` + * — a genuine do-while (no pre-loop guard), with the call's return value (iVar1) kept ONLY in $v1 (never + * saved across calls) and a SEPARATE loop counter `i` in $s3. + * - This target has NO separate counter: the loop variable IS the call's return value itself, tested both + * for the if-guard (>=0) and for loop continuation (<3). Because that variable is reassigned only INSIDE + * the loop body, the while-loop rotation ("if (cond) { preheader; do {...} while(cond); }") needs a + * pre-loop guard test — but since the variable has no source-level initializer before the loop, the guard + * reads whatever is in its (freshly register-allocated, never-yet-written) register: `slti $v0,$s2,3` / + * `beqz $v0,` right after the buf[1]-=0x40 store, with NO assignment to $s2 anywhere before it. + * Reproduced here as a genuinely uninitialized local tested by a `while` loop (matches gcc-2.7.2's + * loop-rotation idiom exactly — the guard is emitted even though the variable's "value" is indeterminate). + * - The `func_80146A6C(...)` calls' 7th argument is `1` here (not `0` as in the seed) — this constant is + * loop-invariant and reused at BOTH call sites, so gcc hoists it once into a callee-saved register ($s4) + * before the loop rather than re-materializing `li $a,1` at each site (the seed's constant is `0`, which + * is free via $zero, so the seed needed no such register — hence the seed has one fewer saved S-register). + * - The post-loop `if (cnt == 0) { ... }` here has NO else-branch (the seed's else called + * `func_80172630((u8*)param_1)`); the asm falls straight from the 3-call if-body into the epilogue. + * - Register roles differ naturally from the seed given the above (actor pointer ends up in $s3 here, not + * $s2 — $s2 is claimed by the loop-return-value variable instead). + * + * Callee/global renames from the seed (per this TU's own asm ground truth): + * func_801824AC -> func_8017D9A0 (still s32, no args) + * func_80182434 -> func_8017D928 (still void, s32 a0) + * func_80172630 -> (unused; no else-branch in this target) + */ + +extern void func_80015978(s32 a0, s32 *a1); +extern s32 func_8017D9A0(void); +extern s32 func_80146A6C(s32 a0, void *a1, s32 a2, s32 a3, s32 a4, s32 a5, s32 a6); +extern int rand(void); +extern void func_8017D928(s32 a0); +extern void func_80159B3C(void *a0); +extern void func_80165718(s32 a0); + +void func_8017D7CC(s32 param_1) +{ + s16 buf[4]; + s32 v2; + s32 uVar3; + s32 uVar4; + s32 uVar5; + s16 rnd; + u8 cnt; + + func_80015978(param_1 + 4, (s32 *)buf); + buf[1] -= 0x40; + + while (v2 < 3) { + v2 = func_8017D9A0(); + if (v2 >= 0) { + func_80146A6C(0x51, (void *)param_1, buf[0], buf[1], buf[2], v2, 1); + + uVar3 = rand(); + uVar4 = rand(); + uVar5 = rand(); + rnd = (uVar3 & 3) * 0x400 + (uVar4 & 3) * 0xfa + (uVar5 & 3) * 0x44; + func_80146A6C(0x52, (void *)param_1, 0, -0x20, 0x10, rnd, 1); + } + } + + cnt = *(u8 *)(param_1 + 0xde); + *(u8 *)(param_1 + 0xde) = cnt + 0xff; + if (cnt == 0) { + func_8017D928(param_1); + func_80159B3C((void *)param_1); + func_80165718(param_1); + } +} + extern void func_80147324(s32 a0); extern void func_80147364(u16, s32);