From f7fee7fcde2bdfcff6af0e89465f971bce7abfa3 Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Mon, 31 Aug 2026 17:08:32 -0600 Subject: [PATCH] =?UTF-8?q?feat(decomp):=20main=20banks=20again=20?= =?UTF-8?q?=E2=80=94=203=20fns=20(func=5F80012B58,=20func=5F800241C0,=20fu?= =?UTF-8?q?nc=5F800242D0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first main banks since the two harness defects were fixed. All three were proven byte-perfect in the real link by the Fable investigation BEFORE any fix, and reported {banked:0, near:3} purely because: * gate_stage compared main against ov_SC01_077's SHA (build/main/main never exists, config/check.main.sha never exists, DEF_SHA took over), and * psyq_integrate dropped 'firstfile = 0x80061FA8;' on every incremental relink, so main's BASELINE was already 2 bytes red before a draft was spliced. func_800242D0 additionally needed one reconcile: it declared 'extern u16 D_80063870' while the just-banked func_800241C0 declares 'extern s16 D_80063870[]' at file scope. gcc-2.7.2 rejects the conflicting redeclaration at file scope AND at block scope (the block-scope shadow was tried and also rejected), so the draft now matches the banked spelling and takes the address by array decay. Only the address is used (t4 is a 'register s16 *'), so the element type never reaches codegen -- and the whole-binary SHA proves it. harvest_verify in the main tree: verified 3 / failed 0, final SHA 143dbb89f34491258bbc27810d0a12ec8b43a8dd BYTE-IDENTICAL. main 1048 -> 1045 stubs. NOTE for the next session: parallel_gate's WORKTREE still cannot gate main (its generated-input staging covers the 3 Makefile-named files but main's link needs more). main is one binary, so gate it in the main tree with harvest_verify -- there is no parallelism to lose. --- src/800.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 3 deletions(-) diff --git a/src/800.c b/src/800.c index e7bcd9004..5bd0f039c 100644 --- a/src/800.c +++ b/src/800.c @@ -661,7 +661,52 @@ s32 func_80012B04(s32 a0, s32 a1, s32 a2) { return func_80012B58((s16)a0, (s16)a1, (s16)a2, sp10); } -INCLUDE_ASM("asm/nonmatchings/800", func_80012B58); +s16 func_80012B58(s16 a0, s16 a1, s16 a2, s16 *a3) +{ + s16 diff = a1 - a0; + s16 h = *a3; + s32 t; + s16 dv; + + if (h != 0) { + t = a2; + t <<= 16; + dv = t >> 16; + if (dv != 0) { + goto block2; + } + } + + { + s16 out = diff; + if (diff >= 0x801) { + out = diff - 0x1000; + } + if (out < -0x800) { + out += 0x1000; + } + return out; + } + +block2: + { + s16 out = diff; + s16 q; + if (diff >= 0x801) { + out = diff - 0x1000; + } + if (out < -0x800) { + out += 0x1000; + } + q = out / dv; + if (q != 0) { + return q; + } + *a3 = h - 1; + return func_80012B58(a0, a1, (dv + ((u32)t >> 31)) >> 1, a3); + } +} + extern s32 func_80012CB8(s32 a0, s32 a1, s32 a2); @@ -10619,9 +10664,126 @@ INCLUDE_ASM("asm/nonmatchings/800", func_80023BF0); INCLUDE_ASM("asm/nonmatchings/800", func_80024054); -INCLUDE_ASM("asm/nonmatchings/800", func_800241C0); +extern u16 D_800636D8[]; +extern u16 D_80063818[]; +extern s16 D_80063870[]; + +void func_800241C0(s32 arg0, u16 *arg1, s32 arg2) +{ + s32 pad[2]; + s32 rem; + register s32 i __asm__("$7"); + s32 cnt; + register s32 d __asm__("$4"); + register s32 q __asm__("$6"); + register s32 zr __asm__("$0"); + register s32 dd __asm__("$3"); + register s32 srem __asm__("$3"); + s32 i2; + u16 *pA; + u16 *pB; + s16 *pC; + + rem = arg0; + cnt = 0; + arg2--; + i = arg2 + zr; + if ((arg2 << 16) < 0) goto tail; + pA = D_80063818; + pB = D_800636D8; + pC = D_80063870; + do { + if ((i << 16) != 0) { + *arg1 = pA[0]; + } else { + *arg1 = pB[0]; + } + srem = (s16)rem; + d = pC[(s16)i]; + q = srem / d; + dd = d + zr; + if ((s16)q != 0) { + *arg1 = pB[(s16)q]; + cnt++; + rem -= q * dd; + } else if (cnt != 0) { + *arg1 = pB[0]; + } + i2 = i - 1; + i = i2 + zr; + arg1++; + } while ((i2 << 16) >= 0); +tail: + *(s16 *)arg1 = -1; +} + + +extern u16 D_80063858; +extern u16 D_8006386C; +/* SAME spelling as the already-banked func_800241C0 uses at file scope: gcc-2.7.2 + * rejects a conflicting redeclaration at file scope AND at block scope, so match it. + * Only the ADDRESS is taken here (t4 is a `register s16 *`), so the element type of + * the decl does not reach codegen. */ +extern s16 D_80063870[]; + +void func_800242D0(s32 arg0, u16* arg1, s32 arg2) { + s32 frame_pad[1]; + register s32 t0 __asm__("$8"); + register s32 t1 __asm__("$9"); + s32 v0; + register s32 v1 __asm__("$3"); + register s32 a3 __asm__("$7"); + register s16* t4 __asm__("$12"); + register u16* t2 __asm__("$10"); + register s32 t3 __asm__("$11"); + register s32 divisor __asm__("$4"); + (void)&frame_pad; + + t0 = arg2 & 0xFFAF; + arg2 = arg2 & 0x80; + t1 = arg0; + if (arg2 != 0) { + t0 = 4; + } + v0 = t0 - 1; + t0 = v0; + __asm__ __volatile__("" : "=r"(t0) : "0"(t0)); + if ((v0 << 16) >= 0) { + t4 = D_80063870; + t2 = &D_80063858; + t3 = 2; + v1 = t1 << 16; + do { + v0 = (t0 << 16) >> 15; + divisor = *(s16*)(v0 + (s32)t4); + v1 = v1 >> 16; + v0 = v1 / divisor; + a3 = v0; + if (((a3 << 16) >> 16) != 0) { + v1 = divisor; + __asm__ __volatile__("" : "=r"(v1) : "0"(v1)); + *(u16*)arg1 = *(u16*)((((a3 << 16) >> 16) << 1) + (s32)t2); + t1 -= a3 * v1; + } else { + *(u16*)arg1 = *(u16*)t2; + } + arg1 += 1; + if (arg2 != 0) { + v0 = (t0 << 16) >> 16; + if (v0 == t3) { + *(u16*)arg1 = D_8006386C; + arg1 += 1; + } + } + v0 = t0 - 1; + t0 = v0; + __asm__ __volatile__("" : "=r"(t0) : "0"(t0)); + v1 = t1 << 16; + } while ((v0 << 16) >= 0); + } + *(s16*)arg1 = -1; +} -INCLUDE_ASM("asm/nonmatchings/800", func_800242D0); extern s32 D_80078D88[]; extern s32 D_800A2B78;