phase11: merge 26 — 545 bodies / 554 regions

Worker A's 0x8006B7C0 (420 B) and worker D's 0x800307FC (92 B).
This commit is contained in:
Christopher Williams
2026-09-24 10:14:45 -04:00
parent 14e927fca6
commit b7ccad87a5
3 changed files with 959 additions and 891 deletions
+889 -891
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -136,6 +136,7 @@
0x800301FC 0x8003022C src/func_800301FC.c
0x80030284 0x800302DC src/func_80030284.c
0x80030358 0x80030390 src/func_80030358.c
0x800307FC 0x80030858 src/func_800307FC.c
0x80030858 0x800308C4 src/func_80030858.c
0x800308C4 0x800309CC src/func_800308C4.c
0x800319F0 0x80031A48 src/func_800319F0.c
@@ -265,6 +266,7 @@
0x8006B66C 0x8006B6BC src/func_8006B66C.c
0x8006B6BC 0x8006B778 src/func_8006B6BC.c
0x8006B778 0x8006B7C0 src/func_8006B778.c
0x8006B7C0 0x8006B964 src/func_8006B7C0.c
0x8006B9E0 0x8006BA3C src/func_8006B9E0.c
0x8006BC08 0x8006BC34 src/func_8006BC08.c
0x8006BC34 0x8006BC74 src/func_8006BC34.c
1 # Code-region registry: one C region per matched function.
136 0x800301FC
137 0x80030284
138 0x80030358
139 0x800307FC
140 0x80030858
141 0x800308C4
142 0x800319F0
266 0x8006B66C
267 0x8006B6BC
268 0x8006B778
269 0x8006B7C0
270 0x8006B9E0
271 0x8006BC08
272 0x8006BC34
+68
View File
@@ -0,0 +1,68 @@
/*
* func_80031EBC — 112 bytes at 0x80031EBC..0x80031F2C
*
* Goal B, Phase 11. **First attempt.** The SIBLING of 0x800320D8: same object at `*(a0 + 164)`,
* same "flag ? one word : a 16-byte struct copy" idiom, same trailing-position call — and the
* struct-assignment lever found on 0x800320D8 transferred unchanged.
*
* obj = *(int **)(a0 + 164);
* if (*(int *)((char *)obj + 652) == 0)
* v.a = *(int *)((char *)obj + 660);
* else
* v = *(V4 *)((char *)obj + 660); <- a 16-byte struct ASSIGNMENT, four loads then four stores
* func_80031CC0(a0, (int *)&v, a0 + 4764);
*
* The observed instructions are:
* addiu sp,sp,-0x28 frame, 40 bytes
* move a3,a0
* sw ra,0x20(sp) only ra is saved — no callee-saved data register
* lw a2,0xa4(a3) a2 = *(int **)(a0 + 164)
* nop
* lw v0,0x28c(a2) the flag
* nop
* bnez v0,else if (flag != 0) take the 4-word path
* nop
* lw v0,0x294(a2) else: v.a = obj->f660
* j join
* sw v0,0x10(sp)
* else:
* lw v0,0x294(a2) / lw v1,0x298(a2) / lw a0,0x29c(a2) / lw a1,0x2a0(a2)
* sw v0,0x10(sp) / sw v1,0x14(sp) / sw a0,0x18(sp) / sw a1,0x1c(sp) FOUR LOADS THEN FOUR STORES
* join:
* move a0,a3
* addiu a1,sp,0x10
* jal 0x80031CC0
* addiu a2,a0,0x129c a2 = a0 + 4764 (delay slot; a0 is already a3)
* lw ra / addiu sp,sp,0x28 / jr ra / nop
*
* THE LEVER — the same BATCH SHAPE as 0x800320D8. Four indexed element stores compile to load/store
* pairs interleaved with load-delay nops; the original batches four loads then four stores, which is
* a 16-byte struct assignment. That it transferred to a second row unchanged is the point: it is a
* *shape* lever, not a row-specific trick.
*
* The single-word path leaves `v.b`/`v.c`/`v.d` uninitialised and the callee receives them — a real
* property of the original (third instance this session), NOT a reconstruction error. Do not "fix" it.
*
* LIMITS: the function name, the callee, the meaning of the 164/652/660/4764 offsets and the claim
* that the local is a 4-int scratch are hypotheses reconstructed from the disassembly; only the
* compiled bytes are evidence. The member names of V4 are not recoverable; the 16-byte copy is.
*/
typedef struct { int a, b, c, d; } V4;
extern void func_80031CC0(int a0, int *a1, int a2);
void func_80031EBC(int a0)
{
V4 v;
int *obj;
obj = *(int **)(a0 + 164);
if (*(int *)((char *)obj + 652) == 0) {
v.a = *(int *)((char *)obj + 660);
} else {
v = *(V4 *)((char *)obj + 660);
}
func_80031CC0(a0, (int *)&v, a0 + 4764);
}