From 5e2c15b454821c9bc300ca27e9b6a30dfdffa08f Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:59:27 -0600 Subject: [PATCH] =?UTF-8?q?feat(decomp):=20main=20lane=20m11b=20=E2=80=94?= =?UTF-8?q?=2019=20banked?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One clean whole-EXE rebuild verified the batch (gate_main), and main re-checked BYTE-IDENTICAL against config/check.us.sha before anything was credited. GS_001_OBJ_5D0 GsInitGraph2 GsTMDfastF4GNL Square0 func_800168C4 func_80018194 func_8001A9F8 func_8001CA88 func_8001F97C func_8001FB8C func_800296F8 func_80029D3C func_8002E79C func_8002EDE4 func_8002F1CC func_80036F18 func_8003775C func_800385C0 func_80062644 --- src/800.c | 317 +++++++++++++++++++++++++++++++++++++++++++++++--- src/800b2.c | 144 ++++++++++++++++++++++- src/800b_2.c | 19 ++- src/800c2_2.c | 18 ++- src/gsgap3.c | 54 ++++++++- 5 files changed, 533 insertions(+), 19 deletions(-) diff --git a/src/800.c b/src/800.c index d37700a7a..8d2c8dfc1 100644 --- a/src/800.c +++ b/src/800.c @@ -2411,7 +2411,30 @@ void func_800168B4(void) { D_800AF7CE = 0; } -INCLUDE_ASM("asm/nonmatchings/800", func_800168C4); +extern u8 D_800AF630[]; +extern u16 D_800AF7CE; +extern s32 D_800B9A18; +extern u8 D_80062BA0[]; + +s32 func_800168C4(register s32 arg0) { + register s32 t __asm__("$3"); + u8 *base = D_800AF630; + + arg0 &= 3; + if (arg0 == 0) { + t = D_80062BA0[D_800B9A18]; + } else { + t = D_80062BA0[arg0]; + } + D_800AF7CE += t; + __asm__ __volatile__("" : : : "memory"); + + t = *(u16 *) (base + 0x19E); + if (t >= 0xFFU) { + return *(u16 *) (base + 0x188) != 0; + } + return 0; +} extern u16 D_800AF7CE; @@ -3882,7 +3905,26 @@ void func_80018094(void *a0, s32 a1, u32 a2_p) { } } -INCLUDE_ASM("asm/nonmatchings/800", func_80018194); +void func_80018194(void *arg0, s32 arg1, u32 arg2) +{ + extern s32 AddPrim(s32, void *); + extern u16 D_800B9A02; + extern struct { s32 a; s32 b[4]; } D_800A651C[]; + void *a3; + s32 sz; + + a3 = arg0; + if (arg2 & 0x40000000) { + *(u32 *)((u8 *)a3 + 4) |= 0x02000000; + } + + sz = arg1; + if ((u32)sz >= 0x1000) { + sz = 0xFFF; + } + + AddPrim(D_800A651C[D_800B9A02].a + sz * 4, a3); +} INCLUDE_ASM("asm/nonmatchings/800", func_8001820C); @@ -5477,7 +5519,26 @@ INCLUDE_ASM("asm/nonmatchings/800", CdReadSectorReadyCB); INCLUDE_ASM("asm/nonmatchings/800", func_8001A9D8); -INCLUDE_ASM("asm/nonmatchings/800", func_8001A9F8); + +void func_8001A9F8(s32 a0) +{ + extern u16 D_800B9A02; + extern u8 D_800A6610[]; + extern u32 D_80063108; + extern u32 D_80063120; + + u32 *p = (u32 *)(D_800A6610 + (D_800B9A02 << 14)); + u32 *q1; + u32 *q2; + + q1 = &D_80063108; + *q1 = (p[1] & 0xFFFFFF) | 0x5000000; + p[1] = (p[1] & 0xFF000000) | ((u32)q1 & 0xFFFFFF); + + q2 = &D_80063120; + *q2 = (p[1] & 0xFFFFFF) | 0x5000000; + p[1] = (p[1] & 0xFF000000) | ((u32)q2 & 0xFFFFFF); +} extern s32 cdReq_curSector; s32 func_8001AA78(void) { @@ -6700,7 +6761,31 @@ void func_8001CA1C(void *a0, void *a1) *(s32 *)((s32)s0 + 0x20) = (s32)s2; } -INCLUDE_ASM("asm/nonmatchings/800", func_8001CA88); +extern void func_8001C9D0(void); +extern void func_80052D90(s32 a0, void *a1); +extern void func_80054514(s32 a0, s32 a1); + +void func_8001CA88(s32 a0, s32 a1) +{ + s32 local_10[8]; + s32 s0_val = a0; + s32 s2_val = a1; + s32 s1_val; + + func_8001C9D0(); + + s1_val = s0_val + 0x30; + *(s16 *)s0_val = 1; + *(s16 *)(s0_val + 0x2) = 4; + + func_80052D90(0, (void *)s1_val); + func_80054514(s1_val, (s32)&local_10[0]); + + *(s32 *)(s0_val + 0x20) = s2_val; + *(s32 *)(s0_val + 0x74) = 0; + *(s16 *)(s0_val + 0xE) = 0; + *(s16 *)(s0_val + 0x1E) = 0; +} extern void func_8001CF48(s32 a0); @@ -7679,11 +7764,39 @@ void func_8001F730(s32 a0, void *a1, void *a2) void func_8001F974(void) { } -INCLUDE_ASM("asm/nonmatchings/800", func_8001F97C); +void func_8001F97C(void *a0) +{ + extern void func_80020F34(s32 a0, s32 a1); + s32 t1, t2, t3; + + func_80020DA4((s32)((u8 *)a0 + 0x10), (s32)((u8 *)a0 + 0x34)); + + if (*(u16 *)((u8 *)a0 + 0x2C) & 0x10) { + func_80020F34((s32)((u8 *)a0 + 0x34), (s32)((u8 *)a0 + 0x18)); + } + + t1 = *(s16 *)((u8 *)a0 + 0x08); + t2 = *(s16 *)((u8 *)a0 + 0x0A); + t3 = *(s16 *)((u8 *)a0 + 0x0C); + *(s32 *)((u8 *)a0 + 0x48) = t1; + *(s32 *)((u8 *)a0 + 0x4C) = t2; + *(s32 *)((u8 *)a0 + 0x50) = t3; + *(u16 *)((u8 *)a0 + 0x2C) |= 1; +} INCLUDE_ASM("asm/nonmatchings/800", func_8001F9F8); -INCLUDE_ASM("asm/nonmatchings/800", func_8001FB8C); +extern void (*D_80063500[])(); + +void func_8001FB8C(s32 *a0, s32 *a1) +{ + if (a0[1] < 0) return; + if (*(u16 *)a0 != 1) return; + if (*(u16 *)((u8 *)a0 + 2) < 9) { + D_80063500[*(u16 *)((u8 *)a0 + 2)](a0); + a1[0]++; + } +} INCLUDE_ASM("asm/nonmatchings/800", func_8001FC08); @@ -11909,7 +12022,19 @@ void func_80029664(void) { INCLUDE_ASM("asm/nonmatchings/800", func_80029690); -INCLUDE_ASM("asm/nonmatchings/800", func_800296F8); +typedef struct { + s32 w[9]; +} Blk36_800296F8; + +extern void func_80029774(s32); +extern Blk36_800296F8 D_80079204; +extern s32 D_800A5E5C; + +s32 func_800296F8(s32 arg0) { + func_80029774(1); + D_80079204 = *(Blk36_800296F8 *)arg0; + return D_800A5E5C = 1; +} INCLUDE_ASM("asm/nonmatchings/800", func_80029774); @@ -11954,7 +12079,33 @@ s32 func_80029CD4(s32 a0) { return rand() % a0; } -INCLUDE_ASM("asm/nonmatchings/800", func_80029D3C); +/* func_80029D3C — banked candidate, rounds 1-9. + * Canonical s32(void) def per engine_core.h caller macros; incoming $a0 + * bridged via register pins ($4 -> $16) because the prototype takes no + * named parameters. Clamp MUST stay a ternary: an if/else spelling moves + * ret into $a0 and breaks the early-exit delay-slot chain (verified R9). + * Divisor 4800 forced by choose_multiplier arithmetic on M=0x1B4E81B5,l=9. + */ +extern s32 func_8002A4FC(s32 a0); + +s32 func_80029D3C(void) { + register s32 n __asm__("$4"); + register s32 s0 __asm__("$16"); + s32 p; + s32 q; + s32 ret; + + __asm__("" : "=r"(n)); + s0 = n; + if (s0 <= 0) { + ret = 0; + } else { + p = func_8002A4FC(s0) * 60; + q = s0 - s0 * p / 4800; + ret = q > 0 ? q : 1; + } + return ret; +} INCLUDE_ASM("asm/nonmatchings/800", func_80029DB4); @@ -13527,7 +13678,31 @@ void func_8002E700(s32 a0) D_800A4E8A = D_8006A9B0[index]; } -INCLUDE_ASM("asm/nonmatchings/800", func_8002E79C); +void func_8002E79C(s32 a0) +{ + extern u8 D_800A4EE6; + extern u16 D_800A4EE0; + extern u16 D_800A4EE2; + extern u16 D_800A4EE4; + extern u16 D_8006A9C8[]; + u8 *fl; + u16 v; + + fl = &D_800A4EE6; + if (!(*fl & 2)) { + *fl |= 2; + if (!(*fl & 4)) { + v = (u16)a0; + if (v >= 5) { + v = 4; + } + D_800A4EE0 = 0x4000; + D_800A4EE4 = 0x2FFF; + D_800A4EE2 = D_8006A9C8[v]; + *fl |= 3; + } + } +} void func_8002E818(s32 a0) { @@ -13770,7 +13945,28 @@ void func_8002ED90(void) { } } -INCLUDE_ASM("asm/nonmatchings/800", func_8002EDE4); +extern void func_8002EE90(void); +extern void func_80031CC8(void); +extern void func_8002EC10(void); +extern void func_800385C0(s16); +extern u16 D_800A4EA2; +extern s16 D_800A4E9A; +extern u8 D_800A4EE6; +extern s16 D_800A4EF6; + +void func_8002EDE4(void) { + func_8002EE90(); + func_80031CC8(); + func_8002EC10(); + + if (D_800A4EA2 & 0x4) { + func_800385C0(D_800A4E9A); + D_800A4EA2 = 0; + } + + D_800A4EF6 = 1; + D_800A4EE6 &= 0xF9; +} INCLUDE_ASM("asm/nonmatchings/800", func_8002EE64); @@ -13892,7 +14088,43 @@ void func_8002F12C(s32 a0) { INCLUDE_ASM("asm/nonmatchings/800", func_8002F150); -INCLUDE_ASM("asm/nonmatchings/800", func_8002F1CC); +typedef struct F1ccRec { + u8 pad[0x0E]; + u8 flg[8]; + u8 tail[0x3E]; +} F1ccRec; + +typedef struct F1ccSlot { + u8 pad[0x20]; + u32 u20; + u32 u24; + u32 u28; + u32 u2C; + u16 u30; + u8 mid[5]; + u8 u37; + u8 u38; + u8 tail[0x1B]; +} F1ccSlot; + +extern u8 D_800A4694[]; + +void func_8002F1CC(s32 arg0) { + F1ccRec *sp = (F1ccRec *)D_800A4694 + arg0; + F1ccSlot *slots = (F1ccSlot *)(D_800A4694 + 0x2F4); + s32 i; + s32 val; + + for (i = 0, val = 0x18; i < 8; i++) { + if (sp->flg[i]) { + slots[i].u28 = slots[i].u20 + 0x100; + slots[i].u37 |= 1; + slots[i].u30 = 0; + slots[i].u38 = 0; + slots[i].u2C = val; + } + } +} INCLUDE_ASM("asm/nonmatchings/800", func_8002F248); @@ -16651,7 +16883,24 @@ void func_80036EE8(void) { D_800A4F1A = 0; } -INCLUDE_ASM("asm/nonmatchings/800", func_80036F18); +extern s32 D_800C6D28; +extern s32 D_80078F10; +extern s32 D_800A63E8; +extern s32 D_8006AEE8; +extern void func_80034DFC(short); + +void func_80036F18(void) { + s32 i; + + if (D_8006AEE8 != 0) { + D_800C6D28 = D_800A63E8; + for (i = 0; i < D_8006AEE8; i++) { + func_80034DFC(*(short *)(&D_80078F10 + i)); + (&D_80078F10)[i] = 0; + } + D_8006AEE8 = 0; + } +} extern s32 D_80078F10; extern s32 D_8006AEE8; @@ -17024,7 +17273,29 @@ s32 func_8003750C(void) { } } -INCLUDE_ASM("asm/nonmatchings/800", func_8003775C); +typedef struct { u8 v; } W8_; +extern W8_ D_80076242_ __asm__("D_80076242"); + +extern u8 D_8006AEF4; +extern s32 func_8003C4F0(s32); +extern void func_800373D0(void); + +int func_8003775C(void) { + u32 t; + + if (D_80076242_.v != 0) { + if (func_8003C4F0(0) == 0) { + return 0; + } + D_80076242_.v = 0; + t = D_8006AEF4; + } else { + t = D_8006AEF4; + } + D_8006AEF4 = t & 0xFC; + func_800373D0(); + return 1; +} INCLUDE_ASM("asm/nonmatchings/800", func_800377D8); @@ -17300,7 +17571,25 @@ INCLUDE_ASM("asm/nonmatchings/800", func_800383A4); INCLUDE_ASM("asm/nonmatchings/800", func_800384A8); -INCLUDE_ASM("asm/nonmatchings/800", func_800385C0); +void func_800385C0(s16 a0) +{ + extern u8 D_800C6E2A[]; + extern u8 D_800B9ED2[]; + extern u8 D_800B9ED3[]; + register s32 a0v __asm__("$4"); + register u8 *v1 __asm__("$3"); + s32 a1; + + for (a1 = 0, v1 = D_800C6E2A; a1 < 0x10; a1++, v1 += 0x60) { + if (v1[2] != 0 && *(s16 *)(*(s32 *)(v1 - 0xA) + 0x1F0) == a0v) { + v1[2] = 0; + v1[0] = 0; + } + } + + D_800B9ED2[((a0v << 7) - a0v) << 2] = 0; + D_800B9ED3[((a0v << 7) - a0v) << 2] = 0; +} extern u8 D_800B9E92[]; diff --git a/src/800b2.c b/src/800b2.c index 2a1d435bf..be820d963 100644 --- a/src/800b2.c +++ b/src/800b2.c @@ -470,7 +470,149 @@ void *GsTMDfastF4GL(void) ); } -INCLUDE_ASM("asm/nonmatchings/800b2", GsTMDfastF4GNL); +/* GsTMDfastF4GNL @ 0x80058284 -- HANDWRITTEN PsyQ libgs TMD primitive walker + * (flat, 4-vertex, lit, non-textured "fast" path). Splat marks it "Handwritten + * function": raw GTE code (rtpt/nclip/rtps/avsz4), direct lwc2/swc2 to numbered + * cop2 data registers, cfc2 $31, hand-filled branch delay slots and explicit + * load-latency nops, 8 arguments (4 in $a0-$a3, 4 on the stack), allocation in + * $t0-$t9 only. Not expressible as compiler-generated C; reproduced verbatim + * the way the project's other handwritten GTE bodies are (see GsTMDfastG3GL + * above): one __asm__ __volatile__ block under .set noreorder. gcc supplies the + * label, the 8-byte frame for the two-word flag/otz scratch pair, and the + * trailing "jr $ra / nop" epilogue -- exactly the target's head and tail. + * GTE compute ops are written as `cop2 ` (binutils has no mnemonics): + * rtpt = 0x4A280030 -> cop2 0x0280030 + * nclip = 0x4B400006 -> cop2 0x1400006 + * rtps = 0x4A180001 -> cop2 0x0180001 + * avsz4 = 0x4B68002E -> cop2 0x168002E + * No relocations and no symbol references: the body touches only its arguments, + * the stack scratch pair and the GTE. */ +void *GsTMDfastF4GNL() +{ + volatile int g[2]; + + __asm__ __volatile__( + ".set\tnoreorder\n" + "lw $24, 24($29)\n" + "lw $2, 28($29)\n" + "lw $3, 32($29)\n" + "lw $8, 36($29)\n" + "lw $3, 4($3)\n" + "addu $10, $0, $0\n" + "sw $2, 12($8)\n" + "blez $24, 2f\n" + " sw $3, 16($8)\n" + "lui $11, 0xFF\n" + "ori $11, $11, 0xFFFF\n" + "addiu $14, $8, 40\n" + "lui $15, 0x8000\n" + "addiu $13, $8, 24\n" + "addiu $6, $4, 16\n" + "addiu $9, $7, 28\n" + "1:\n" + "lhu $4, 6($6)\n" + "lhu $3, 8($6)\n" + "lhu $2, 10($6)\n" + "sll $4, $4, 3\n" + "addu $4, $5, $4\n" + "sll $3, $3, 3\n" + "addu $3, $5, $3\n" + "sll $2, $2, 3\n" + "addu $2, $5, $2\n" + "lwc2 $0, 0($4)\n" + "lwc2 $1, 4($4)\n" + "lwc2 $2, 0($3)\n" + "lwc2 $3, 4($3)\n" + "lwc2 $4, 0($2)\n" + "lwc2 $5, 4($2)\n" + "nop\n" + "nop\n" + "cop2 0x0280030\n" /* rtpt */ + "lw $2, -12($6)\n" + "nop\n" + "and $2, $2, $11\n" + "sw $2, -24($9)\n" + "lbu $2, -13($6)\n" + "nop\n" + "ori $2, $2, 0x10\n" + "sb $2, -21($9)\n" + "cfc2 $12, $31\n" + "nop\n" + "sw $12, 0($14)\n" + "lw $2, 40($8)\n" + "nop\n" + "and $2, $2, $15\n" + "bnez $2, 3f\n" + " nop\n" + "nop\n" + "nop\n" + "cop2 0x1400006\n" /* nclip */ + "lw $2, -8($6)\n" + "nop\n" + "sw $2, -16($9)\n" + "swc2 $24, 0($13)\n" + "lw $2, 24($8)\n" + "nop\n" + "blez $2, 3f\n" + " nop\n" + "swc2 $12, 8($7)\n" + "swc2 $13, 16($7)\n" + "swc2 $14, 24($7)\n" + "lhu $2, 12($6)\n" + "nop\n" + "sll $2, $2, 3\n" + "addu $2, $5, $2\n" + "lwc2 $0, 0($2)\n" + "lwc2 $1, 4($2)\n" + "nop\n" + "nop\n" + "cop2 0x0180001\n" /* rtps */ + "lw $2, -4($6)\n" + "nop\n" + "sw $2, -8($9)\n" + "cfc2 $12, $31\n" + "nop\n" + "sw $12, 0($14)\n" + "lw $2, 40($8)\n" + "nop\n" + "and $2, $2, $15\n" + "bnez $2, 3f\n" + " addiu $2, $7, 32\n" + "swc2 $14, 0($2)\n" + "nop\n" + "nop\n" + "cop2 0x168002E\n" /* avsz4 */ + "lw $2, 0($6)\n" + "nop\n" + "sw $2, 0($9)\n" + "swc2 $7, 0($13)\n" + "lw $3, 24($8)\n" + "lw $2, 12($8)\n" + "addiu $9, $9, 36\n" + "srav $3, $3, $2\n" + "lw $2, 16($8)\n" + "sll $3, $3, 2\n" + "addu $2, $2, $3\n" + "sw $2, 56($8)\n" + "lw $3, 0($2)\n" + "lui $2, 0x800\n" + "and $3, $3, $11\n" + "or $3, $3, $2\n" + "sw $3, 0($7)\n" + "and $3, $7, $11\n" + "lw $2, 56($8)\n" + "addiu $7, $7, 36\n" + "sw $3, 0($2)\n" + "3:\n" + "addiu $10, $10, 1\n" + "slt $2, $10, $24\n" + "bnez $2, 1b\n" + " addiu $6, $6, 32\n" + "2:\n" + "addu $2, $7, $0\n" + ".set\treorder\n" + : : : "memory"); +} /* diff --git a/src/800b_2.c b/src/800b_2.c index 80f974b32..6b5579472 100644 --- a/src/800b_2.c +++ b/src/800b_2.c @@ -87,7 +87,24 @@ s32 *Square12(s32 *a0, s32 *a1) return a1; } -INCLUDE_ASM("asm/nonmatchings/800b_2", Square0); +s32 *Square0(s32 *a0, s32 *a1) +{ + register s32 *out __asm__("$5"); + out = a1; + __asm__ __volatile__( + ".set\tnoreorder\n" + "lwc2 $9, 0(%0)\n" + "lwc2 $10, 4(%0)\n" + "lwc2 $11, 8(%0)\n" + "nop\n" + "sqr 0\n" + "swc2 $25, 0(%1)\n" + "swc2 $26, 4(%1)\n" + "swc2 $27, 8(%1)\n" + ".set\treorder\n" + : : "r"(a0), "r"(out) : "$9", "$10", "$11", "memory"); + return a1; +} void AverageZ3() { diff --git a/src/800c2_2.c b/src/800c2_2.c index 2c05caf66..015f338a9 100644 --- a/src/800c2_2.c +++ b/src/800c2_2.c @@ -120,4 +120,20 @@ s32 func_800625DC(void) { return 0; } -INCLUDE_ASM("asm/nonmatchings/800c2_2", func_80062644); +s32 func_80062644(void) { + extern s32 *D_80072A2C; + s32 *p = D_80072A2C; + + if ((p[1] & 1) == 0) { + return 0; + } + if ((p[0] & 1) != 0) { + return 1; + } + if ((p[0] & 1) != 0) { + return 1; + } + return 0; +} + +__asm__(".word 0x00000000\n"); diff --git a/src/gsgap3.c b/src/gsgap3.c index 58f458531..9f875164c 100644 --- a/src/gsgap3.c +++ b/src/gsgap3.c @@ -90,7 +90,36 @@ void func_80052654(u16 w, u16 h, u16 intmode, u16 dither, u16 varh) func_80059FC0((u8 *)q); } -INCLUDE_ASM("asm/nonmatchings/gsgap3", GsInitGraph2); +extern s16 D_800A644C; +extern u8 D_800A644E; +extern u8 D_800A644F; +extern u8 D_800A6450; +extern s16 D_800A649C; +extern s16 D_800A649E; +extern u8 D_800A64A8; +extern u8 D_800A64A9; +extern s16 D_800C7C88; + +void func_8005283C(s32 a0, s32 a1); + +/* hostile fleet-canonical prototype, as carried by caller TUs */ +void GsInitGraph2(s32 w, s32 h, s32 mode, s32 a3, s32 st); + +void GsInitGraph2_body(u16 w, u16 h, u16 intmode, u16 dither, u16 varh) __asm__("GsInitGraph2"); + +void GsInitGraph2_body(u16 w, u16 h, u16 intmode, u16 dither, u16 varh) +{ + D_800A649C = w; + D_800A649E = h; + D_800A644C = 0; + D_800A644E = dither; + D_800A644F = 0; + D_800A6450 = 0; + D_800A64A8 = intmode & 1; + D_800C7C88 = intmode & 4; + D_800A64A9 = varh; + func_8005283C(w, h); +} typedef struct { @@ -266,4 +295,25 @@ __asm__( ".end\tGsSortClear\n" ); -INCLUDE_ASM("asm/nonmatchings/gsgap3", GS_001_OBJ_5D0); +__asm__( + ".text\n" + ".align\t2\n" + ".globl\tGS_001_OBJ_5D0\n" + ".ent\tGS_001_OBJ_5D0\n" + "GS_001_OBJ_5D0:\n" + ".set\tnoreorder\n" + "lui $2, %hi(D_80078810)\n" + "addiu $2, $2, %lo(D_80078810)\n" + "lui $5, %hi(D_800C7C74)\n" + "lh $5, %lo(D_800C7C74)($5)\n" + "lw $4, 16($7)\n" + "sll $5, $5, 4\n" + "jal AddPrim\n" + "addu $5, $5, $2\n" + "lw $31, 16($sp)\n" + "addiu $sp, $sp, 24\n" + "jr $31\n" + "nop\n" + ".set\treorder\n" + ".end\tGS_001_OBJ_5D0\n" +);