feat(md): bank the 4 -O0-stranded functions — and the class is now essentially empty

md_MAIN_011:func_800CF28C · md_MAIN_003:func_800D0268/func_800D0740/func_800D0C50, all byte-verified
from a clean rebuild and counted from the SOURCE: md_MAIN_011 is now FULLY MATCHED (0 open stubs),
md_MAIN_003 is down to 1 (func_800CF3E8).

THE PREMISE I HANDED THE AGENT WAS WRONG, AND IT SAID SO. md_MAIN_011 is already a whole-object -O0
module — no carve was needed. Its real blocker was tools/jtbl_rodata_pads._s_rodata_span ignoring a
trailing `.align`, the SAME defect this session fixed for md_SC07_003 from the other direction: two
agents converged on it independently. Adopted this agent's stricter form (only a TRULY trailing
align rounds `hi`; an interior one is followed by data that sets `hi` higher anyway).

Note WHY it stayed latent: `derive`'s zero_gap self-corrects a 1-3 byte undershoot whenever the next
stream item is an anchor. A C jump table has NO anchor — so the bug can only fire the moment someone
banks a switch function into such an object, and when it fires it accuses the CARVE ("island layout
drift"), not itself.

md_MAIN_003 needed one new -O0 object, and the boundary I proposed (0x1f74 -> 0x1e58) was both too
narrow and off by 0x2B8. The carve made is `md_MAIN_003_o0e` at 0x1308 (vram 0x800D0100) running to
the existing o0c boundary: everything in that span is a §265 verbatim __asm__ body or an INCLUDE_ASM
stub — zero optimizable C — so the whole tail flips with one cut. Proved byte-identical with NOTHING
banked first (§431 discipline), then the three drafts gated one at a time.

TWO MORE GENERAL DEFECTS FIXED IN jr_isolate_all, both of which silently mis-place a boundary:
 * an item-less CLOSING region emitted a duplicate `- [off, c, …]` line and the validator refused;
   the empty-region skip covered only region 0, and `_partition`'s empty `footer` made the closing
   region look non-empty.
 * A §265 VERBATIM __asm__ BODY IS PREAMBLE, AND PREAMBLE IS ASSUMED BYTE-NEUTRAL. It is not — it
   emits bytes. `parse_overlay_c` has four addressed-anchor forms and a verbatim body is none of
   them, so it attaches to the NEXT anchor: cutting at func_800D0268 would have moved 0x168 bytes of
   other functions into the new object while the yaml claimed the region starts higher. New
   `_region_emit_start()` derives the yaml offset from the region's CONTENT (item addresses + every
   .globl/.ent the text names that resolves inside the object) and takes min(cut, emit), so a
   boundary can only move DOWN. Where no verbatim asm is in play it equals the cut — every existing
   isolate is unchanged.

BLAST RADIUS PROVEN, not argued: jtbl_rodata_pads is in the build path (`--derive` for md_*/main),
so the agent rebuilt main + all 70 md_* from scratch (71/71) and then ran the full fleet:
**make check-all 213/213 passed, 0 failed**, main 143dbb89 BYTE-IDENTICAL.

CENSUS, denominator asserted (1057 live stubs, 0 without a .s): exactly ONE -O0-prologue stub
remains stranded in an -O2 TU fleet-wide — main:func_8002C410 in src/800_b.c, 299 ins. Nothing more
should be built for this class; the general tool already existed and what was missing was
correctness, not coverage.
This commit is contained in:
Drew T
2026-09-02 19:23:25 -06:00
parent 3a886b9652
commit 5e10215269
6 changed files with 1176 additions and 700 deletions
+1
View File
@@ -97,6 +97,7 @@ segments:
# - [0x0, rodata, head]
- [0x0, .rodata, md_MAIN_003_jr_800D1E18] # module-id header (+jtbl/ptr table) — §154-A; named for the TU holding ALL island emitters (D_800CEDF8 include, D_800CEE1C asm, MDEC literals, func_800D30D0 with its migrated strings): spimdisasm rodata-migration is same-subseg-only. Renamed _jr_800D12D0 -> _jr_800D1E18 by the S68 func_800D12D0 o0 carve (region0 became md_MAIN_003_o0d; the emitters live in the post region)
- [0xd8, c, md_MAIN_003]
- [0x1308, c, md_MAIN_003_o0e]
- [0x1f74, c, md_MAIN_003_o0c]
- [0x24d8, c, md_MAIN_003_o0d]
- [0x3020, c, md_MAIN_003_jr_800D1E18]
-682
View File
@@ -580,685 +580,3 @@ void func_800CFFEC(void) {
D_800AF6DC = 0;
D_800AF680 = 0;
}
/* func_800D0100 - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue, per-statement scheduling, every delay slot
* a nop) stranded inside md_MAIN_003's -O2 object (sec 261: 116 functions across the
* tree are this class; nothing under src/md_* globs -O0 yet). Same family as the
* already-banked func_800D0440/func_800D05B4/func_800D06BC/func_800D09A0 in this
* exact TU (same $s0 = D_800AF630 far-base idiom, same ra/fp/s0(/s1) save set).
*
* Recovered C semantics for the eventual real -O0-object decomp:
*
* void (*fn)(void) = D_800D363C[*(u16 *)((u8 *)D_800AF630 + 0xA3B4)];
* fn();
*
* S69 provenance: a prior real-C draft (`register u8 *p = D_800AF630; D_800D363C[*(u16*)
* (p+0xA3B4)]();`) reported MATCH under match_one's --auto-o0 (it force-compiles a
* standalone C draft at -O0 on seeing the target's frame-pointer prologue), but
* tools/recover_integration.py's real-cc1 probe against the actual TU (compiled -O2,
* per this object's Makefile globs) came back DIFF 15/29 mismatched -- exactly the
* §261 "shown an -O2 compile of its own C" failure mode: no C draft can bank this
* function inside md_MAIN_003.c's -O2 object. This file-scope verbatim body is
* opt-level-independent (cc1 passes the string through untouched per §265), so it
* reproduces the target bytes regardless of the TU's compile flags. No C externs
* shipped (link-time resolution).
*/
__asm__(".text\n.align 2\n.globl func_800D0100\n.ent\tfunc_800D0100\n"
"func_800D0100:\n.frame $sp,32,$31\n.mask 0xC0030000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 28($sp)\n"
"sw $fp, 24($sp)\n"
"sw $s1, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"lhu $v0, -23628($at)\n"
"nop\n"
"addu $v1, $v0, $zero\n"
"sll $v0, $v1, 2\n"
"lui $v1, %hi(D_800D363C)\n"
"addiu $v1, $v1, %lo(D_800D363C)\n"
"addu $v0, $v0, $v1\n"
"lw $s1, 0($v0)\n"
"nop\n"
"jalr $s1\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 28($sp)\n"
"lw $fp, 24($sp)\n"
"lw $s1, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0100\n");
__asm__(".text\n.align 2\n.globl func_800D0174\n.ent\tfunc_800D0174\n"
"func_800D0174:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sb $v0, -23583($at)\n"
"jal func_8001C044\n"
"nop\n"
"jal func_80015310\n"
"nop\n"
"jal func_8002D858\n"
"nop\n"
"lui $a0, %hi(D_800D93FC)\n"
"addiu $a0, $a0, %lo(D_800D93FC)\n"
"jal func_800183E0\n"
"nop\n"
"lui $at, %hi(D_800EC894)\n"
"sh $zero, %lo(D_800EC894)($at)\n"
"jal func_800D1E18\n"
"nop\n"
"lui $at, %hi(D_800EC8B0)\n"
"sw $v0, %lo(D_800EC8B0)($at)\n"
"jal func_800118AC\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0174\n");
__asm__(".text\n.align 2\n.globl func_800D0204\n.ent\tfunc_800D0204\n"
"func_800D0204:\n.frame $sp,24,$31\n.mask 0xC0000000,-8\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -24\n"
"sw $ra, 20($sp)\n"
"sw $fp, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $v0, %hi(D_800EC8B0)\n"
"lw $v0, %lo(D_800EC8B0)($v0)\n"
"nop\n"
"beqz $v0, .L800D0248\n"
"nop\n"
"jal func_800D1E58\n"
"nop\n"
"jal func_800D0D6C\n"
"nop\n"
"jal func_800118AC\n"
"nop\n"
"j .L800D0250\n"
"nop\n"
".L800D0248:\n"
"jal func_800118AC\n"
"nop\n"
".L800D0250:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 20($sp)\n"
"lw $fp, 16($sp)\n"
"addiu $sp, $sp, 24\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0204\n");
INCLUDE_ASM("asm/md_MAIN_003/nonmatchings/md_MAIN_003", func_800D0268);
__asm__(".text\n.align 2\n.globl func_800D0440\n.ent\tfunc_800D0440\n"
"func_800D0440:\n.frame $sp,40,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -40\n"
"sw $ra, 32($sp)\n"
"sw $fp, 28($sp)\n"
"sw $s0, 24($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"addiu $a0, $zero, 4\n"
"jal func_800167F0\n"
"nop\n"
"andi $v1, $v0, 65535\n"
"beqz $v1, .L800D0590\n"
"nop\n"
"lui $v0, %hi(D_800EC894)\n"
"lh $v0, %lo(D_800EC894)($v0)\n"
"addiu $v1, $zero, 1\n"
"beq $v0, $v1, .L800D04EC\n"
"nop\n"
"slti $v1, $v0, 2\n"
"beqz $v1, .L800D04A4\n"
"nop\n"
"beqz $v0, .L800D04C4\n"
"nop\n"
"j .L800D0560\n"
"nop\n"
".L800D04A4:\n"
"addiu $v1, $zero, 2\n"
"beq $v0, $v1, .L800D0510\n"
"nop\n"
"addiu $v1, $zero, 4\n"
"beq $v0, $v1, .L800D0538\n"
"nop\n"
"j .L800D0560\n"
"nop\n"
".L800D04C4:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 2\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0560\n"
"nop\n"
".L800D04EC:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $zero, -23624($at)\n"
"j .L800D0560\n"
"nop\n"
".L800D0510:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0560\n"
"nop\n"
".L800D0538:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 4\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0560\n"
"nop\n"
".L800D0560:\n"
"sh $zero, 16($fp)\n"
"sh $zero, 18($fp)\n"
"addiu $v0, $zero, 320\n"
"sh $v0, 20($fp)\n"
"addiu $v0, $zero, 480\n"
"sh $v0, 22($fp)\n"
"addiu $a0, $fp, 16\n"
"addu $a1, $zero, $zero\n"
"addu $a2, $zero, $zero\n"
"addu $a3, $zero, $zero\n"
"jal func_80059888\n"
"nop\n"
".L800D0590:\n"
"jal func_800D0D6C\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 32($sp)\n"
"lw $fp, 28($sp)\n"
"lw $s0, 24($sp)\n"
"addiu $sp, $sp, 40\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0440\n");
/* func_800D05B4 - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue) stranded inside md_MAIN_003's -O2 object
* (sec 261/6 -- nothing under src/md_ globs -O0 yet). Recovered C semantics for the
* eventual real decomp (register u8 *s0 = D_800AF630):
*
* func_8001C044();
* func_80015310();
* s0[0xA3E1] = 0;
* D_800EC890 = 0;
* D_800EC8A0 = 1;
* func_800183E0((s32)&D_800D4E6C);
* func_800183E0((s32)&D_800D52BC);
* D_800EC894 = 0;
* D_800EC88C = -1;
* *(u16 *)(s0 + 0xA3B8) = 0;
* func_800118AC();
*
* Siblings func_800D0440/func_800D06BC/func_800D09A0 (same TU) are the same shape
* banked the same way; frame/mask (48/0xC0010000,-16) matches the ra/fp/s0 save set
* used throughout this file's verbatim-asm blocks. No C externs shipped (link-time
* resolution).
*/
__asm__(".text\n.align 2\n.globl func_800D05B4\n.ent\tfunc_800D05B4\n"
"func_800D05B4:\n.frame $sp,48,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -48\n"
"sw $ra, 40($sp)\n"
"sw $fp, 36($sp)\n"
"sw $s0, 32($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"jal func_8001C044\n"
"nop\n"
"jal func_80015310\n"
"nop\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sb $zero, -23583($at)\n"
"lui $at, %hi(D_800EC890)\n"
"sw $zero, %lo(D_800EC890)($at)\n"
"addiu $v0, $zero, 1\n"
"lui $at, %hi(D_800EC8A0)\n"
"sw $v0, %lo(D_800EC8A0)($at)\n"
"lui $a0, %hi(D_800D4E6C)\n"
"addiu $a0, $a0, %lo(D_800D4E6C)\n"
"jal func_800183E0\n"
"nop\n"
"lui $a0, %hi(D_800D52BC)\n"
"addiu $a0, $a0, %lo(D_800D52BC)\n"
"jal func_800183E0\n"
"nop\n"
"lui $at, %hi(D_800EC894)\n"
"sh $zero, %lo(D_800EC894)($at)\n"
"addiu $v0, $zero, -1\n"
"lui $at, %hi(D_800EC88C)\n"
"sw $v0, %lo(D_800EC88C)($at)\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $zero, -23624($at)\n"
"jal func_800118AC\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 40($sp)\n"
"lw $fp, 36($sp)\n"
"lw $s0, 32($sp)\n"
"addiu $sp, $sp, 48\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D05B4\n");
/* func_800D0664 - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue, nop in every delay slot) stranded inside
* md_MAIN_003's -O2 object (sec 261/6 -- this subseg has no -O0 glob; the _o0c/_o0d
* objects start at 0x1f74, past this function's 0x186c). No -O2 C can ever emit this
* prologue, so C drafting cannot converge here -- a prior attempt scored match_one
* MATCH only because the oracle auto-detected -O0, which the real object never uses.
* This body sidesteps that entirely: cc1 passes the string through untouched, so it is
* opt-level-independent -- VERIFIED, not assumed: match_one scores MATCH 22/22 both at
* -O0 (auto) AND under --no-auto-o0 (forced -O2, the level this object really uses).
* match_one still prints its 'CANNOT BANK until the function lives in an -O0 object'
* NOTE here, but that heuristic keys only on (target has -O0 prologue) + (subseg builds
* -O2) and is blind to the draft's FORM; it describes the C lane, not this one. The
* gated-green counterexamples are in this very file: func_800D0440, func_800D05B4 and
* func_800D06BC are all -O0 bodies banked verbatim inside this -O2 subseg.
* Recovered C semantics for the eventual real decomp:
*
* register u8 *s0 = D_800AF630; // hoisted base, never read (sec 6 idiom)
* func_80015310();
* func_800183E0((s32)&D_800D93FC);
* func_800118AC();
*
* Immediate siblings func_800D05B4 (above) and func_800D06BC (below) are the same
* shape banked the same way; frame/mask (40/0xC0010000,-16) derived the same way they
* were -- frame 0x28=40, lowest saved reg $s0 at 0x18=24, 24-40 = -16; save set
* ra/fp/s0 = 0xC0010000. All immediates decimal (maspsx rejects hex in __asm__
* strings). No C externs shipped (link-time resolution, sec 265 / sec 236-1).
*/
__asm__(".text\n.align 2\n.globl func_800D0664\n.ent\tfunc_800D0664\n"
"func_800D0664:\n.frame $sp,40,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -40\n"
"sw $ra, 32($sp)\n"
"sw $fp, 28($sp)\n"
"sw $s0, 24($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"jal func_80015310\n"
"nop\n"
"lui $a0, %hi(D_800D93FC)\n"
"addiu $a0, $a0, %lo(D_800D93FC)\n"
"jal func_800183E0\n"
"nop\n"
"jal func_800118AC\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 32($sp)\n"
"lw $fp, 28($sp)\n"
"lw $s0, 24($sp)\n"
"addiu $sp, $sp, 40\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0664\n");
/* func_800D06BC - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue) stranded inside md_MAIN_003's -O2 object
* (sec 261/6 -- nothing under src/md_ globs -O0 yet). Recovered C semantics for the
* eventual real decomp:
*
* D_800EC890 += 4;
* if (D_800EC890 >= 128) {
* D_800EC890 = 128;
* func_800118AC();
* }
*
* Sibling func_800D09A0 (same TU, few lines below) is the same shape banked the same
* way; frame/mask (32/0xC0010000,-16) copied from it. All immediates decimal
* (maspsx rejects hex in __asm__ strings). No C externs shipped (link-time resolution).
*/
__asm__(".text\n.align 2\n.globl func_800D06BC\n.ent\tfunc_800D06BC\n"
"func_800D06BC:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"jal func_800D12D0\n"
"nop\n"
"lui $v0, %hi(D_800EC890)\n"
"lw $v0, %lo(D_800EC890)($v0)\n"
"nop\n"
"addiu $v1, $v0, 4\n"
"lui $at, %hi(D_800EC890)\n"
"sw $v1, %lo(D_800EC890)($at)\n"
"lui $v0, %hi(D_800EC890)\n"
"lw $v0, %lo(D_800EC890)($v0)\n"
"nop\n"
"slti $v1, $v0, 128\n"
"bnez $v1, .L800D0724\n"
"nop\n"
"addiu $v0, $zero, 128\n"
"lui $at, %hi(D_800EC890)\n"
"sw $v0, %lo(D_800EC890)($at)\n"
"jal func_800118AC\n"
"nop\n"
".L800D0724:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D06BC\n");
INCLUDE_ASM("asm/md_MAIN_003/nonmatchings/md_MAIN_003", func_800D0740);
__asm__(".text\n.align 2\n.globl func_800D09A0\n.ent\tfunc_800D09A0\n"
"func_800D09A0:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"jal func_800D12D0\n"
"nop\n"
"lui $v0, %hi(D_800EC898)\n"
"lhu $v0, %lo(D_800EC898)($v0)\n"
"nop\n"
"addiu $v1, $v0, 1\n"
"addu $v0, $v1, $zero\n"
"lui $at, %hi(D_800EC898)\n"
"sh $v0, %lo(D_800EC898)($at)\n"
"lui $v0, %hi(D_800EC898)\n"
"lhu $v0, %lo(D_800EC898)($v0)\n"
"nop\n"
"andi $v1, $v0, 4\n"
"sll $a0, $v1, 16\n"
"sra $v0, $a0, 16\n"
"beqz $v0, .L800D0A24\n"
"nop\n"
"lui $v0, %hi(D_800EC894)\n"
"lh $v0, %lo(D_800EC894)($v0)\n"
"nop\n"
"addu $a0, $v0, $zero\n"
"addiu $a1, $zero, 1\n"
"jal func_800D1D14\n"
"nop\n"
"j .L800D0A40\n"
"nop\n"
".L800D0A24:\n"
"lui $v0, %hi(D_800EC894)\n"
"lh $v0, %lo(D_800EC894)($v0)\n"
"nop\n"
"addu $a0, $v0, $zero\n"
"addu $a1, $zero, $zero\n"
"jal func_800D1D14\n"
"nop\n"
".L800D0A40:\n"
"lui $v0, %hi(D_800EC898)\n"
"lh $v0, %lo(D_800EC898)($v0)\n"
"nop\n"
"slti $v1, $v0, 33\n"
"bnez $v1, .L800D0A60\n"
"nop\n"
"jal func_800118AC\n"
"nop\n"
".L800D0A60:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D09A0\n");
/* func_800D0A7C - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue) stranded inside md_MAIN_003's -O2 object
* (sec 261/6 -- nothing under src/md_ globs -O0 yet). Recovered C semantics for the
* eventual real decomp:
*
* D_800EC890 -= 4;
* if (D_800EC890 < 0) {
* D_800EC890 = 0;
* func_800146B0(1);
* *(s32 *)((u8 *)D_800AF630 + 0xA3E8) = 2;
* func_800118AC();
* } else {
* func_800D12D0();
* }
*
* Siblings func_800D06BC / func_800D09A0 (same TU) are the same shape banked the same
* way; frame/mask (32/0xC0010000,-16) copied from them. All immediates decimal
* (maspsx rejects hex in __asm__ strings). No C externs shipped (link-time resolution).
*/
__asm__(".text\n.align 2\n.globl func_800D0A7C\n.ent\tfunc_800D0A7C\n"
"func_800D0A7C:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"lui $v0, %hi(D_800EC890)\n"
"lw $v0, %lo(D_800EC890)($v0)\n"
"nop\n"
"addiu $v1, $v0, -4\n"
"lui $at, %hi(D_800EC890)\n"
"sw $v1, %lo(D_800EC890)($at)\n"
"lui $v0, %hi(D_800EC890)\n"
"lw $v0, %lo(D_800EC890)($v0)\n"
"nop\n"
"bgez $v0, .L800D0AF8\n"
"nop\n"
"lui $at, %hi(D_800EC890)\n"
"sw $zero, %lo(D_800EC890)($at)\n"
"addiu $a0, $zero, 1\n"
"jal func_800146B0\n"
"nop\n"
"addiu $v0, $zero, 2\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sw $v0, -23576($at)\n"
"jal func_800118AC\n"
"nop\n"
"j .L800D0B00\n"
"nop\n"
".L800D0AF8:\n"
"jal func_800D12D0\n"
"nop\n"
".L800D0B00:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0A7C\n");
/* func_800D0B1C - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue / 21F0A003, a nop in every delay slot,
* per-statement li) stranded inside md_MAIN_003's -O2 object (sec 261: nothing
* under src/md_* globs -O0 yet). Sec 261a addendum (d) names this TU explicitly:
* the fleet's TERMINAL state for an -O0 function stranded in an -O2 TU is the
* sec 265 verbatim-asm block IN THIS TU, not (yet) the sec 18/sec 261 _o0 carve.
* Same family and same save set (ra/fp/s0, frame 32, mask 0xC0010000,-16) as the
* already-banked func_800D0174 / func_800D0204 / func_800D0440 / func_800D06BC /
* func_800D09A0 / func_800D0A7C in this exact file.
*
* Three prior wave agents each reported match_one MATCH 77/77 for the real C body
* below (match_one force-compiles -O0 on seeing the frame-pointer prologue) and
* each was rejected by the whole-binary gate: tools/recover_integration.py's
* real-cc1 probe DIFFs 49/77 because the object's own CC1FLAGS are -O2. That is
* exactly sec 261's "shown an -O2 compile of its own C" failure mode - no C source
* can bank this function while md_MAIN_003.c compiles -O2. A raw __asm__ body is
* opt-level-independent (cc1 passes the string through untouched), so it emits the
* target bytes regardless of the TU's compile flags.
*
* Recovered C semantics for the eventual real -O0-object decomp:
*
* register u8 *s0 = D_800AF630; // sec 127 far-base hi/lo pair
* func_800183E0((s32)&D_800D4E6C);
* switch (D_800EC894) { // extern s16 D_800EC894 (lh)
* case 0: *(u16 *)(s0 + 0xA3B6) = 1; *(u16 *)(s0 + 0xA3B8) = 2; break;
* case 1: *(u16 *)(s0 + 0xA3B6) = 1; *(u16 *)(s0 + 0xA3B8) = 0; break;
* case 2: *(u16 *)(s0 + 0xA3B6) = 1; *(u16 *)(s0 + 0xA3B8) = 1; break;
* case 4: *(u16 *)(s0 + 0xA3B6) = 1; *(u16 *)(s0 + 0xA3B8) = 4; break;
* }
*
* All immediates decimal (maspsx rejects hex inside __asm__ strings); -0x5C4A =
* -23626, -0x5C48 = -23624, lui $at,(0x10000>>16) = lui $at,1. No C externs
* shipped (link-time resolution, per sec 265 / sec 236-1).
*/
__asm__(".text\n.align 2\n.globl func_800D0B1C\n.ent\tfunc_800D0B1C\n"
"func_800D0B1C:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"lui $a0, %hi(D_800D4E6C)\n"
"addiu $a0, $a0, %lo(D_800D4E6C)\n"
"jal func_800183E0\n"
"nop\n"
"lui $v0, %hi(D_800EC894)\n"
"lh $v0, %lo(D_800EC894)($v0)\n"
"addiu $v1, $zero, 1\n"
"beq $v0, $v1, .L800D0BC0\n"
"nop\n"
"slti $v1, $v0, 2\n"
"beqz $v1, .L800D0B78\n"
"nop\n"
"beqz $v0, .L800D0B98\n"
"nop\n"
"j .L800D0C34\n"
"nop\n"
".L800D0B78:\n"
"addiu $v1, $zero, 2\n"
"beq $v0, $v1, .L800D0BE4\n"
"nop\n"
"addiu $v1, $zero, 4\n"
"beq $v0, $v1, .L800D0C0C\n"
"nop\n"
"j .L800D0C34\n"
"nop\n"
".L800D0B98:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 2\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0C34\n"
"nop\n"
".L800D0BC0:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $zero, -23624($at)\n"
"j .L800D0C34\n"
"nop\n"
".L800D0BE4:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0C34\n"
"nop\n"
".L800D0C0C:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 4\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0C34\n"
"nop\n"
".L800D0C34:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0B1C\n");
INCLUDE_ASM("asm/md_MAIN_003/nonmatchings/md_MAIN_003", func_800D0C50);
+917
View File
@@ -0,0 +1,917 @@
#include "common.h"
/* ==== Phase-26 §8b carried decl layer (jr_isolate_all.py) ===================
* The file-scope decl environment from earlier code regions of this object —
* file-local types, col-0 decls, DEFINE_func macro externs, and each earlier
* definition's implied prototype (types first, then decls in original order).
* Decls emit no code => byte-neutral. See cookbook §8c. */
extern void (*D_800D3598[])(void);
extern void func_800CEED0(void);
extern u8 D_800B9A11;
extern s32 D_800EC694;
extern s32 D_800EC68C;
extern s16 D_800EC678;
extern s32 D_800EC67C;
extern s32 D_800EC680;
extern s32 D_800EC690;
extern s32 D_800EC698;
extern s32 D_800EC688;
extern s32 D_800EC684;
extern u8 D_800DA48C[];
extern void func_8001C044(void);
extern void func_80015310(void);
extern void func_8002D858(void);
extern s32 func_800D1E18(void);
extern void func_800CFB3C();
extern void func_800118AC(void);
extern void func_800CEF04(void);
extern void func_8001A9F8(s32 a0);
extern s32 CdReadRequest(s32 *a0, void *a1, s32 a2, s32 a3);
extern s32 D_800AE858;
extern void func_800CEFBC(void);
extern s32 D_800B9A18;
extern s32 D_800EC6A0;
extern s32 D_800EC6A4;
extern unsigned char D_800DA48C[];
extern void func_800D1E58(void);
extern void func_800CFFEC(void);
extern void func_800CF010(void);
extern void func_800CF3E8(void);
extern s32 func_800CFC1C();
extern void func_800CF078(void);
extern s32 func_800149E0(s32);
extern s32 func_80014B10(s32);
extern void func_8002D4C8(s32, s32);
extern void func_800CFE00(void);
extern void func_800CF104(void);
extern void func_80059888(void *a0, s32 a1, s32 a2, s32 a3);
extern void func_800CF300(void);
extern void func_800146B0(s32);
extern void func_800118AC();
extern void func_800CF370(void);
extern s8 D_800D52BC[];
extern u16 D_800B99E6;
extern u16 D_800B99E8;
extern void func_800183E0(s32 a0);
extern void func_800CF3A4(void);
extern s32 D_800EC69C;
extern void func_800599B8();
extern void func_800CFB3C(u16 *arg0);
extern s32 func_800CFC1C(u16 *param_1);
extern void func_800599B8(u16 *, u16 *);
extern s32 func_800CFEB4(u16 *arg0);
extern u16 D_800AF7BC;
extern u16 D_800AF7BE;
extern u16 D_800AF7C0;
extern void GsInitGraph2(s32 w, s32 h, s32 mode, s32 a3, s32 st);
extern void func_80053EEC(s32 a0, s32 a1, s32 a2, s32 a3);
extern void func_80059234(s32 a0);
extern void func_80053218(void);
extern void func_800147B8(void);
extern u8 D_800AF6DC;
extern u8 D_800AF680;
/* ==== end §8b carried decl layer ==== */
/* func_800D0100 - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue, per-statement scheduling, every delay slot
* a nop) stranded inside md_MAIN_003's -O2 object (sec 261: 116 functions across the
* tree are this class; nothing under src/md_* globs -O0 yet). Same family as the
* already-banked func_800D0440/func_800D05B4/func_800D06BC/func_800D09A0 in this
* exact TU (same $s0 = D_800AF630 far-base idiom, same ra/fp/s0(/s1) save set).
*
* Recovered C semantics for the eventual real -O0-object decomp:
*
* void (*fn)(void) = D_800D363C[*(u16 *)((u8 *)D_800AF630 + 0xA3B4)];
* fn();
*
* S69 provenance: a prior real-C draft (`register u8 *p = D_800AF630; D_800D363C[*(u16*)
* (p+0xA3B4)]();`) reported MATCH under match_one's --auto-o0 (it force-compiles a
* standalone C draft at -O0 on seeing the target's frame-pointer prologue), but
* tools/recover_integration.py's real-cc1 probe against the actual TU (compiled -O2,
* per this object's Makefile globs) came back DIFF 15/29 mismatched -- exactly the
* §261 "shown an -O2 compile of its own C" failure mode: no C draft can bank this
* function inside md_MAIN_003.c's -O2 object. This file-scope verbatim body is
* opt-level-independent (cc1 passes the string through untouched per §265), so it
* reproduces the target bytes regardless of the TU's compile flags. No C externs
* shipped (link-time resolution).
*/
__asm__(".text\n.align 2\n.globl func_800D0100\n.ent\tfunc_800D0100\n"
"func_800D0100:\n.frame $sp,32,$31\n.mask 0xC0030000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 28($sp)\n"
"sw $fp, 24($sp)\n"
"sw $s1, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"lhu $v0, -23628($at)\n"
"nop\n"
"addu $v1, $v0, $zero\n"
"sll $v0, $v1, 2\n"
"lui $v1, %hi(D_800D363C)\n"
"addiu $v1, $v1, %lo(D_800D363C)\n"
"addu $v0, $v0, $v1\n"
"lw $s1, 0($v0)\n"
"nop\n"
"jalr $s1\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 28($sp)\n"
"lw $fp, 24($sp)\n"
"lw $s1, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0100\n");
__asm__(".text\n.align 2\n.globl func_800D0174\n.ent\tfunc_800D0174\n"
"func_800D0174:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sb $v0, -23583($at)\n"
"jal func_8001C044\n"
"nop\n"
"jal func_80015310\n"
"nop\n"
"jal func_8002D858\n"
"nop\n"
"lui $a0, %hi(D_800D93FC)\n"
"addiu $a0, $a0, %lo(D_800D93FC)\n"
"jal func_800183E0\n"
"nop\n"
"lui $at, %hi(D_800EC894)\n"
"sh $zero, %lo(D_800EC894)($at)\n"
"jal func_800D1E18\n"
"nop\n"
"lui $at, %hi(D_800EC8B0)\n"
"sw $v0, %lo(D_800EC8B0)($at)\n"
"jal func_800118AC\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0174\n");
__asm__(".text\n.align 2\n.globl func_800D0204\n.ent\tfunc_800D0204\n"
"func_800D0204:\n.frame $sp,24,$31\n.mask 0xC0000000,-8\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -24\n"
"sw $ra, 20($sp)\n"
"sw $fp, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $v0, %hi(D_800EC8B0)\n"
"lw $v0, %lo(D_800EC8B0)($v0)\n"
"nop\n"
"beqz $v0, .L800D0248\n"
"nop\n"
"jal func_800D1E58\n"
"nop\n"
"jal func_800D0D6C\n"
"nop\n"
"jal func_800118AC\n"
"nop\n"
"j .L800D0250\n"
"nop\n"
".L800D0248:\n"
"jal func_800118AC\n"
"nop\n"
".L800D0250:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 20($sp)\n"
"lw $fp, 16($sp)\n"
"addiu $sp, $sp, 24\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0204\n");
extern s32 func_800149E0(s32 arg0);
extern u8 D_800AF630[];
extern void func_8002D4C8(s32 arg0, s32 arg1);
extern s16 D_800EC894;
extern void func_800167B8(s32 arg0);
extern void func_800118AC(void);
extern void func_800D0D6C(void);
void func_800D0268(void) {
u16 sp10;
register u8 *p = D_800AF630;
sp10 = func_800149E0(0);
if (sp10 & 0x4000) {
func_8002D4C8(0x9C1, 0);
D_800EC894++;
if (D_800EC894 >= 3) {
D_800EC894 = 0;
}
} else if (sp10 & 0x1000) {
func_8002D4C8(0x9C1, 0);
D_800EC894--;
if (D_800EC894 < 0) {
D_800EC894 = 2;
}
}
switch (D_800EC894) {
case 0:
if (sp10 & 0x800) {
func_8002D4C8(0x9C0, 0);
func_800167B8(4);
func_800118AC();
}
break;
case 1:
case 2:
if (sp10 & 0x800) {
func_8002D4C8(0x9C0, 0);
func_800167B8(4);
func_800118AC();
}
break;
}
func_800D0D6C();
}
__asm__(".text\n.align 2\n.globl func_800D0440\n.ent\tfunc_800D0440\n"
"func_800D0440:\n.frame $sp,40,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -40\n"
"sw $ra, 32($sp)\n"
"sw $fp, 28($sp)\n"
"sw $s0, 24($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"addiu $a0, $zero, 4\n"
"jal func_800167F0\n"
"nop\n"
"andi $v1, $v0, 65535\n"
"beqz $v1, .L800D0590\n"
"nop\n"
"lui $v0, %hi(D_800EC894)\n"
"lh $v0, %lo(D_800EC894)($v0)\n"
"addiu $v1, $zero, 1\n"
"beq $v0, $v1, .L800D04EC\n"
"nop\n"
"slti $v1, $v0, 2\n"
"beqz $v1, .L800D04A4\n"
"nop\n"
"beqz $v0, .L800D04C4\n"
"nop\n"
"j .L800D0560\n"
"nop\n"
".L800D04A4:\n"
"addiu $v1, $zero, 2\n"
"beq $v0, $v1, .L800D0510\n"
"nop\n"
"addiu $v1, $zero, 4\n"
"beq $v0, $v1, .L800D0538\n"
"nop\n"
"j .L800D0560\n"
"nop\n"
".L800D04C4:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 2\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0560\n"
"nop\n"
".L800D04EC:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $zero, -23624($at)\n"
"j .L800D0560\n"
"nop\n"
".L800D0510:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0560\n"
"nop\n"
".L800D0538:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 4\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0560\n"
"nop\n"
".L800D0560:\n"
"sh $zero, 16($fp)\n"
"sh $zero, 18($fp)\n"
"addiu $v0, $zero, 320\n"
"sh $v0, 20($fp)\n"
"addiu $v0, $zero, 480\n"
"sh $v0, 22($fp)\n"
"addiu $a0, $fp, 16\n"
"addu $a1, $zero, $zero\n"
"addu $a2, $zero, $zero\n"
"addu $a3, $zero, $zero\n"
"jal func_80059888\n"
"nop\n"
".L800D0590:\n"
"jal func_800D0D6C\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 32($sp)\n"
"lw $fp, 28($sp)\n"
"lw $s0, 24($sp)\n"
"addiu $sp, $sp, 40\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0440\n");
/* func_800D05B4 - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue) stranded inside md_MAIN_003's -O2 object
* (sec 261/6 -- nothing under src/md_ globs -O0 yet). Recovered C semantics for the
* eventual real decomp (register u8 *s0 = D_800AF630):
*
* func_8001C044();
* func_80015310();
* s0[0xA3E1] = 0;
* D_800EC890 = 0;
* D_800EC8A0 = 1;
* func_800183E0((s32)&D_800D4E6C);
* func_800183E0((s32)&D_800D52BC);
* D_800EC894 = 0;
* D_800EC88C = -1;
* *(u16 *)(s0 + 0xA3B8) = 0;
* func_800118AC();
*
* Siblings func_800D0440/func_800D06BC/func_800D09A0 (same TU) are the same shape
* banked the same way; frame/mask (48/0xC0010000,-16) matches the ra/fp/s0 save set
* used throughout this file's verbatim-asm blocks. No C externs shipped (link-time
* resolution).
*/
__asm__(".text\n.align 2\n.globl func_800D05B4\n.ent\tfunc_800D05B4\n"
"func_800D05B4:\n.frame $sp,48,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -48\n"
"sw $ra, 40($sp)\n"
"sw $fp, 36($sp)\n"
"sw $s0, 32($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"jal func_8001C044\n"
"nop\n"
"jal func_80015310\n"
"nop\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sb $zero, -23583($at)\n"
"lui $at, %hi(D_800EC890)\n"
"sw $zero, %lo(D_800EC890)($at)\n"
"addiu $v0, $zero, 1\n"
"lui $at, %hi(D_800EC8A0)\n"
"sw $v0, %lo(D_800EC8A0)($at)\n"
"lui $a0, %hi(D_800D4E6C)\n"
"addiu $a0, $a0, %lo(D_800D4E6C)\n"
"jal func_800183E0\n"
"nop\n"
"lui $a0, %hi(D_800D52BC)\n"
"addiu $a0, $a0, %lo(D_800D52BC)\n"
"jal func_800183E0\n"
"nop\n"
"lui $at, %hi(D_800EC894)\n"
"sh $zero, %lo(D_800EC894)($at)\n"
"addiu $v0, $zero, -1\n"
"lui $at, %hi(D_800EC88C)\n"
"sw $v0, %lo(D_800EC88C)($at)\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $zero, -23624($at)\n"
"jal func_800118AC\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 40($sp)\n"
"lw $fp, 36($sp)\n"
"lw $s0, 32($sp)\n"
"addiu $sp, $sp, 48\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D05B4\n");
/* func_800D0664 - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue, nop in every delay slot) stranded inside
* md_MAIN_003's -O2 object (sec 261/6 -- this subseg has no -O0 glob; the _o0c/_o0d
* objects start at 0x1f74, past this function's 0x186c). No -O2 C can ever emit this
* prologue, so C drafting cannot converge here -- a prior attempt scored match_one
* MATCH only because the oracle auto-detected -O0, which the real object never uses.
* This body sidesteps that entirely: cc1 passes the string through untouched, so it is
* opt-level-independent -- VERIFIED, not assumed: match_one scores MATCH 22/22 both at
* -O0 (auto) AND under --no-auto-o0 (forced -O2, the level this object really uses).
* match_one still prints its 'CANNOT BANK until the function lives in an -O0 object'
* NOTE here, but that heuristic keys only on (target has -O0 prologue) + (subseg builds
* -O2) and is blind to the draft's FORM; it describes the C lane, not this one. The
* gated-green counterexamples are in this very file: func_800D0440, func_800D05B4 and
* func_800D06BC are all -O0 bodies banked verbatim inside this -O2 subseg.
* Recovered C semantics for the eventual real decomp:
*
* register u8 *s0 = D_800AF630; // hoisted base, never read (sec 6 idiom)
* func_80015310();
* func_800183E0((s32)&D_800D93FC);
* func_800118AC();
*
* Immediate siblings func_800D05B4 (above) and func_800D06BC (below) are the same
* shape banked the same way; frame/mask (40/0xC0010000,-16) derived the same way they
* were -- frame 0x28=40, lowest saved reg $s0 at 0x18=24, 24-40 = -16; save set
* ra/fp/s0 = 0xC0010000. All immediates decimal (maspsx rejects hex in __asm__
* strings). No C externs shipped (link-time resolution, sec 265 / sec 236-1).
*/
__asm__(".text\n.align 2\n.globl func_800D0664\n.ent\tfunc_800D0664\n"
"func_800D0664:\n.frame $sp,40,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -40\n"
"sw $ra, 32($sp)\n"
"sw $fp, 28($sp)\n"
"sw $s0, 24($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"jal func_80015310\n"
"nop\n"
"lui $a0, %hi(D_800D93FC)\n"
"addiu $a0, $a0, %lo(D_800D93FC)\n"
"jal func_800183E0\n"
"nop\n"
"jal func_800118AC\n"
"nop\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 32($sp)\n"
"lw $fp, 28($sp)\n"
"lw $s0, 24($sp)\n"
"addiu $sp, $sp, 40\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0664\n");
/* func_800D06BC - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue) stranded inside md_MAIN_003's -O2 object
* (sec 261/6 -- nothing under src/md_ globs -O0 yet). Recovered C semantics for the
* eventual real decomp:
*
* D_800EC890 += 4;
* if (D_800EC890 >= 128) {
* D_800EC890 = 128;
* func_800118AC();
* }
*
* Sibling func_800D09A0 (same TU, few lines below) is the same shape banked the same
* way; frame/mask (32/0xC0010000,-16) copied from it. All immediates decimal
* (maspsx rejects hex in __asm__ strings). No C externs shipped (link-time resolution).
*/
__asm__(".text\n.align 2\n.globl func_800D06BC\n.ent\tfunc_800D06BC\n"
"func_800D06BC:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"jal func_800D12D0\n"
"nop\n"
"lui $v0, %hi(D_800EC890)\n"
"lw $v0, %lo(D_800EC890)($v0)\n"
"nop\n"
"addiu $v1, $v0, 4\n"
"lui $at, %hi(D_800EC890)\n"
"sw $v1, %lo(D_800EC890)($at)\n"
"lui $v0, %hi(D_800EC890)\n"
"lw $v0, %lo(D_800EC890)($v0)\n"
"nop\n"
"slti $v1, $v0, 128\n"
"bnez $v1, .L800D0724\n"
"nop\n"
"addiu $v0, $zero, 128\n"
"lui $at, %hi(D_800EC890)\n"
"sw $v0, %lo(D_800EC890)($at)\n"
"jal func_800118AC\n"
"nop\n"
".L800D0724:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D06BC\n");
/* func_800D0740 - the pad-driven 3-way menu cursor tick.
*
* -O0 BODY (§261a). match_one force-compiles -O0 on seeing the frame-pointer
* prologue (sw $fp / addu $fp,$sp,$zero) and reports MATCH 152/152. It CANNOT
* bank while md_MAIN_003.c compiles -O2 -- it needs an -O0 object of its own
* (tools/o0_subsplit.py / rollout_o0.py), exactly like the siblings
* func_800D06BC / func_800D09A0 that are banked as §265 verbatim __asm__.
* Its true home is a md_MAIN_003_o0*.c, whose house spellings are copied below.
*
* The three -O0 laws this body rests on:
* - `register u8 *base = D_800AF630;` is the §6 / §127 far-base idiom: never
* read, but it emits the lui/addiu %hi/%lo pair. Here it crosses calls, so
* -O0 gives it a CALLEE-saved reg ($s0) -- unlike the o0c/o0d instances that
* land in $v0 for want of a call.
* - `D_800EC894++` / `--D_800EC88C` AS A STATEMENT routes through
* expand_increment -> expand_assignment(want_value=1) -> store_expr's
* copy_to_reg, which is what emits the extra `addu $v0,$v1,$zero` /
* `addu $v1,$v0,$zero` copy before the store. `x = x + 1;` does NOT emit it.
* The same law lets `if (--D_800EC88C == 0)` test the COPY with no reload.
* - expand_binop's no_extend=1 for add/sub/and makes the s16 global load `lhu`
* when it feeds arithmetic but `lh` (+ signed `slti`, not `sltiu`) when it
* feeds a comparison. A prior draft read that `lhu` as proof of u16 and got
* `sltiu` -- that single mistype cost it 109 instructions.
* - the beqz / bltz / slti 3 / beqz / j ladder is emit_case_nodes on a real
* `switch` whose `case 1:` and `case 2:` share one body (two separate `if`s
* cannot produce the bltz + slti pair).
*
* Verified past match_one's masking (law 1c / §195-D): all 56 relocations are
* symbol-for-symbol identical to the .s, and all 15 edges -- including the four
* internal `j` targets that masked_diff.mask_for zeroes -- were compared
* unmasked against the objdump of the kept object.
*/
extern u16 D_800EC888;
extern s16 D_800EC894;
extern s16 D_800EC898;
extern s32 D_800EC88C;
extern u8 D_800AF630[];
extern void func_800D12D0(void);
extern s32 func_800149E0(s32);
extern void func_8002D4C8(s32, s32);
extern void func_800167B8(s32);
extern void func_800118AC();
void func_800D0740(void) {
register u8 *base = D_800AF630;
s32 sp10;
func_800D12D0();
D_800EC888 = func_800149E0(0);
sp10 = 0;
if (D_800EC888 & 0x4000) {
func_8002D4C8(0x9C1, 0);
sp10 = 1;
D_800EC894++;
if (D_800EC894 >= 3) {
D_800EC894 = 0;
}
} else if (D_800EC888 & 0x1000) {
func_8002D4C8(0x9C1, 0);
sp10 = 1;
D_800EC894--;
if (D_800EC894 < 0) {
D_800EC894 = 2;
}
}
D_800EC898 = 0;
switch (D_800EC894) {
case 0:
if (D_800EC888 & 0x800) {
func_8002D4C8(0x9C0, 0);
func_800167B8(4);
func_800118AC();
}
break;
case 1:
case 2:
if (D_800EC888 & 0x800) {
func_8002D4C8(0x9C0, 0);
func_800167B8(4);
func_800118AC();
}
break;
}
if (D_800EC88C > 0) {
if (--D_800EC88C == 0) {
func_800167B8(4);
D_800EC894 = 4;
func_800118AC();
}
}
}
__asm__(".text\n.align 2\n.globl func_800D09A0\n.ent\tfunc_800D09A0\n"
"func_800D09A0:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"jal func_800D12D0\n"
"nop\n"
"lui $v0, %hi(D_800EC898)\n"
"lhu $v0, %lo(D_800EC898)($v0)\n"
"nop\n"
"addiu $v1, $v0, 1\n"
"addu $v0, $v1, $zero\n"
"lui $at, %hi(D_800EC898)\n"
"sh $v0, %lo(D_800EC898)($at)\n"
"lui $v0, %hi(D_800EC898)\n"
"lhu $v0, %lo(D_800EC898)($v0)\n"
"nop\n"
"andi $v1, $v0, 4\n"
"sll $a0, $v1, 16\n"
"sra $v0, $a0, 16\n"
"beqz $v0, .L800D0A24\n"
"nop\n"
"lui $v0, %hi(D_800EC894)\n"
"lh $v0, %lo(D_800EC894)($v0)\n"
"nop\n"
"addu $a0, $v0, $zero\n"
"addiu $a1, $zero, 1\n"
"jal func_800D1D14\n"
"nop\n"
"j .L800D0A40\n"
"nop\n"
".L800D0A24:\n"
"lui $v0, %hi(D_800EC894)\n"
"lh $v0, %lo(D_800EC894)($v0)\n"
"nop\n"
"addu $a0, $v0, $zero\n"
"addu $a1, $zero, $zero\n"
"jal func_800D1D14\n"
"nop\n"
".L800D0A40:\n"
"lui $v0, %hi(D_800EC898)\n"
"lh $v0, %lo(D_800EC898)($v0)\n"
"nop\n"
"slti $v1, $v0, 33\n"
"bnez $v1, .L800D0A60\n"
"nop\n"
"jal func_800118AC\n"
"nop\n"
".L800D0A60:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D09A0\n");
/* func_800D0A7C - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue) stranded inside md_MAIN_003's -O2 object
* (sec 261/6 -- nothing under src/md_ globs -O0 yet). Recovered C semantics for the
* eventual real decomp:
*
* D_800EC890 -= 4;
* if (D_800EC890 < 0) {
* D_800EC890 = 0;
* func_800146B0(1);
* *(s32 *)((u8 *)D_800AF630 + 0xA3E8) = 2;
* func_800118AC();
* } else {
* func_800D12D0();
* }
*
* Siblings func_800D06BC / func_800D09A0 (same TU) are the same shape banked the same
* way; frame/mask (32/0xC0010000,-16) copied from them. All immediates decimal
* (maspsx rejects hex in __asm__ strings). No C externs shipped (link-time resolution).
*/
__asm__(".text\n.align 2\n.globl func_800D0A7C\n.ent\tfunc_800D0A7C\n"
"func_800D0A7C:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"lui $v0, %hi(D_800EC890)\n"
"lw $v0, %lo(D_800EC890)($v0)\n"
"nop\n"
"addiu $v1, $v0, -4\n"
"lui $at, %hi(D_800EC890)\n"
"sw $v1, %lo(D_800EC890)($at)\n"
"lui $v0, %hi(D_800EC890)\n"
"lw $v0, %lo(D_800EC890)($v0)\n"
"nop\n"
"bgez $v0, .L800D0AF8\n"
"nop\n"
"lui $at, %hi(D_800EC890)\n"
"sw $zero, %lo(D_800EC890)($at)\n"
"addiu $a0, $zero, 1\n"
"jal func_800146B0\n"
"nop\n"
"addiu $v0, $zero, 2\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sw $v0, -23576($at)\n"
"jal func_800118AC\n"
"nop\n"
"j .L800D0B00\n"
"nop\n"
".L800D0AF8:\n"
"jal func_800D12D0\n"
"nop\n"
".L800D0B00:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0A7C\n");
/* func_800D0B1C - VERBATIM-ASM BANK (cookbook sec 265, file-scope form #1).
* -O0 body (addu $fp,$sp,$zero prologue / 21F0A003, a nop in every delay slot,
* per-statement li) stranded inside md_MAIN_003's -O2 object (sec 261: nothing
* under src/md_* globs -O0 yet). Sec 261a addendum (d) names this TU explicitly:
* the fleet's TERMINAL state for an -O0 function stranded in an -O2 TU is the
* sec 265 verbatim-asm block IN THIS TU, not (yet) the sec 18/sec 261 _o0 carve.
* Same family and same save set (ra/fp/s0, frame 32, mask 0xC0010000,-16) as the
* already-banked func_800D0174 / func_800D0204 / func_800D0440 / func_800D06BC /
* func_800D09A0 / func_800D0A7C in this exact file.
*
* Three prior wave agents each reported match_one MATCH 77/77 for the real C body
* below (match_one force-compiles -O0 on seeing the frame-pointer prologue) and
* each was rejected by the whole-binary gate: tools/recover_integration.py's
* real-cc1 probe DIFFs 49/77 because the object's own CC1FLAGS are -O2. That is
* exactly sec 261's "shown an -O2 compile of its own C" failure mode - no C source
* can bank this function while md_MAIN_003.c compiles -O2. A raw __asm__ body is
* opt-level-independent (cc1 passes the string through untouched), so it emits the
* target bytes regardless of the TU's compile flags.
*
* Recovered C semantics for the eventual real -O0-object decomp:
*
* register u8 *s0 = D_800AF630; // sec 127 far-base hi/lo pair
* func_800183E0((s32)&D_800D4E6C);
* switch (D_800EC894) { // extern s16 D_800EC894 (lh)
* case 0: *(u16 *)(s0 + 0xA3B6) = 1; *(u16 *)(s0 + 0xA3B8) = 2; break;
* case 1: *(u16 *)(s0 + 0xA3B6) = 1; *(u16 *)(s0 + 0xA3B8) = 0; break;
* case 2: *(u16 *)(s0 + 0xA3B6) = 1; *(u16 *)(s0 + 0xA3B8) = 1; break;
* case 4: *(u16 *)(s0 + 0xA3B6) = 1; *(u16 *)(s0 + 0xA3B8) = 4; break;
* }
*
* All immediates decimal (maspsx rejects hex inside __asm__ strings); -0x5C4A =
* -23626, -0x5C48 = -23624, lui $at,(0x10000>>16) = lui $at,1. No C externs
* shipped (link-time resolution, per sec 265 / sec 236-1).
*/
__asm__(".text\n.align 2\n.globl func_800D0B1C\n.ent\tfunc_800D0B1C\n"
"func_800D0B1C:\n.frame $sp,32,$31\n.mask 0xC0010000,-16\n.fmask 0,0\n"
".set\tnoreorder\n"
"addiu $sp, $sp, -32\n"
"sw $ra, 24($sp)\n"
"sw $fp, 20($sp)\n"
"sw $s0, 16($sp)\n"
"addu $fp, $sp, $zero\n"
"lui $s0, %hi(D_800AF630)\n"
"addiu $s0, $s0, %lo(D_800AF630)\n"
"lui $a0, %hi(D_800D4E6C)\n"
"addiu $a0, $a0, %lo(D_800D4E6C)\n"
"jal func_800183E0\n"
"nop\n"
"lui $v0, %hi(D_800EC894)\n"
"lh $v0, %lo(D_800EC894)($v0)\n"
"addiu $v1, $zero, 1\n"
"beq $v0, $v1, .L800D0BC0\n"
"nop\n"
"slti $v1, $v0, 2\n"
"beqz $v1, .L800D0B78\n"
"nop\n"
"beqz $v0, .L800D0B98\n"
"nop\n"
"j .L800D0C34\n"
"nop\n"
".L800D0B78:\n"
"addiu $v1, $zero, 2\n"
"beq $v0, $v1, .L800D0BE4\n"
"nop\n"
"addiu $v1, $zero, 4\n"
"beq $v0, $v1, .L800D0C0C\n"
"nop\n"
"j .L800D0C34\n"
"nop\n"
".L800D0B98:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 2\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0C34\n"
"nop\n"
".L800D0BC0:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $zero, -23624($at)\n"
"j .L800D0C34\n"
"nop\n"
".L800D0BE4:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0C34\n"
"nop\n"
".L800D0C0C:\n"
"addiu $v0, $zero, 1\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23626($at)\n"
"addiu $v0, $zero, 4\n"
"lui $at, 1\n"
"addu $at, $s0, $at\n"
"sh $v0, -23624($at)\n"
"j .L800D0C34\n"
"nop\n"
".L800D0C34:\n"
"addu $sp, $fp, $zero\n"
"lw $ra, 24($sp)\n"
"lw $fp, 20($sp)\n"
"lw $s0, 16($sp)\n"
"addiu $sp, $sp, 32\n"
"jr $ra\n"
"nop\n"
".set\treorder\n.end\tfunc_800D0B1C\n");
extern s16 D_800EC894;
extern void func_800599B8(u16 *, u16 *);
extern void func_80011928(s32);
void func_800D0C50(void) {
s16 sp10[8];
u16 *addr2;
u16 *addr1;
addr1 = (u16 *)(D_800EC894 * 307744 + 0x80114014);
addr2 = (u16 *)(D_800EC894 * 307744 + 0x80114220);
sp10[0] = 0;
sp10[1] = 0x1E0;
sp10[2] = 0x100;
sp10[3] = 1;
sp10[4] = 0x280;
sp10[5] = 0x10;
sp10[6] = 0x140;
sp10[7] = 0x1E0;
func_800599B8(sp10, addr1);
func_800599B8(&sp10[4], addr2);
func_80011928(3);
}
+184 -1
View File
@@ -85,7 +85,190 @@ void func_800CEF00(void) {
INCLUDE_RODATA("asm/md_MAIN_011/nonmatchings/md_MAIN_011", D_800CEDF8);
INCLUDE_ASM("asm/md_MAIN_011/nonmatchings/md_MAIN_011", func_800CF28C);
void func_800CF28C(void) {
extern u8 D_800AF630[];
extern u8 D_80078E78[];
extern u8 D_800D31F8[];
extern u8 D_800D3334[];
typedef struct { s16 unk00; s16 unk02; s16 unk04; } S6;
typedef struct { u8 pad00[0x1A]; u16 f1A; } SP18;
extern S6 D_800D4A5C[];
extern s16 D_800D4C80;
extern u16 D_800D4C9C;
extern s32 D_800D4C90;
extern s32 D_800D4C94;
extern s32 D_800D3344;
extern s16 D_800D3348;
extern s16 D_800D334A;
extern void func_800D0858(void);
extern void func_8001534C(int, void *, int, int, int, int);
extern void func_80011928(s32);
extern void func_800167B8(s32);
extern void func_80029514(s32);
extern s32 func_80029178(s32);
extern void func_80029124(s32, s32);
extern void func_800D04F4(void);
extern void func_800CFBF0(void);
extern void func_800CFB88(void);
register u8 *v0 = D_800AF630;
SP18 *sp18 = (SP18 *)D_80078E78;
s32 sp1C;
v0[0xA3E1] = 0;
func_800D0858();
if ((u16)(D_800D4C9C & 0x4000)) {
D_800D4C80++;
if (D_800D4C80 >= 13) {
D_800D4C80 = 0;
}
} else if ((u16)(D_800D4C9C & 0x1000)) {
D_800D4C80--;
if (D_800D4C80 < 0) {
D_800D4C80 = 12;
}
}
func_8001534C(1, D_800D31F8, 0x34, (s16)D_800D3334[D_800D4C80], 0, 0);
switch (D_800D4C80) {
case 0:
if ((u16)(D_800D4C9C & 0x820)) {
func_80011928(4);
}
break;
case 1:
case 2:
case 3:
case 5:
if ((u16)(D_800D4C9C & 0x820)) {
func_80011928(2);
func_800167B8(4);
}
break;
case 4:
if ((u16)(D_800D4C9C & 0x8000)) {
D_800D4C90--;
if (D_800D4C90 < 0) {
D_800D4C90 = 6;
}
}
if ((u16)(D_800D4C9C & 0x2000)) {
D_800D4C90++;
if (D_800D4C90++ >= 7) {
D_800D4C90 = 0;
}
}
break;
case 6:
if ((u16)(D_800D4C9C & 0x8000)) {
D_800D4C94--;
if (D_800D4C94 < 0) {
D_800D4C94 = 7;
}
}
if ((u16)(D_800D4C9C & 0x2000)) {
D_800D4C94++;
if (D_800D4C94 >= 8) {
D_800D4C94 = 0;
}
}
break;
case 7:
if ((u16)(D_800D4C9C & 0x8000)) {
if ((D_800D3344 = D_800D3344 - 10) < 0) {
D_800D3344 = 0;
}
}
if ((u16)(D_800D4C9C & 0x2000)) {
if ((D_800D3344 = D_800D3344 + 10) >= 0x6A5) {
D_800D3344 = 0x6A4;
}
}
if ((u16)(D_800D4C9C & 0x20)) {
if ((D_800D3344 = D_800D3344 + 1) >= 0x6A5) {
D_800D3344 = 0x6A4;
}
}
if ((u16)(D_800D4C9C & 0x40)) {
if ((D_800D3344 = D_800D3344 - 1) < 0) {
D_800D3344 = 0;
}
}
if ((u16)(D_800D4C9C & 0x10)) {
if ((D_800D3344 = D_800D3344 + 100) >= 0x6A5) {
D_800D3344 = 0x6A4;
}
}
if ((u16)(D_800D4C9C & 0x80)) {
if ((D_800D3344 = D_800D3344 - 100) < 0) {
D_800D3344 = 0;
}
}
func_80029514(D_800D3344);
break;
case 8:
if ((u16)(D_800D4C9C & 0x8000)) {
if ((D_800D3348 = D_800D3348 - 1) < 0) {
D_800D3348 = 0x2B;
}
}
if ((u16)(D_800D4C9C & 0x2000)) {
if ((D_800D3348 = D_800D3348 + 1) >= 0x2C) {
D_800D3348 = 0;
}
}
if ((u16)(D_800D4C9C & 0x20)) {
sp1C = D_800D4A5C[D_800D3348].unk04;
func_80029124(sp1C, (u8)func_80029178(sp1C) == 0);
}
break;
case 9:
if ((u16)(D_800D4C9C & 0x2000)) {
D_800D334A += 0x3C;
}
if ((u16)(D_800D4C9C & 0x8000)) {
D_800D334A -= 0x3C;
}
if ((u16)(D_800D4C9C & 0xA0)) {
D_800D334A += 0xF;
}
if ((u16)(D_800D4C9C & 0x40)) {
D_800D334A -= 0xF;
}
if (D_800D334A < 0) {
D_800D334A = 0x59F;
}
if (D_800D334A >= 0x5A0) {
D_800D334A = 0;
}
sp18->f1A = D_800D334A;
break;
case 10:
if ((u16)(D_800D4C9C & 0x2000)) {
func_80029124(0, (u8)func_80029178(0) == 0);
}
break;
case 11:
if ((u16)(D_800D4C9C & 0x2000)) {
func_80029124(1, (u8)func_80029178(1) == 0);
}
break;
case 12:
if ((u16)(D_800D4C9C & 0x2000)) {
func_80029124(2, (u8)func_80029178(2) == 0);
}
break;
}
if (D_800D4C80 >= 6) {
if ((u16)(D_800D4C9C & 0x800)) {
D_800D4C80 = 0;
func_80011928(4);
}
}
sp18->f1A = D_800D334A;
func_800D04F4();
func_800CFBF0();
func_800CFB88();
}
void func_800CFB88(void) {
extern s32 D_800D4C90;
+57 -5
View File
@@ -272,6 +272,38 @@ def carve_owners(ov, banked, base, carve_offs):
return owners
# .globl / .ent inside a §265 verbatim `__asm__` body — the separator can be a literal two-char
# escape (`\t`, `\n`) or a quote boundary, since the directives live inside C string literals.
_EMIT_SYM_RE = re.compile(r'\.(?:globl|ent)(?:\s|\\[nt]|")+([A-Za-z_]\w*)')
def _region_emit_start(items, syms, obj_lo, obj_hi):
"""The lowest vram a region's TEXT actually EMITS — which is not always its cut vram.
P31 S74. `overlay_src_split.parse_overlay_c` recognises four ADDRESSED ANCHOR forms; a §265
verbatim `__asm__(".text\n.globl func_X\n…")` body is none of them, so it lands in the
PREAMBLE of the next anchor. Preamble is assumed byte-neutral (comments + decls) — and for a
verbatim asm body that assumption is false: it emits its bytes. Cutting md_MAIN_003 at
func_800D0268 therefore carried the verbatim bodies of func_800D0100/0174/0204 into the new
region while the yaml said the region starts at 0x800D0268 — a config 0x168 bytes above where
the object's bytes actually begin. (Only the TRAILING case was handled, in `_partition`.)
So derive the boundary from the CONTENT: the min of the region's item addresses and of every
`.globl`/`.ent` symbol its text names that resolves INSIDE this object. Returns None when
nothing resolves. Where no verbatim asm is in play this equals the cut, so every existing
isolate is unchanged — the whole-binary byte-gate (G3/P9) remains the arbiter."""
best = None
for it in items:
if it[0] is not None:
best = it[0] if best is None else min(best, it[0])
for nm in _EMIT_SYM_RE.findall(it[3] or ''):
a = oss.addr_of(nm, syms)
if a is None or a < obj_lo or (obj_hi is not None and a >= obj_hi):
continue
best = a if best is None else min(best, a)
return best
def build_new_config(ov, p):
"""Return (new_cfg_lines, new_files:{path:content}, carve_renames:{old_sub:new_sub})."""
base = p["base"]
@@ -318,10 +350,21 @@ def build_new_config(ov, p):
# ov_SC01_000_jr_801734BC — the leader 0x801734BC is a cut too, per the banked-jr rule).
# Emitting it would duplicate region 1's line exactly (same offset, and subseg_name(lo)
# == nm when the object is already named _jr_<leader>) → splat "segments out of order".
if lo is None and not items:
# ...and an EMPTY CUT region likewise (P31 S74): a region with no items emits no
# bytes, so its config line is a zero-length subseg AT the next boundary's offset —
# `- [0x1f74, c, md_MAIN_003_o0e]` immediately above the existing
# `- [0x1f74, c, md_MAIN_003_o0c]`, which the ascending/unique validator rejects as
# "out of order". o0_subsplit closes every run with a cut at the next anchor (or --hi);
# when that lands exactly on an existing subseg boundary the closing region is empty by
# construction and must simply not be emitted.
if not items:
continue
sub = nm if lo is None else subseg_name(ov, lo)
off = (s if lo is None else lo) - base
if lo is None:
off = s - base
else:
_emit = _region_emit_start(items, syms, s, e)
off = (lo if _emit is None else min(lo, _emit)) - base
cfg_block.append(f"{ind}- [{hex(off)}, c, {sub}]")
body = _render_region(header, items, old_sub=nm, new_sub=sub, ambient=ambient,
syms=syms, obj_start=s)
@@ -434,9 +477,18 @@ def _partition(srcpath, cuts, syms):
if (lo is None or it[0] >= lo) and (hi is None or it[0] < hi)),
key=lambda it: it[0])
regions.append((lo, hi, sel))
if tail or footer: # tail = guarded last-region content (see above);
lo, hi, sel = regions[-1] # footer = comment/blank-only trailing chunk
regions[-1] = (lo, hi, sel + tail + footer)
if tail: # tail = guarded last-region content (see above): it HAS
lo, hi, sel = regions[-1] # addresses, validated at/after the last cut, so it belongs
regions[-1] = (lo, hi, sel + tail)
if footer:
# footer = comment/blank-only trailing chunk: it emits NOTHING, so it must not be what
# makes an otherwise-empty last region look non-empty (P31 S74 — that is what kept
# build_new_config's empty-region skip from firing on md_MAIN_003, whose closing cut at
# 0x800D0D6C lands exactly on the existing md_MAIN_003_o0c boundary). Attach it to the last
# region that actually has content, so the text is preserved and no empty subseg is emitted.
idx = max((i for i, (_l, _h, sel) in enumerate(regions) if sel), default=len(regions) - 1)
lo, hi, sel = regions[idx]
regions[idx] = (lo, hi, sel + footer)
# Place each file-local `static` definition with the ONE region that references it.
for it in local_defs:
name = it[1]
+17 -12
View File
@@ -157,8 +157,17 @@ def _module_target(binary):
return vram, open(tgt, "rb").read()
def _s_rodata_span(path):
"""[lo, hi) vaddr span of everything the included .s emits into .rodata (comments carry vaddr)."""
"""[lo, hi) vaddr span of everything the included .s emits into .rodata (comments carry vaddr).
P31 S74: a TRAILING `.align N` counts. spimdisasm closes a sized symbol with the `.align` that
produced the original's padding (`.asciz "7"` + `.align 2` = 4 emitted bytes, not 2), and `as`
emits that pad — so the walk position after the include is the ROUNDED end. The under-report was
invisible while the next item was an anchor (`derive`'s zero_gap self-corrects an undershoot of
1-3 zero bytes) and fatal the moment the next item was a C jump table, which has no anchor:
md_MAIN_011's banked func_800CF28C refused with "C table entry 0 at 0x800CEDFA ... not a code
address" — the walk was 2 bytes short of the island, not the island adrift."""
lo, hi, in_ro = None, None, False
pend_align = 0 # `.align N` seen with no sized item after it
for ln in open(path, errors="replace"):
st = ln.strip()
if st.startswith(".section"):
@@ -166,6 +175,10 @@ def _s_rodata_span(path):
continue
if not in_ro:
continue
if st.startswith(".align"):
tok = st.split()
pend_align = (1 << int(tok[1])) if len(tok) > 1 and tok[1].isdigit() else 0
continue
m = re.match(r"/\*\s*[0-9A-Fa-f]+\s+([0-9A-Fa-f]{8})(?:\s+([0-9A-Fa-f]+))?\s*\*/\s*(\S+)\s*(.*)$", st)
if m:
a = int(m.group(1), 16)
@@ -182,17 +195,9 @@ def _s_rodata_span(path):
else:
continue
lo = a if lo is None else min(lo, a); hi = a + n if hi is None else max(hi, a + n)
elif st.startswith(".align") and hi is not None:
# A TRAILING `.align` IS PART OF THE SPAN (P31 S74). The assembler emits the padding
# to satisfy it, so a `.s` ending in `.asciz "r"` + `.align 2` occupies 4 bytes, not 2.
# Measuring only the emitted DATA left `hi` short, the island walk then landed
# mid-object, and `--derive` aborted with `C table entry 0 at 0x801A00DA ... island
# layout drift` — a true statement about a span that was never the real one. Found by a
# drafting agent that ran its own gate reject to ground instead of respelling the body:
# the reject was this, not its C. Byte-neutral control: the unmodified TU's object is
# identical with and without this branch.
al = 1 << int(st.split()[1])
hi = (hi + al - 1) // al * al
pend_align = 0
if hi is not None and pend_align > 1:
hi = (hi + pend_align - 1) // pend_align * pend_align
return lo, hi
_DIRSIZE = {".word": 4, ".long": 4, ".half": 2, ".short": 2, ".byte": 1, ".float": 4, ".double": 8}