feat(phase-31): S78 #12 — the 800c3 "wall" band is LIBPAD 4.2.1 + LIBAPI 4.2: 46 names applied; integrate wired by subseg range; renames via ApplySymbols

- provenance: the psx loader's per-version PsyQ signature sets place PADENTRY/PADCMD/PADPORTD/
  PADSEQD (4.2), WAITRC2 (4.3), COUNTER/C114/FIRST/PAD/PATCH/CHCLRPAD (libapi 4.2) byte-exact in
  0x8005CE48-0x8005FC68 / 800c2 -> 12 of main's 29 stubs incl. all four §332 walls are Sony's
  DualShock library in reorder mode. 46 names -> symbols.us.txt (count 1081), band TUs, verbatim
  manifest, wave_exclude; firstfile/firstfile2 (4.2 naming); CdGetToc @0x800430B8 (was the Phase-21
  xdedup mislabel DecDCToutCallback). SETUP §5.1 corrected; psyq-worklist S78; cookbook §487;
  decision-log + accelerators S78; CHECKSUMS +Psy-Q_46.zip +PSYQ_SDevTC_v4.5.zip.
- psyq_integrate: --yaml maps stub<->objects by SUBSEG RANGE with an exact-tiling check and PRINTS
  the located-but-unwired residue (libgte: 13 objs / 1,264 ins) — main's LINKED build had been RED
  at HEAD since the S77 psyq_identify fix (22 libgte blocks merged to 3; gate worktrees take the
  stub fallback so it never showed); a library object's exported symbol whose recovered address the
  curated file names differently is --redefine-sym'd (R15; A66 firstfile->firstfile2).
- Ghidra: 47 MCP renames did NOT persist through the sentinel stop (R9 caught it) -> NEW
  tools/ghidra_scripts/ApplySymbols.java + tools/ghidra_apply_symbols.sh mirror the curated file
  headless with a real save: 73 renamed, R9-verified x4. SETUP inventory rows (R21).
- lint_symbol_refs: scans verbatim __asm__ bodies (`.ent\tfunc_X` is invisible to \b and to the
  string-masked scan); negative-controlled (red on the pre-fix TUs, green on the passing tree).
- R22: clean extract-all 212/212 + check-all green on the final config; main rebuilt byte-identical
  143dbb89 after the last src-only fix -> 213/213; tools-health OK.
This commit is contained in:
Drew T
2026-09-04 15:57:06 -06:00
parent ac97233aa9
commit a7394f44dc
23 changed files with 678 additions and 276 deletions
-51
View File
@@ -1,61 +1,10 @@
{"ts": "2026-07-01 03:21:03", "addr": null, "name": "func_80180EC0", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 9, "where_stuck": "residual: 9 mismatch", "best_draft": ".run/backlog_drafts/func_80180EC0.c", "binary": "ov_SC03_013", "source": "bulk-harvest", "residual": null, "passes_tried": null}
{"ts": "2026-07-01 12:44:46", "addr": null, "name": "func_80181C84", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 8, "where_stuck": "residual: 8 mismatch", "best_draft": ".run/backlog_drafts/func_80181C84.c", "binary": "ov_SC06_006", "source": "bulk-harvest", "residual": null, "passes_tried": null}
{"ts": "2026-08-29 13:52:45", "addr": "0x8017eb30", "name": "func_8017EB30", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_8017EB30.c", "binary": "ov_SC01_004", "source": "t6-recover", "residual": null, "passes_tried": null}
{"ts": "2026-08-31 01:02:04", "addr": "0x80181344", "name": "func_80181344", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 48, "where_stuck": "residual: 48 mismatch", "best_draft": ".run/backlog_drafts/func_80181344.c", "binary": "ov_SC03_111", "source": "S67-strand", "residual": [[9, "08000047 j\t11c <func_80181344+0x11c>", "08060517 j .L8018145C"], [18, "08000047 j\t11c <func_80181344+0x11c>", "08060517 j .L8018145C"], [26, "1440002c bnez\tv0,11c <func_80181344+0x11c>", "1440002b bnez $v0, .L8018145C"], [27, "00000000 nop", "24020004 addiu $v0, $zero, 0x4"], [32, "24020004 li\tv0,4", "3c01801c lui $at, %hi(D_801B9888)"], [33, "3c010000 lui\tat,0x0", "ac229888 sw $v0, %lo(D_801B9888)($at)"], [34, "ac220000 sw\tv0,0(at)", "00038040 sll $s0, $v1, 1"], [35, "00038040 sll\ts0,v1,0x1", "02038021 addu $s0, $s0, $v1"], [36, "02038021 addu\ts0,s0,v1", "00108040 sll $s0, $s0, 1"], [37, "00108040 sll\ts0,s0,0x1", "0c06051c jal func_80181470"], [38, "0c000000 jal\t0 <func_80181344>", "02002821 addu $a1, $s0, $zero"], [39, "02002821 move\ta1,s0", "3c04801b lui $a0, %hi(D_801B1174)"], [40, "3c040000 lui\ta0,0x0", "24841174 addiu $a0, $a0, %lo(D_801B1174)"], [41, "24840000 addiu\ta0,a0,0", "0c06051c jal func_80181470"], [42, "0c000000 jal\t0 <func_80181344>", "02002821 addu $a1, $s0, $zero"], [43, "02002821 move\ta1,s0", "3c04801b lui $a0, %hi(D_801B11D4)"], [44, "3c040000 lui\ta0,0x0", "248411d4 addiu $a0, $a0, %lo(D_801B11D4)"], [45, "24840000 addiu\ta0,a0,0", "0c06051c jal func_80181470"], [46, "0c000000 jal\t0 <func_80181344>", "02002821 addu $a1, $s0, $zero"], [47, "02002821 move\ta1,s0", "3c04801b lui $a0, %hi(D_801B1234)"], [48, "3c040000 lui\ta0,0x0", "24841234 addiu $a0, $a0, %lo(D_801B1234)"], [49, "24840000 addiu\ta0,a0,0", "0c06051c jal func_80181470"], [50, "0c000000 jal\t0 <func_80181344>", "02002821 addu $a1, $s0, $zero"], [51, "02002821 move\ta1,s0", "3c04801b lui $a0, %hi(D_801B1294)"]], "passes_tried": null}
{"ts": "2026-08-11 18:02:48", "addr": "0x8017f2d4", "name": "func_8017F2D4", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but gate rejected (declaration/TU plumbing)", "best_draft": ".run/backlog_drafts/func_8017F2D4.c", "binary": "ov_SC01_005", "source": "worker", "residual": null, "passes_tried": null}
{"ts": "2026-08-14 03:20:00", "addr": "0x80183178", "name": "func_80183178", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 21, "where_stuck": "residual: 21 mismatch", "best_draft": ".run/backlog_drafts/func_80183178.c", "binary": "ov_SC03_118", "source": "worker", "residual": [[0, "27bdffe0 addiu\tsp,sp,-32", "27bdffd8 addiu $sp, $sp, -0x28"], [1, "00002021 move\ta0,zero", "afbf0024 sw $ra, 0x24($sp)"], [2, "00002821 move\ta1,zero", "afbe0020 sw $fp, 0x20($sp)"], [3, "3c060000 lui\ta2,0x0", "03a0f021 addu $fp, $sp, $zero"], [4, "24c60000 addiu\ta2,a2,0", "afa00010 sw $zero, 0x10($sp)"], [5, "00003821 move\ta3,zero", "00002021 addu $a0, $zero, $zero"], [6, "afbf0018 sw\tra,24(sp)", "00002821 addu $a1, $zero, $zero"], [8, "afa00010 sw\tzero,16(sp)", "24c6f058 addiu $a2, $a2, %lo(D_800AF058)"], [9, "8fbf0018 lw\tra,24(sp)", "00003821 addu $a3, $zero, $zero"], [10, "27bd0020 addiu\tsp,sp,32", "0c006aef jal func_8001ABBC"], [11, "03e00008 jr\tra", "00000000 nop"], [12, "00000000 nop", "afc20018 sw $v0, 0x18($fp)"], [13, "--", "8fc20018 lw $v0, 0x18($fp)"], [14, "--", "08060c6e j .L801831B8"], [15, "--", "00000000 nop"], [16, "--", "03c0e821 addu $sp, $fp, $zero"], [17, "--", "8fbf0024 lw $ra, 0x24($sp)"], [18, "--", "8fbe0020 lw $fp, 0x20($sp)"], [19, "--", "27bd0028 addiu $sp, $sp, 0x28"], [20, "--", "03e00008 jr $ra"], [21, "--", "00000000 nop"]], "passes_tried": null}
{"ts": "2026-08-14 04:00:51", "addr": "0x8017fe0c", "name": "func_8017FE0C", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_8017FE0C.c", "binary": "ov_SC06_018", "source": "worker", "residual": null, "passes_tried": null}
{"ts": "2026-08-18 04:15:53", "addr": "0x8017db98", "name": "func_8017DB98", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 115, "where_stuck": "residual: 115 mismatch", "best_draft": ".run/backlog_drafts/func_8017DB98.c", "binary": "ov_SC06_025", "source": "worker", "residual": [[0, "27bdffd0 addiu\tsp,sp,-48", "27bdffc8 addiu $sp, $sp, -0x38"], [1, "afb10024 sw\ts1,36(sp)", "afb20028 sw $s2, 0x28($sp)"], [2, "00808821 move\ts1,a0", "00809021 addu $s2, $a0, $zero"], [3, "afb20028 sw\ts2,40(sp)", "afb40030 sw $s4, 0x30($sp)"], [4, "00a09021 move\ts2,a1", "00a0a021 addu $s4, $a1, $zero"], [5, "afbf002c sw\tra,44(sp)", "afb3002c sw $s3, 0x2C($sp)"], [6, "afb00020 sw\ts0,32(sp)", "afbf0034 sw $ra, 0x34($sp)"], [7, "96250000 lhu\ta1,0(s1)", "afb10024 sw $s1, 0x24($sp)"], [8, "240200ff li\tv0,255", "afb00020 sw $s0, 0x20($sp)"], [9, "30a3ffff andi\tv1,a1,0xffff", "96450000 lhu $a1, 0x0($s2)"], [10, "10620061 beq\tv1,v0,1b0 <func_8017DB98+0x1b0>", "240200ff addiu $v0, $zero, 0xFF"], [11, "24900008 addiu\ts0,a0,8", "30a3ffff andi $v1, $a1, 0xFFFF"], [12, "30a3ffff andi\tv1,a1,0xffff", "10620063 beq $v1, $v0, .L8017DD58"], [13, "24020009 li\tv0,9", "00009821 addu $s3, $zero, $zero"], [14, "14620057 bne\tv1,v0,198 <func_8017DB98+0x198>", "24900008 addiu $s0, $a0, 0x8"], [15, "00000000 nop", "30a3ffff andi $v1, $a1, 0xFFFF"], [16, "9602fffc lhu\tv0,-4(s0)", "24020009 addiu $v0, $zero, 0x9"], [17, "00000000 nop", "14620058 bne $v1, $v0, .L8017DD40"], [18, "a7a20010 sh\tv0,16(sp)", "00000000 nop"], [19, "9602fffe lhu\tv0,-2(s0)", "9602fffc lhu $v0, -0x4($s0)"], [21, "a7a20012 sh\tv0,18(sp)", "a7a20010 sh $v0, 0x10($sp)"], [22, "96020000 lhu\tv0,0(s0)", "9602fffe lhu $v0, -0x2($s0)"], [24, "a7a20014 sh\tv0,20(sp)", "a7a20012 sh $v0, 0x12($sp)"], [25, "96020002 lhu\tv0,2(s0)", "96020000 lhu $v0, 0x0($s0)"]], "passes_tried": null}
{"ts": "2026-08-25 23:37:44", "addr": "0x8017faa8", "name": "func_8017FAA8", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "resolver CC1 (real-TU rtu_match, 20260825-233727): .run/resolver/work/ov_SC03_013__func_8017FAA8/c0/rtu/func_8017FAA8/t.c:4276: conflicting types for `SV3'", "best_draft": ".run/backlog_drafts/func_8017FAA8.c", "binary": "ov_SC03_013", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-25 23:39:15", "addr": "0x8017ec68", "name": "func_8017EC68", "reach": null, "klass": null, "nins": 279, "status": "near", "closeness": 274, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260825-233820): mine=341 target=279", "best_draft": ".run/wave_fa/shard313/func_8017EC68.c", "binary": "ov_SC01_008", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-31 03:44:39", "addr": "0x8017d918", "name": "func_8017D918", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 4, "where_stuck": "residual: 4 mismatch", "best_draft": ".run/backlog_drafts/func_8017D918.c", "binary": "ov_SC06_020", "source": "S67-cc1", "residual": [[17, "97a2005a lhu\tv0,90(sp)", "97a30058 lhu $v1, 0x58($sp)"], [18, "97a30058 lhu\tv1,88(sp)", "97a2005a lhu $v0, 0x5A($sp)"], [19, "24440080 addiu\ta0,v0,128", "00708021 addu $s0, $v1, $s0"], [20, "00708021 addu\ts0,v1,s0", "24440080 addiu $a0, $v0, 0x80"]], "passes_tried": null}
{"ts": "2026-08-25 23:39:15", "addr": "0x80180b3c", "name": "func_80180B3C", "reach": null, "klass": null, "nins": 297, "status": "near", "closeness": 125, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260825-233820): mine=296 target=297", "best_draft": ".run/wave_eo/shard478/func_80180B3C.c", "binary": "ov_SC02_027", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-25 23:39:15", "addr": "0x80180abc", "name": "func_80180ABC", "reach": null, "klass": null, "nins": 257, "status": "near", "closeness": 250, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260825-233820): mine=49 target=257", "best_draft": ".run/wave_ci/shard141/func_80180ABC.c", "binary": "ov_SC03_105", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-25 23:39:15", "addr": "0x80182cbc", "name": "func_80182CBC", "reach": null, "klass": null, "nins": 28, "status": "near", "closeness": 7, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260825-233820): mine=28 target=28", "best_draft": ".run/backlog_drafts/func_80182CBC.c", "binary": "ov_SC04_002", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-29 17:19:19", "addr": "0x80181804", "name": "func_80181804", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_80181804.c", "binary": "ov_SC04_018", "source": "family-remap", "residual": null, "passes_tried": null}
{"ts": "2026-08-25 23:39:15", "addr": "0x800d06e8", "name": "func_800D06E8", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "resolver CC1 (real-TU rtu_match, 20260825-233820): .run/resolver/work/resident__func_800D06E8/c0/rtu/func_800D06E8/t.c:1770: conflicting types for `Struct80078E78'", "best_draft": ".run/wave_ch/shard62/func_800D06E8.c", "binary": "resident", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-26 02:23:19", "addr": "0x80180b3c", "name": "func_80180B3C", "reach": null, "klass": null, "nins": 21, "status": "near", "closeness": 287, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260826-022235): mine=287 target=21", "best_draft": ".run/wave_eq/shard63/func_80180B3C.c", "binary": "ov_SC07_000", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-26 04:46:45", "addr": "0x800d0c50", "name": "func_800D0C50", "reach": null, "klass": null, "nins": 71, "status": "near", "closeness": 68, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260826-044601): mine=46 target=71", "best_draft": ".run/backlog_drafts/func_800D0C50.c", "binary": "md_MAIN_003", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-26 05:32:16", "addr": "0x800cb00c", "name": "func_800CB00C", "reach": null, "klass": null, "nins": 123, "status": "near", "closeness": 168, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260826-053145): mine=174 target=123", "best_draft": ".run/wave_g0c/shard30/func_800CB00C.c", "binary": "md_MAIN_034", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-26 06:24:18", "addr": "0x801806f8", "name": "func_801806F8", "reach": null, "klass": null, "nins": 241, "status": "near", "closeness": 235, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260826-062321): mine=72 target=241", "best_draft": ".run/wave_g0d/shard20/func_801806F8.c", "binary": "ov_SC03_105", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-26 06:24:18", "addr": "0x801867d0", "name": "func_801867D0", "reach": null, "klass": null, "nins": 198, "status": "near", "closeness": 166, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260826-062321): mine=100 target=198", "best_draft": ".run/wave_g0d/shard11/func_801867D0.c", "binary": "ov_SC03_105", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-26 08:02:18", "addr": "0x800d02d0", "name": "func_800D02D0", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "resolver CC1 (real-TU rtu_match, 20260826-080111): .run/resolver/work/resident__func_800D02D0/c0/rtu/func_800D02D0/t.c:1136: conflicting types for `CdFileLoc'", "best_draft": ".run/backlog_drafts/func_800D02D0.c", "binary": "resident", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-30 22:12:57", "addr": "0x800d00e4", "name": "func_800D00E4", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_800D00E4.c", "binary": "resident", "source": "worker", "residual": null, "passes_tried": null}
{"ts": "2026-08-26 14:56:44", "addr": "0x801a4acc", "name": "func_801A4ACC", "reach": null, "klass": null, "nins": 237, "status": "near", "closeness": 2, "where_stuck": "resolver DIFF (real-TU rtu_match, 20260826-145551): mine=237 target=237", "best_draft": ".run/backlog_drafts/func_801A4ACC.c", "binary": "md_SC07_004", "source": "resolver", "residual": null, "passes_tried": null}
{"ts": "2026-08-29 14:43:39", "addr": "0x80181294", "name": "func_80181294", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 19, "where_stuck": "residual: 19 mismatch", "best_draft": ".run/backlog_drafts/func_80181294.c", "binary": "ov_SC05_018", "source": "t6-recover", "residual": [[1, "24031000 li\tv1,4096", "24021000 addiu $v0, $zero, 0x1000"], [2, "00651823 subu\tv1,v1,a1", "00451023 subu $v0, $v0, $a1"], [3, "00c30018 mult\ta2,v1", "00c20018 mult $a2, $v0"], [5, "00003012 mflo\ta2", "00002812 mflo $a1"], [6, "00041142 srl\tv0,a0,0x5", "00041942 srl $v1, $a0, 5"], [7, "3042001f andi\tv0,v0,0x1f", "3063001f andi $v1, $v1, 0x1F"], [8, "00430018 mult\tv0,v1", "00620018 mult $v1, $v0"], [9, "00002812 mflo\ta1", "00001812 mflo $v1"], [12, "00830018 mult\ta0,v1", "00820018 mult $a0, $v0"], [13, "00061303 sra\tv0,a2,0xc", "00051303 sra $v0, $a1, 12"], [15, "000511c3 sra\tv0,a1,0x7", "000319c3 sra $v1, $v1, 7"], [16, "304203e0 andi\tv0,v0,0x3e0", "306203e0 andi $v0, $v1, 0x3E0"], [18, "00432825 or\ta1,v0,v1", "00431025 or $v0, $v0, $v1"], [19, "00c51825 or\tv1,a2,a1", "00c21025 or $v0, $a2, $v0"], [21, "00081083 sra\tv0,t0,0x2", "00082083 sra $a0, $t0, 2"], [22, "30427c00 andi\tv0,v0,0x7c00", "30837c00 andi $v1, $a0, 0x7C00"], [23, "03e00008 jr\tra", "00431025 or $v0, $v0, $v1"], [24, "00621025 or\tv0,v1,v0", "03e00008 jr $ra"], [25, "--", "3042ffff andi $v0, $v0, 0xFFFF"]], "passes_tried": null}
{"ts": "2026-08-29 17:19:19", "addr": "0x80181cb8", "name": "func_80181CB8", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_80181CB8.c", "binary": "ov_SC04_018", "source": "family-remap", "residual": null, "passes_tried": null}
{"ts": "2026-08-30 21:42:38", "addr": "0x8017ecb4", "name": "func_8017ECB4", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_8017ECB4.c", "binary": "ov_SC07_000", "source": "worker", "residual": null, "passes_tried": null}
{"ts": "2026-08-30 22:06:27", "addr": "0x80188e3c", "name": "func_80188E3C", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_80188E3C.c", "binary": "ov_SC02_011", "source": "worker", "residual": null, "passes_tried": null}
{"ts": "2026-08-30 22:12:57", "addr": "0x800d0488", "name": "func_800D0488", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_800D0488.c", "binary": "resident", "source": "worker", "residual": null, "passes_tried": null}
{"ts": "2026-08-30 22:24:51", "addr": "0x8016ae5c", "name": "func_8016AE5C", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_8016AE5C.c", "binary": "ov_SC03_108", "source": "worker", "residual": null, "passes_tried": null}
{"ts": "2026-08-31 00:38:52", "addr": "0x801a11d4", "name": "func_801A11D4", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_801A11D4.c", "binary": "md_SC07_004", "source": "S67-strand", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 00:59:23", "addr": "0x801ada10", "name": "func_801ADA10", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_801ADA10.c", "binary": "md_SC07_004", "source": "t6-recover", "residual": null, "passes_tried": null}
{"ts": "2026-08-31 01:53:51", "addr": "0x8017fbcc", "name": "func_8017FBCC", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_8017FBCC.c", "binary": "ov_SC01_005", "source": "S67-cc1", "residual": null, "passes_tried": null}
{"ts": "2026-08-31 02:19:40", "addr": "0x801832f8", "name": "func_801832F8", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_801832F8.c", "binary": "ov_SC02_041", "source": "S67-cc1", "residual": null, "passes_tried": null}
{"ts": "2026-08-31 02:36:44", "addr": "0x8017f018", "name": "func_8017F018", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_8017F018.c", "binary": "ov_SC03_105", "source": "S67-cc1", "residual": null, "passes_tried": null}
{"ts": "2026-08-31 02:40:59", "addr": "0x8018095c", "name": "func_8018095C", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_8018095C.c", "binary": "ov_SC03_124", "source": "S67-cc1", "residual": null, "passes_tried": null}
{"ts": "2026-08-31 03:19:48", "addr": "0x80181720", "name": "func_80181720", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_80181720.c", "binary": "ov_SC05_003", "source": "S67-cc1", "residual": null, "passes_tried": null}
{"ts": "2026-08-31 11:19:08", "addr": "0x8018dfc4", "name": "func_8018DFC4", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_8018DFC4.c", "binary": "ov_SC02_005", "source": "S67-wave", "residual": null, "passes_tried": null}
{"ts": "2026-09-01 16:29:12", "addr": "0x801801d8", "name": "func_801801D8", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_801801D8.c", "binary": "ov_SC06_029", "source": "S70-standalone", "residual": null, "passes_tried": null}
{"ts": "2026-09-01 16:29:12", "addr": "0x801898cc", "name": "func_801898CC", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_801898CC.c", "binary": "ov_SC06_029", "source": "S70-standalone", "residual": null, "passes_tried": null}
{"ts": "2026-09-01 20:26:31", "addr": "0x8002b0b4", "name": "func_8002B0B4", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_8002B0B4.c", "binary": "main", "source": "S70-rebank", "residual": null, "passes_tried": null}
{"ts": "2026-09-01 20:34:37", "addr": "0x80062144", "name": "func_80062144", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": null, "binary": "main", "source": "S70-332b", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 20:23:31", "addr": "0x800d06e8", "name": "func_800D06E8", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_800D06E8.c", "binary": "resident", "source": "s75-regate", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 20:35:17", "addr": "0x8016ae5c", "name": "func_8016AE5C", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": null, "binary": "ov_SC03_108", "source": "s75-regate", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 22:17:51", "addr": "0x800cb00c", "name": "func_800CB00C", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_800CB00C.c", "binary": "md_MAIN_034", "source": "s75-regate", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 22:18:53", "addr": "0x8018dfc4", "name": "func_8018DFC4", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_8018DFC4.c", "binary": "ov_SC02_005", "source": "s75-regate", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 22:19:58", "addr": "0x801832f8", "name": "func_801832F8", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_801832F8.c", "binary": "ov_SC02_041", "source": "s75-regate", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 22:21:02", "addr": "0x801806f8", "name": "func_801806F8", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_801806F8.c", "binary": "ov_SC03_013", "source": "s75-regate", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 22:23:35", "addr": "0x8018095c", "name": "func_8018095C", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_8018095C.c", "binary": "ov_SC03_124", "source": "s75-regate", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 22:25:01", "addr": "0x80181720", "name": "func_80181720", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_80181720.c", "binary": "ov_SC05_003", "source": "s75-regate", "residual": null, "passes_tried": null}
{"ts": "2026-09-02 22:26:23", "addr": "0x80181294", "name": "func_80181294", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 27, "where_stuck": "residual: 27 mismatch", "best_draft": ".run/backlog_drafts/func_80181294.c", "binary": "ov_SC05_018", "source": "s75-regate", "residual": [[1, "00052c00 sll\ta1,a1,0x10", "24021000 addiu $v0, $zero, 0x1000"], [2, "00052c03 sra\ta1,a1,0x10", "00451023 subu $v0, $v0, $a1"], [3, "24021000 li\tv0,4096", "00c20018 mult $a2, $v0"], [4, "00451023 subu\tv0,v0,a1", "3084ffff andi $a0, $a0, 0xFFFF"], [5, "00c20018 mult\ta2,v0", "00002812 mflo $a1"], [6, "3084ffff andi\ta0,a0,0xffff", "00041942 srl $v1, $a0, 5"], [7, "00002812 mflo\ta1", "3063001f andi $v1, $v1, 0x1F"], [8, "00041942 srl\tv1,a0,0x5", "00620018 mult $v1, $v0"], [9, "3063001f andi\tv1,v1,0x1f", "00001812 mflo $v1"], [10, "00620018 mult\tv1,v0", "00042282 srl $a0, $a0, 10"], [11, "00001812 mflo\tv1", "3084001f andi $a0, $a0, 0x1F"], [12, "00042282 srl\ta0,a0,0xa", "00820018 mult $a0, $v0"], [13, "3084001f andi\ta0,a0,0x1f", "00051303 sra $v0, $a1, 12"], [14, "00820018 mult\ta0,v0", "3046001f andi $a2, $v0, 0x1F"], [15, "00051303 sra\tv0,a1,0xc", "000319c3 sra $v1, $v1, 7"], [16, "3046001f andi\ta2,v0,0x1f", "306203e0 andi $v0, $v1, 0x3E0"], [17, "000311c3 sra\tv0,v1,0x7", "24038000 addiu $v1, $zero, -0x8000"], [18, "304203e0 andi\tv0,v0,0x3e0", "00431025 or $v0, $v0, $v1"], [19, "24038000 li\tv1,-32768", "00c21025 or $v0, $a2, $v0"], [20, "00431025 or\tv0,v0,v1", "00004012 mflo $t0"], [21, "00c21025 or\tv0,a2,v0", "00082083 sra $a0, $t0, 2"], [22, "00004012 mflo\tt0", "30837c00 andi $v1, $a0, 0x7C00"], [23, "00082083 sra\ta0,t0,0x2", "00431025 or $v0, $v0, $v1"], [24, "30847c00 andi\ta0,a0,0x7c00", "03e00008 jr $ra"]], "passes_tried": null}
{"ts": "2026-09-02 22:27:46", "addr": "0x8017d918", "name": "func_8017D918", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 4, "where_stuck": "residual: 4 mismatch", "best_draft": ".run/backlog_drafts/func_8017D918.c", "binary": "ov_SC06_020", "source": "s75-regate", "residual": [[17, "97a2005a lhu\tv0,90(sp)", "97a30058 lhu $v1, 0x58($sp)"], [18, "97a30058 lhu\tv1,88(sp)", "97a2005a lhu $v0, 0x5A($sp)"], [19, "24440080 addiu\ta0,v0,128", "00708021 addu $s0, $v1, $s0"], [20, "00708021 addu\ts0,v1,s0", "24440080 addiu $a0, $v0, 0x80"]], "passes_tried": null}
{"ts": "2026-09-02 22:29:30", "addr": "0x8017db98", "name": "func_8017DB98", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 115, "where_stuck": "residual: 115 mismatch", "best_draft": ".run/backlog_drafts/func_8017DB98.c", "binary": "ov_SC06_025", "source": "s75-regate", "residual": [[3, "afb4002c sw\ts4,44(sp)", "afb40030 sw $s4, 0x30($sp)"], [5, "afbf0030 sw\tra,48(sp)", "afb3002c sw $s3, 0x2C($sp)"], [6, "afb10024 sw\ts1,36(sp)", "afbf0034 sw $ra, 0x34($sp)"], [7, "afb00020 sw\ts0,32(sp)", "afb10024 sw $s1, 0x24($sp)"], [8, "96450000 lhu\ta1,0(s2)", "afb00020 sw $s0, 0x20($sp)"], [9, "240200ff li\tv0,255", "96450000 lhu $a1, 0x0($s2)"], [10, "30a3ffff andi\tv1,a1,0xffff", "240200ff addiu $v0, $zero, 0xFF"], [11, "10620061 beq\tv1,v0,1b4 <func_8017DB98+0x1b4>", "30a3ffff andi $v1, $a1, 0xFFFF"], [12, "24900008 addiu\ts0,a0,8", "10620063 beq $v1, $v0, .L8017DD58"], [13, "30a3ffff andi\tv1,a1,0xffff", "00009821 addu $s3, $zero, $zero"], [14, "24020009 li\tv0,9", "24900008 addiu $s0, $a0, 0x8"], [15, "14620057 bne\tv1,v0,19c <func_8017DB98+0x19c>", "30a3ffff andi $v1, $a1, 0xFFFF"], [16, "00000000 nop", "24020009 addiu $v0, $zero, 0x9"], [17, "9602fffc lhu\tv0,-4(s0)", "14620058 bne $v1, $v0, .L8017DD40"], [19, "a7a20010 sh\tv0,16(sp)", "9602fffc lhu $v0, -0x4($s0)"], [20, "9602fffe lhu\tv0,-2(s0)", "00000000 nop"], [21, "00000000 nop", "a7a20010 sh $v0, 0x10($sp)"], [22, "a7a20012 sh\tv0,18(sp)", "9602fffe lhu $v0, -0x2($s0)"], [23, "96020000 lhu\tv0,0(s0)", "00000000 nop"], [24, "00000000 nop", "a7a20012 sh $v0, 0x12($sp)"], [25, "a7a20014 sh\tv0,20(sp)", "96020000 lhu $v0, 0x0($s0)"], [26, "96020002 lhu\tv0,2(s0)", "00000000 nop"], [27, "12800004 beqz\ts4,80 <func_8017DB98+0x80>", "a7a20014 sh $v0, 0x14($sp)"], [28, "a7a20016 sh\tv0,22(sp)", "96020002 lhu $v0, 0x2($s0)"]], "passes_tried": null}
{"ts": "2026-09-02 22:32:17", "addr": "0x800d06e8", "name": "func_800D06E8", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_800D06E8.c", "binary": "resident", "source": "s75-regate", "residual": null, "passes_tried": null}
{"ts": "2026-09-03 00:03:01", "addr": "0x800cb00c", "name": "func_800CB00C", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_800CB00C.c", "binary": "md_MAIN_034", "source": "s75-redraft", "residual": null, "passes_tried": null}
{"ts": "2026-09-03 00:04:37", "addr": "0x80180b3c", "name": "func_80180B3C", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_80180B3C.c", "binary": "ov_SC02_027", "source": "s75-redraft", "residual": null, "passes_tried": null}
{"ts": "2026-09-03 00:07:08", "addr": "0x80181344", "name": "func_80181344", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 48, "where_stuck": "residual: 48 mismatch", "best_draft": ".run/backlog_drafts/func_80181344.c", "binary": "ov_SC03_111", "source": "s75-redraft", "residual": [[9, "08000047 j\t11c <func_80181344+0x11c>", "08060517 j .L8018145C"], [18, "08000047 j\t11c <func_80181344+0x11c>", "08060517 j .L8018145C"], [26, "1440002c bnez\tv0,11c <func_80181344+0x11c>", "1440002b bnez $v0, .L8018145C"], [27, "00000000 nop", "24020004 addiu $v0, $zero, 0x4"], [32, "24020004 li\tv0,4", "3c01801c lui $at, %hi(D_801B9888)"], [33, "3c010000 lui\tat,0x0", "ac229888 sw $v0, %lo(D_801B9888)($at)"], [34, "ac220000 sw\tv0,0(at)", "00038040 sll $s0, $v1, 1"], [35, "00038040 sll\ts0,v1,0x1", "02038021 addu $s0, $s0, $v1"], [36, "02038021 addu\ts0,s0,v1", "00108040 sll $s0, $s0, 1"], [37, "00108040 sll\ts0,s0,0x1", "0c06051c jal func_80181470"], [38, "0c000000 jal\t0 <func_80181344>", "02002821 addu $a1, $s0, $zero"], [39, "02002821 move\ta1,s0", "3c04801b lui $a0, %hi(D_801B1174)"], [40, "3c040000 lui\ta0,0x0", "24841174 addiu $a0, $a0, %lo(D_801B1174)"], [41, "24840000 addiu\ta0,a0,0", "0c06051c jal func_80181470"], [42, "0c000000 jal\t0 <func_80181344>", "02002821 addu $a1, $s0, $zero"], [43, "02002821 move\ta1,s0", "3c04801b lui $a0, %hi(D_801B11D4)"], [44, "3c040000 lui\ta0,0x0", "248411d4 addiu $a0, $a0, %lo(D_801B11D4)"], [45, "24840000 addiu\ta0,a0,0", "0c06051c jal func_80181470"], [46, "0c000000 jal\t0 <func_80181344>", "02002821 addu $a1, $s0, $zero"], [47, "02002821 move\ta1,s0", "3c04801b lui $a0, %hi(D_801B1234)"], [48, "3c040000 lui\ta0,0x0", "24841234 addiu $a0, $a0, %lo(D_801B1234)"], [49, "24840000 addiu\ta0,a0,0", "0c06051c jal func_80181470"], [50, "0c000000 jal\t0 <func_80181344>", "02002821 addu $a1, $s0, $zero"], [51, "02002821 move\ta1,s0", "3c04801b lui $a0, %hi(D_801B1294)"]], "passes_tried": null}
{"ts": "2026-09-03 00:08:28", "addr": "0x80181294", "name": "func_80181294", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 27, "where_stuck": "residual: 27 mismatch", "best_draft": ".run/backlog_drafts/func_80181294.c", "binary": "ov_SC05_018", "source": "s75-redraft", "residual": [[1, "00052c00 sll\ta1,a1,0x10", "24021000 addiu $v0, $zero, 0x1000"], [2, "00052c03 sra\ta1,a1,0x10", "00451023 subu $v0, $v0, $a1"], [3, "24021000 li\tv0,4096", "00c20018 mult $a2, $v0"], [4, "00451023 subu\tv0,v0,a1", "3084ffff andi $a0, $a0, 0xFFFF"], [5, "00c20018 mult\ta2,v0", "00002812 mflo $a1"], [6, "3084ffff andi\ta0,a0,0xffff", "00041942 srl $v1, $a0, 5"], [7, "00002812 mflo\ta1", "3063001f andi $v1, $v1, 0x1F"], [8, "00041942 srl\tv1,a0,0x5", "00620018 mult $v1, $v0"], [9, "3063001f andi\tv1,v1,0x1f", "00001812 mflo $v1"], [10, "00620018 mult\tv1,v0", "00042282 srl $a0, $a0, 10"], [11, "00001812 mflo\tv1", "3084001f andi $a0, $a0, 0x1F"], [12, "00042282 srl\ta0,a0,0xa", "00820018 mult $a0, $v0"], [13, "3084001f andi\ta0,a0,0x1f", "00051303 sra $v0, $a1, 12"], [14, "00820018 mult\ta0,v0", "3046001f andi $a2, $v0, 0x1F"], [15, "00051303 sra\tv0,a1,0xc", "000319c3 sra $v1, $v1, 7"], [16, "3046001f andi\ta2,v0,0x1f", "306203e0 andi $v0, $v1, 0x3E0"], [17, "000311c3 sra\tv0,v1,0x7", "24038000 addiu $v1, $zero, -0x8000"], [18, "304203e0 andi\tv0,v0,0x3e0", "00431025 or $v0, $v0, $v1"], [19, "24038000 li\tv1,-32768", "00c21025 or $v0, $a2, $v0"], [20, "00431025 or\tv0,v0,v1", "00004012 mflo $t0"], [21, "00c21025 or\tv0,a2,v0", "00082083 sra $a0, $t0, 2"], [22, "00004012 mflo\tt0", "30837c00 andi $v1, $a0, 0x7C00"], [23, "00082083 sra\ta0,t0,0x2", "00431025 or $v0, $v0, $v1"], [24, "30847c00 andi\ta0,a0,0x7c00", "03e00008 jr $ra"]], "passes_tried": null}
{"ts": "2026-09-03 00:10:12", "addr": "0x8017db98", "name": "func_8017DB98", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 120, "where_stuck": "residual: 120 mismatch", "best_draft": ".run/backlog_drafts/func_8017DB98.c", "binary": "ov_SC06_025", "source": "s75-redraft", "residual": [[0, "27bdffd0 addiu\tsp,sp,-48", "27bdffc8 addiu $sp, $sp, -0x38"], [1, "afb10024 sw\ts1,36(sp)", "afb20028 sw $s2, 0x28($sp)"], [2, "00808821 move\ts1,a0", "00809021 addu $s2, $a0, $zero"], [3, "afb20028 sw\ts2,40(sp)", "afb40030 sw $s4, 0x30($sp)"], [4, "00a09021 move\ts2,a1", "00a0a021 addu $s4, $a1, $zero"], [5, "afbf002c sw\tra,44(sp)", "afb3002c sw $s3, 0x2C($sp)"], [6, "afb00020 sw\ts0,32(sp)", "afbf0034 sw $ra, 0x34($sp)"], [7, "96250000 lhu\ta1,0(s1)", "afb10024 sw $s1, 0x24($sp)"], [8, "240200ff li\tv0,255", "afb00020 sw $s0, 0x20($sp)"], [9, "30a3ffff andi\tv1,a1,0xffff", "96450000 lhu $a1, 0x0($s2)"], [10, "10620061 beq\tv1,v0,1b0 <func_8017DB98+0x1b0>", "240200ff addiu $v0, $zero, 0xFF"], [11, "24900008 addiu\ts0,a0,8", "30a3ffff andi $v1, $a1, 0xFFFF"], [12, "30a3ffff andi\tv1,a1,0xffff", "10620063 beq $v1, $v0, .L8017DD58"], [13, "24020009 li\tv0,9", "00009821 addu $s3, $zero, $zero"], [14, "14620057 bne\tv1,v0,198 <func_8017DB98+0x198>", "24900008 addiu $s0, $a0, 0x8"], [15, "00000000 nop", "30a3ffff andi $v1, $a1, 0xFFFF"], [16, "9602fffc lhu\tv0,-4(s0)", "24020009 addiu $v0, $zero, 0x9"], [17, "00000000 nop", "14620058 bne $v1, $v0, .L8017DD40"], [18, "a7a20010 sh\tv0,16(sp)", "00000000 nop"], [19, "9602fffe lhu\tv0,-2(s0)", "9602fffc lhu $v0, -0x4($s0)"], [21, "a7a20012 sh\tv0,18(sp)", "a7a20010 sh $v0, 0x10($sp)"], [22, "96020000 lhu\tv0,0(s0)", "9602fffe lhu $v0, -0x2($s0)"], [24, "a7a20014 sh\tv0,20(sp)", "a7a20012 sh $v0, 0x12($sp)"], [25, "96020002 lhu\tv0,2(s0)", "96020000 lhu $v0, 0x0($s0)"]], "passes_tried": null}
{"ts": "2026-09-03 19:09:54", "addr": "0x800cb17c", "name": "func_800CB17C", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 0, "where_stuck": "match_one MATCH but the whole-binary gate rejected \u2014 CAUSE NOT DETERMINED. FIRST re-derive the destination TU from the asm subdir: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => src/<ov>/<TU_stem>.c (the third path component IS the TU). Only then look for a decl conflict or a codegen residual.", "best_draft": ".run/backlog_drafts/func_800CB17C.c", "binary": "md_MAIN_020", "source": "worker", "residual": null, "passes_tried": null}
{"ts": "2026-09-03 19:42:37", "addr": "0x80181e04", "name": "func_80181E04", "reach": null, "klass": null, "nins": null, "status": "failed", "closeness": null, "where_stuck": "won't compile standalone (loose-typing / missing decl)", "best_draft": ".run/backlog_drafts/func_80181E04.c", "binary": "ov_SC01_001", "source": "worker", "residual": null, "passes_tried": null}
+9 -9
View File
@@ -833,47 +833,47 @@ ifeq ($(BINARY),main)
# Wire in the real libcd objects (after the build objects exist — the externals discovery
# trial-links the whole image). Idempotent: re-running re-derives the externals only.
if [ -d "$(LIBCD_ELF)" ]; then
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) $(LIBCD_ELF) $(LD_SCRIPT) $(LIBCD_OBJDIR) $(LIBCD_SYMS) libcd1,libcd2
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) --yaml $(main_SPLAT_YAML) $(LIBCD_ELF) $(LD_SCRIPT) $(LIBCD_OBJDIR) $(LIBCD_SYMS) libcd1,libcd2
else
echo " (no $(LIBCD_ELF) — libcd region stays asm stubs; run tools/psyq_build_libs.sh LIBCD)"
fi
if [ -d "$(LIBGS_ELF)" ]; then
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) $(LIBGS_ELF) $(LD_SCRIPT) $(LIBGS_OBJDIR) $(LIBGS_SYMS) libgs1,libgs2,libgs3,libgs4,libgs5,libgs6 0x80051804 0x80057928
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) --yaml $(main_SPLAT_YAML) $(LIBGS_ELF) $(LD_SCRIPT) $(LIBGS_OBJDIR) $(LIBGS_SYMS) libgs1,libgs2,libgs3,libgs4,libgs5,libgs6 0x80051804 0x80057928
else
echo " (no $(LIBGS_ELF) — libgs region stays asm stubs; run tools/make_libgs.sh)"
fi
if [ -d "$(LIBETC_ELF)" ]; then
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) $(LIBETC_ELF) $(LD_SCRIPT) $(LIBETC_OBJDIR) $(LIBETC_SYMS) libetc
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) --yaml $(main_SPLAT_YAML) $(LIBETC_ELF) $(LD_SCRIPT) $(LIBETC_OBJDIR) $(LIBETC_SYMS) libetc
else
echo " (no $(LIBETC_ELF) — libetc region stays asm stubs; run tools/psyq_build_libs.sh LIBETC)"
fi
if [ -d "$(LIBGPU_ELF)" ]; then
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) $(LIBGPU_ELF) $(LD_SCRIPT) $(LIBGPU_OBJDIR) $(LIBGPU_SYMS) libgpu
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) --yaml $(main_SPLAT_YAML) $(LIBGPU_ELF) $(LD_SCRIPT) $(LIBGPU_OBJDIR) $(LIBGPU_SYMS) libgpu
else
echo " (no $(LIBGPU_ELF) — libgpu region stays asm stubs; run tools/psyq_build_libs.sh LIBGPU + curate libgpu_used)"
fi
if [ -d "$(LIBMCRD_ELF)" ]; then
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) $(LIBMCRD_ELF) $(LD_SCRIPT) $(LIBMCRD_OBJDIR) $(LIBMCRD_SYMS) libmcrd1,libmcrd2
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) --yaml $(main_SPLAT_YAML) $(LIBMCRD_ELF) $(LD_SCRIPT) $(LIBMCRD_OBJDIR) $(LIBMCRD_SYMS) libmcrd1,libmcrd2
else
echo " (no $(LIBMCRD_ELF) — libmcrd region stays asm stubs; run tools/psyq_build_libs.sh LIBMCRD)"
fi
if [ -d "$(LIBC2_ELF)" ]; then
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) $(LIBC2_ELF) $(LD_SCRIPT) $(LIBC2_OBJDIR) $(LIBC2_SYMS) libc2_1,libc2_2
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) --yaml $(main_SPLAT_YAML) $(LIBC2_ELF) $(LD_SCRIPT) $(LIBC2_OBJDIR) $(LIBC2_SYMS) libc2_1,libc2_2
else
echo " (no $(LIBC2_ELF) — libc2 region stays asm stubs; run tools/psyq_build_libs.sh LIBC2)"
fi
if [ -d "$(LIBGTE_ELF)" ]; then
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) $(LIBGTE_ELF) $(LD_SCRIPT) $(LIBGTE_OBJDIR) $(LIBGTE_SYMS) $(LIBGTE_STUBS) 0x8004787C 0x80051804
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) --yaml $(main_SPLAT_YAML) $(LIBGTE_ELF) $(LD_SCRIPT) $(LIBGTE_OBJDIR) $(LIBGTE_SYMS) $(LIBGTE_STUBS) 0x8004787C 0x80051804
else
echo " (no $(LIBGTE_ELF) — libgte region stays asm stubs; run tools/psyq_build_libs.sh LIBGTE)"
fi
if [ -d "$(SND_ELF)" ]; then
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) $(SND_ELF) $(LD_SCRIPT) $(SND_OBJDIR) $(SND_SYMS) $(SND_STUBS) 0x8003A444 0x8004239C
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) --yaml $(main_SPLAT_YAML) $(SND_ELF) $(LD_SCRIPT) $(SND_OBJDIR) $(SND_SYMS) $(SND_STUBS) 0x8003A444 0x8004239C
else
echo " (no $(SND_ELF) — sound region stays asm stubs; run tools/psyq_build_libs.sh LIBSPU LIBSND + tools/make_snd_used.py)"
fi
if [ -d "$(APICARD_ELF)" ]; then
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) $(APICARD_ELF) $(LD_SCRIPT) $(APICARD_OBJDIR) $(APICARD_SYMS) $(APICARD_STUBS) 0x80061F38 0x80062888
$(PYTHON) tools/psyq_integrate.py --vram-base $(main_VRAM_BASE) --exe $(main_EXE) --symbols $(main_SYMBOLS) --yaml $(main_SPLAT_YAML) $(APICARD_ELF) $(LD_SCRIPT) $(APICARD_OBJDIR) $(APICARD_SYMS) $(APICARD_STUBS) 0x80061F38 0x80062888
else
echo " (no $(APICARD_ELF) — apicard region stays asm stubs; run tools/psyq_build_libs.sh LIBAPI LIBCARD + tools/make_apicard_used.py)"
fi
+48 -2
View File
@@ -6,7 +6,7 @@
// - `D_800629D4` added: a data label in the text->data boundary region that the boot code
// references but splat did not auto-label (keeps the all-asm link resolving; no bytes change).
// Durable text record of manual RE work (the .rep is gitignored).
// count=968
// count=1081
lzss_ringBuffer = 0x1F800000; // data
start = 0x80010000; // func
@@ -847,6 +847,41 @@ PUTS_OBJ_2C = 0x8005CD74; // func
longjmp = 0x8005CDD4; // func
CloseEvent = 0x8005CE88; // func
DisableEvent = 0x8005CEC8; // func
PadChkVsync = 0x8005D0D8; // func
PadStartCom = 0x8005D0F8; // func
PadStopCom = 0x8005D118; // func
PadChkMtap = 0x8005D138; // func
PadGetState = 0x8005D184; // func
PadInfoMode = 0x8005D244; // func
PadInfoAct = 0x8005D33C; // func
PadInfoComb = 0x8005D410; // func
PadSetActAlign = 0x8005D4B8; // func
PadSetMainMode = 0x8005D4F0; // func
PadSetAct = 0x8005D538; // func
PadEnableCom = 0x8005D588; // func
_padSetVsyncParam = 0x8005D6A0; // func
_padChkVsync = 0x8005D8A0; // func
_padStartCom = 0x8005D8B4; // func
_padStopCom = 0x8005D980; // func
_padInitSioMode = 0x8005D9C4; // func
_padSioRW = 0x8005DCA0; // func
_padSioRW2 = 0x8005DE78; // func
_padClrIntSio0 = 0x8005E0AC; // func
_padWaitRXready = 0x8005E13C; // func
_padSetAct = 0x8005E188; // func
_padSetCmd = 0x8005E194; // func
_padSendAtLoadInfo = 0x8005E1A4; // func
_padRecvAtLoadInfo = 0x8005E228; // func
_padGetActSize = 0x8005E374; // func
_padLoadActInfo = 0x8005E3AC; // func
_padSetActAlign = 0x8005E79C; // func
_padSetMainMode = 0x8005E8E8; // func
_padCmdParaMode = 0x8005EA34; // func
PadInitDirect = 0x8005F0C8; // func
_padInitDirSeq = 0x8005F728; // func
_dirFailAuto = 0x8005FA94; // func
setRC2wait = 0x8005FBA8; // func
chkRC2wait = 0x8005FBC8; // func
MemCardEnd = 0x8005FC98; // func
MemCardStop = 0x8005FD18; // func
LIBMCRD_OBJ_15C = 0x8005FDC4; // func
@@ -926,10 +961,21 @@ _card_close = 0x80061A80; // func
_card_stop = 0x80061AA0; // func
STRCAT_OBJ_8C = 0x80061F1C; // func
erase = 0x80061F98; // func
firstfile = 0x80061FA8; // func
SetInitPadFlag = 0x80062388; // func
ReadInitPadFlag = 0x80062394; // func
PAD_init = 0x800623A4; // func
InitPAD = 0x80062434; // func
StartPAD = 0x800624C4; // func
StopPAD = 0x800624F4; // func
InitPAD2 = 0x80062688; // func
StartPAD2 = 0x80062698; // func
StopPAD2 = 0x800626A8; // func
PAD_init2 = 0x800626B8; // func
EnablePAD = 0x800626C8; // func
DisablePAD = 0x800626DC; // func
_patch_pad = 0x800626F0; // func
_remove_ChgclrPAD = 0x80062768; // func
StopCARD2 = 0x800627F8; // func
USERFUNC_OBJ_84 = 0x8006290C; // func
D_800629D4 = 0x800629D4; // data
@@ -1001,7 +1047,7 @@ DMACallback = 0x800425e0; // func PsyQ libetc (xdedup vs xen
startIntr = 0x80042718; // func PsyQ libetc (xdedup vs xenogears, Phase 21)
startIntrVSync = 0x80042c90; // func PsyQ libetc (xdedup vs xenogears, Phase 21)
startIntrDMA = 0x80042db8; // func PsyQ libetc (xdedup vs xenogears, Phase 21)
DecDCToutCallback = 0x800430b8; // func PsyQ libpress (xdedup vs vagrant-story, Phase 21)
CdGetToc = 0x800430B8; // func PsyQ libcd TOC.o (S78 - the linked byte-identical object outranks the Phase-21 xdedup-vs-VS label DecDCToutCallback)
CdMix = 0x80043974; // func PsyQ libcd (xdedup vs xenogears, Phase 21)
CD_vol = 0x80044a8c; // func PsyQ libcd (xdedup vs xenogears, Phase 21)
CD_flush = 0x80044b14; // func PsyQ libcd (xdedup vs xenogears, Phase 21)
+49 -49
View File
@@ -1574,7 +1574,7 @@
},
{
"binary": "main",
"fn": "func_8005D33C",
"fn": "PadInfoAct",
"addr": "0x8005d33c",
"nins": 53,
"cls": "SDK-C-REORDER",
@@ -1582,11 +1582,11 @@
"unit_entry": "func_8005d33c",
"unit_nins": 53,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005D410",
"fn": "PadInfoComb",
"addr": "0x8005d410",
"nins": 42,
"cls": "SDK-C-REORDER",
@@ -1594,11 +1594,11 @@
"unit_entry": "func_8005d410",
"unit_nins": 42,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005D4B8",
"fn": "PadSetActAlign",
"addr": "0x8005d4b8",
"nins": 14,
"cls": "SDK-C-REORDER",
@@ -1606,11 +1606,11 @@
"unit_entry": "func_8005d4b8",
"unit_nins": 14,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005D4F0",
"fn": "PadSetMainMode",
"addr": "0x8005d4f0",
"nins": 18,
"cls": "SDK-C-REORDER",
@@ -1618,11 +1618,11 @@
"unit_entry": "func_8005d4f0",
"unit_nins": 18,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005D538",
"fn": "PadSetAct",
"addr": "0x8005d538",
"nins": 20,
"cls": "SDK-C-REORDER",
@@ -1630,11 +1630,11 @@
"unit_entry": "func_8005d538",
"unit_nins": 20,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005D588",
"fn": "PadEnableCom",
"addr": "0x8005d588",
"nins": 70,
"cls": "SDK-C-REORDER",
@@ -1642,7 +1642,7 @@
"unit_entry": "func_8005d588",
"unit_nins": 70,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 4 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 4 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
@@ -1658,19 +1658,19 @@
},
{
"binary": "main",
"fn": "func_8005D8A0",
"fn": "_padChkVsync",
"addr": "0x8005d8a0",
"nins": 5,
"cls": "SDK-C-REORDER",
"disposition": "DECOMPILE-NOW",
"unit_entry": "func_8005D8A0",
"unit_entry": "_padChkVsync",
"unit_nins": 5,
"path": "src/800c3.c",
"why": "label-only `asm(\".section .text ... \"func_8005D8A0:\")` block MISSED by all three detectors; 5-ins leaf"
"why": "label-only `asm(\".section .text ... \"_padChkVsync:\")` block MISSED by all three detectors; 5-ins leaf"
},
{
"binary": "main",
"fn": "func_8005D8B4",
"fn": "_padStartCom",
"addr": "0x8005d8b4",
"nins": 51,
"cls": "SDK-C-REORDER",
@@ -1678,11 +1678,11 @@
"unit_entry": "func_8005d8b4",
"unit_nins": 51,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005E13C",
"fn": "_padWaitRXready",
"addr": "0x8005e13c",
"nins": 11,
"cls": "SDK-C-REORDER",
@@ -1694,7 +1694,7 @@
},
{
"binary": "main",
"fn": "func_8005E228",
"fn": "_padRecvAtLoadInfo",
"addr": "0x8005e228",
"nins": 83,
"cls": "SDK-C-REORDER",
@@ -1702,11 +1702,11 @@
"unit_entry": "func_8005e228",
"unit_nins": 83,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005E3AC",
"fn": "_padLoadActInfo",
"addr": "0x8005e3ac",
"nins": 53,
"cls": "SDK-C-REORDER",
@@ -1714,11 +1714,11 @@
"unit_entry": "func_8005e3ac",
"unit_nins": 53,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005E79C",
"fn": "_padSetActAlign",
"addr": "0x8005e79c",
"nins": 26,
"cls": "SDK-C-REORDER",
@@ -1726,11 +1726,11 @@
"unit_entry": "func_8005e79c",
"unit_nins": 26,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 3 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005E8E8",
"fn": "_padSetMainMode",
"addr": "0x8005e8e8",
"nins": 38,
"cls": "SDK-C-REORDER",
@@ -1738,7 +1738,7 @@
"unit_entry": "func_8005e8e8",
"unit_nins": 38,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 5 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 5 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
@@ -1762,7 +1762,7 @@
"unit_entry": "func_8005eae8",
"unit_nins": 16,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
@@ -1774,7 +1774,7 @@
"unit_entry": "func_8005eb28",
"unit_nins": 54,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
@@ -1786,7 +1786,7 @@
"unit_entry": "func_8005ec00",
"unit_nins": 48,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
@@ -1798,7 +1798,7 @@
"unit_entry": "func_8005ed4c",
"unit_nins": 223,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 7 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 7 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
@@ -1810,11 +1810,11 @@
"unit_entry": "func_8005f450",
"unit_nins": 159,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005F728",
"fn": "_padInitDirSeq",
"addr": "0x8005f728",
"nins": 13,
"cls": "SDK-ASM",
@@ -1826,7 +1826,7 @@
},
{
"binary": "main",
"fn": "func_8005FA94",
"fn": "_dirFailAuto",
"addr": "0x8005fa94",
"nins": 55,
"cls": "SDK-C-REORDER",
@@ -1834,11 +1834,11 @@
"unit_entry": "func_8005fa94",
"unit_nins": 55,
"path": "src/800c3.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_8005FBA8",
"fn": "setRC2wait",
"addr": "0x8005fba8",
"nins": 8,
"cls": "SDK-ASM",
@@ -1850,19 +1850,19 @@
},
{
"binary": "main",
"fn": "func_80062388",
"fn": "SetInitPadFlag",
"addr": "0x80062388",
"nins": 3,
"cls": "SDK-ASM",
"disposition": "PERMANENT-VERBATIM",
"unit_entry": "func_80062388",
"unit_entry": "SetInitPadFlag",
"unit_nins": 3,
"path": "src/800c2_2.c",
"why": "lui $at; jr $ra; sw $a0,lo($at) \u2014 hand-written setter (libcard region, 800c2 reorder island)"
},
{
"binary": "main",
"fn": "func_800623A4",
"fn": "PAD_init",
"addr": "0x800623a4",
"nins": 36,
"cls": "SDK-C-REORDER",
@@ -1870,19 +1870,19 @@
"unit_entry": "func_800623a4",
"unit_nins": 36,
"path": "src/800c2_2.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 5 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 5 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_80062434",
"fn": "InitPAD",
"addr": "0x80062434",
"nins": 36,
"cls": "SDK-C-REORDER",
"disposition": "DECOMPILE-NOW",
"unit_entry": "func_80062434",
"unit_entry": "InitPAD",
"unit_nins": 36,
"path": "src/800c2_2.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 5 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 5 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
@@ -1894,11 +1894,11 @@
"unit_entry": "func_8006252c",
"unit_nins": 30,
"path": "src/800c2_2.c",
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL func_8005D244/func_8005DCA0/func_80061FA8 carry t"
"why": "\u00a7188 shape (jr $ra + addiu $sp in slot, 2 restores) \u2014 produced by the as -O2 REORDER island (Makefile REORDER_TUS, landed 2026-09-01, commit:3557); REAL PadInfoMode/_padSioRW/firstfile carry t"
},
{
"binary": "main",
"fn": "func_800626C8",
"fn": "EnablePAD",
"addr": "0x800626c8",
"nins": 5,
"cls": "SDK-ASM",
@@ -1910,7 +1910,7 @@
},
{
"binary": "main",
"fn": "func_800626DC",
"fn": "DisablePAD",
"addr": "0x800626dc",
"nins": 5,
"cls": "SDK-ASM",
@@ -1922,7 +1922,7 @@
},
{
"binary": "main",
"fn": "func_800626F0",
"fn": "_patch_pad",
"addr": "0x800626f0",
"nins": 30,
"cls": "SDK-ASM",
@@ -1930,16 +1930,16 @@
"unit_entry": "func_800626f0",
"unit_nins": 30,
"path": "src/800c2_3.c",
"why": "hand-written (sibling of func_80062768)"
"why": "hand-written (sibling of _remove_ChgclrPAD)"
},
{
"binary": "main",
"fn": "func_80062768",
"fn": "_remove_ChgclrPAD",
"addr": "0x80062768",
"nins": 28,
"cls": "SDK-ASM",
"disposition": "PERMANENT-VERBATIM",
"unit_entry": "func_80062768",
"unit_entry": "_remove_ChgclrPAD",
"unit_nins": 28,
"path": "src/800c2_3.c",
"why": "splat Handwritten; B0-table call with $ra stashed in D_80078D28"
+4 -4
View File
@@ -4,11 +4,11 @@
# part of every tool fix, or it becomes a list of work you decided not to do.
main:PopMatrix # WALL: compiler wall (merged from S68_walls_332.txt)
main:PushMatrix # WALL: compiler wall (merged from S68_walls_332.txt)
main:func_8005D9C4 # WALL: no jump table — curated compiler fact, not a tooling limit
main:_padInitSioMode # WALL: no jump table — curated compiler fact, not a tooling limit
main:func_8005ECC0 # NEAR-2/35 (DELAY-SLOT) — NOT a wall. Same wrong-oracle provenance as
# func_8005F0C8; re-measured S77 at 2 of 35. permuter_ils 4 cycles reached 5, not 0.
# PadInitDirect; re-measured S77 at 2 of 35. permuter_ils 4 cycles reached 5, not 0.
# Excluded as UNSOLVED, not as impossible.
main:func_8005F0C8 # NEAR-3/88 (ADDRESSING/move!=lui) — NOT a wall. The S68 'compiler wall'
main:PadInitDirect # NEAR-3/88 (ADDRESSING/move!=lui) — NOT a wall. The S68 'compiler wall'
# verdict was measured under the WRONG oracle (800c3 is a REORDER_TUS island; S76 fixed
# match_one/rtu_match to use reorder_passthrough + as -O2). Re-measured S77: 3 of 88.
# permuter_ils 4 cycles reached 3, not 0. Excluded as UNSOLVED, not as impossible.
@@ -19,6 +19,6 @@ ov_SC06_022:func_8017DF28 # WALL: expand_block_move copy_addr_to_reg pseudo + c
# S77: wall_sweep named these and the list did not carry them — an agent handed one
# always returns a NEAR with an unexplainable tail, indistinguishable from a hard function.
main:func_8005D734 # WALL: §332 %lo in a delay slot (wall_sweep, 1 site) — no C can place it
main:func_8005D8B4 # WALL: §332 %lo in a delay slot (wall_sweep, 1 site) — no C can place it
main:_padStartCom # WALL: §332 %lo in a delay slot (wall_sweep, 1 site) — no C can place it
main:func_8005ED4C # WALL: §332 %lo in a delay slot (wall_sweep, 2 sites) — no C can place it
main:func_8005F450 # WALL: §332 %lo in a delay slot (wall_sweep, 2 sites) — no C can place it
+6 -3
View File
@@ -337,7 +337,7 @@ Phase 4's observable milestone: a `check-env` make target that asserts every §4
### §5.1 The evidence
Locally verified on the extracted US EXE (DetectPsyQ-style masked-pattern scan): **13 pattern hits, of which 12 are genuine `Ps` library stamps** — 9× PsyQ **4.0** (libnums 2, 3, 4, 6, 7, 8, 9, 17, 24), 1× **4.0.1x** (libnum 16), 1× **4.2** (libnum 0), 1× **4.2.1x** (libnum 12); the remaining hit (ver 0x0000 at vaddr 0x8005CD20) is a code false positive. A raw-track scan during research reported 16 hits with extra spurious 4.0 stamps — the extracted-EXE scan is ground truth, and ghidra_psx_ldr's detection at import is the final word (ledger #12). Library copyright string `(c) 1993-1997 Sony` corroborates the era. Conclusion: BFM links **PsyQ 4.0 libraries with 4.2 library updates** ⇒ the GCC 2.7.2/SN32-era toolchain — **NOT sotn's GCC 2.6.3** (the starting-point doc's claim is corrected). PsyQ 4.2 was a library-only refresh: no 4.2 toolchain disc survives (absent from redump/arthus sets), so 4.2 stamps still mean the 4.0/4.1 toolchain.
Locally verified on the extracted US EXE (DetectPsyQ-style masked-pattern scan): **13 pattern hits, of which 12 are genuine `Ps` library stamps** — 9× PsyQ **4.0** (libnums 2, 3, 4, 6, 7, 8, 9, 17, 24), 1× **4.0.1x** (libnum 16), 1× **4.2** (libnum 0), 1× **4.2.1x** (libnum 12); the remaining hit (ver 0x0000 at vaddr 0x8005CD20) is a code false positive. **Identified (P31 S78, byte-placed via the psx loader's per-version signature sets, `~/ghidra_12.1_PUBLIC/Ghidra/Extensions/ghidra_psx_ldr/data/psyq/<ver>/<LIB>.LIB.json`):** the 4.2 stamp at `0x8005CE48` is **LIBAPI 4.2 `C114.OBJ` (`_96_remove`)** at the head of the `800c3` band, and the 4.2.1x stamp at `0x80072954` sits in front of **LIBPAD 4.2.1's** `.data` (the callback tables `D_8007295C..D_800729D8`); the band `0x8005CF68–0x8005FC68` is COUNTER (libapi) · PADENTRY · PADMAIN · L02/L03 · PADCMD · PADIF · PADPORTD · PADSEQD · WAITRC2 (libpad), and `FIRST`/`PAD`/`PATCH`/`CHCLRPAD` (libapi 4.2) sit in `800c2`. See `docs/psyq-worklist.md` "S78". A raw-track scan during research reported 16 hits with extra spurious 4.0 stamps — the extracted-EXE scan is ground truth, and ghidra_psx_ldr's detection at import is the final word (ledger #12). Library copyright string `(c) 1993-1997 Sony` corroborates the era. Conclusion: BFM links **PsyQ 4.0 libraries with 4.2 library updates** ⇒ the GCC 2.7.2/SN32-era toolchain — **NOT sotn's GCC 2.6.3** (the starting-point doc's claim is corrected). PsyQ 4.2 was a library-only refresh: no 4.2 toolchain disc survives (absent from redump/arthus sets), so 4.2 stamps still mean the 4.0/4.1 toolchain.
Caveat: `Ps` stamps date the **linked libraries**, not the compiler that built game code — Square mixed cc1 builds within one EXE (see §5.5). The final triple is pinned only by Phase-6 fingerprinting.
@@ -399,6 +399,8 @@ Phase 18 (raise the match-% ceiling by understanding gcc-2.7.2's blocking codege
| `pmret/gcc-papermario` | ⚠️ **actually gcc 2.8.1, NOT 2.7.2** (behavioral diff: 2.8.1 `&&0`-disables biv-elim paths ENABLED in real 2.7.2 — caught Phase 23). OK for passes where 2.8.1≡2.7.2, but **cite `gcc-2.7.2/` below for accuracy**. | `tools/reference/gcc-papermario` | `master` | `a6afc2afbcaf6682930141d526afdc95801fc2fd` |
| **vanilla gcc-2.7.2** (the REAL source of our pinned cc1) | authoritative source for the codegen map (cookbook §31/§34 + `docs/gcc-2.7.2-map/`): `sched.c`/`reorg.c` (scheduling), `local-alloc.c`/`global.c`/`reload1.c` (regalloc), `loop.c` (IV/hoist), `cse.c`/`expr.c` (CSE/aliasing). Staged Phase 23; **completed Phase 24 T5** (18 `.c` files — +toplev.c/function.c/flow.c/… from the FSF tarball; sched.c/loop.c/mips.c verified byte-identical to vanilla → §34's `local-alloc.c:1441` 3-qty-sort-bug citation is sound). **P31 T2: +6 files** — `calls.c` + `caller-save.c` (both cited by §172's frame-residue producer model, previously MISSING) + `integrate.c`/`optabs.c`/`varasm.c`/`recog.c` — from GNU ftp `gcc-2.7.2.tar.gz`, sha256 `7cd8bce5c3aeec59a72ecc2d3d5123864a817b14cdbd0680b1a969c3bccc5da5`. | `tools/reference/gcc-2.7.2` | GNU 2.7.2 release | (re-fetch: GNU ftp `gcc-2.7.2.tar.gz`; tarball kept at `.run/t7/fable/gcc-2.7.2.tar.gz`) |
| `ladysilverberg/xenogears-decomp` | Square, Oct 1998, **gcc-2.7.2-psx + -cdk** (our exact compiler); mine transferable quirk idioms + `gears.toml` per-module presets | `tools/reference/xenogears-decomp` | `main` | `f27c0768b1ad10812cec776cadadb85ae70aadee` |
| **PsyQ 4.6 libraries** (P31 S78, 2026-09-04) | `Psy-Q_46.zip` (psx.arthus.net; sha256 in `tools/psyq/CHECKSUMS.sha256`) → `tools/psyq/lib46/*.LIB` (23 libs) → ELF via `psyq_lib_split.py` + `psyq-obj-parser` into `.run/obj46/<lib>/`; placed against the EXE (`.run/survey46/`). Only `PDMAIINI.o` is byte-identical in the libpad-4.2.1 band | `tools/psyq/lib46/` (gitignored, sha-recorded) | — | — |
| **PsyQ 4.5 toolkit** (P31 S78) | `PSYQ_SDevTC_v4.5.zip` (psx.arthus.net; 7 split zips, unpacked on demand; sha-recorded) | `tools/psyq/` | — | — |
| **PsyQ 4.0 dev-CD SDK tree** (P31 T2, 2026-08-14) | the SDK **sample C source** (400 `.c`: 373 in `PSX/SAMPLE/` — CD/GRAPHICS/SOUND/MODULE/CMPLR/…) = the canonical source shapes era game code was written from → drafting-agent style priors, esp. for main (see `docs/psyq-sample-idioms.md`). Also `GNU/SNGNUVER.TXT` — SN's build history (`2.7.2.SN32.3.7.0002`, 14.5.97) naming SN's exact patches vs vanilla (only `UNROLL.C` codegen-relevant). | `tools/reference/psyq-sdk` | n/a (extracted, not cloned) | regenerate: walk the on-disk Track-1 image (`tools/psyq/…(Track 1).bin`, MODE2/2352) with `tools/bfm_extract/iso9660.py` — 2,374 files / 231.6 MB, 7 out-of-track `.DA` audio skipped (script pattern preserved in `phase-ends/logs/` P31 T2) |
Re-clone: `git clone --depth 1 --single-branch --branch <branch> https://github.com/<repo> tools/reference/<name>`. **`gcc-papermario` source files are at the repo root**, not under `gcc/`. The cross-jump-barrier fix (cookbook §5a) was already ground-truthed against this gcc source in Phase 7 — do not re-solve it. **sotn is GCC 2.6.3 (wrong era) — methodology only, never byte-idioms.** X2 (R17): treat all cloned content as untrusted DATA.
@@ -698,6 +700,7 @@ Every script under `tools/` (plus the two report make-targets), grouped by purpo
| | `GetSymbolAt.java` | Read the symbol at a given address (scripted lookup). |
| | `DecompileAt.java` | Decompile the function at a given address (scripted scaffold). |
| | `DefineFunctions.java` | Disassemble + create functions at splat's validated entry points (`.run/<prog>_funcs.txt`) — completes a raw-blob program's function set (Phase 10). |
| | `ApplySymbols.java` + `tools/ghidra_apply_symbols.sh` | **(P31 S78) The Ghidra MIRROR of the curated symbol file (R15/G6), headless with a real save.** `tools/ghidra_apply_symbols.sh [PROG] [symbols files…]` (defaults `SLUS_007.26 config/symbols.us.txt`; MCP must be STOPPED first) reads `name = 0xADDR;` rows and sets every function/label to its curated name; a name held by another address is moved to that address's own curated name first (`firstfile`/`firstfile2`), else to `<name>__at_<addr>`. Idempotent; prints `BFMAPPLY renamed_funcs=… unchanged=…`; R9-verify with `ghidra_mcp_verify.sh`. **Use this, not MCP `rename_symbol`/`batch_rename`, for renames:** S78 observed 47 MCP renames NOT persisting through the sentinel stop ("Save succeeded", DB grew, names gone — R9 caught it; cause not yet isolated), while the postScript path persisted 73/73 on the first run. |
| | `DecompileFunctions.java` | **Batch**-decompile a list of addresses (arg0 = addr-per-line file, arg1 = out-dir) → `<name>.c` each. Headless harvest Ghidra-C pre-pass (Phase 17); no live MCP / `/mcp` needed. Run: stop MCP, `analyzeHeadless ghidra bfm -process <prog> -noanalysis -postScript DecompileFunctions.java <addrfile> <outdir>`. |
| | `tools/ghidra_import.sh` | Headless `analyzeHeadless` import/analysis driver (PS-X EXE; auto-detect PSX loader). |
| | `tools/ghidra_import_raw.sh` | Headless import of a RAW flat blob — `BinaryLoader` + `--loader-baseAddr <vram>` + `PSX:LE:32:default` (resident blob / Gen2 overlays; no PS-X EXE header). |
@@ -729,7 +732,7 @@ Every script under `tools/` (plus the two report make-targets), grouped by purpo
| | `tools/psyq_link.py` | Link identified PsyQ objects into the build. |
| | `tools/psyq_link_lib.py` | Per-library link driver. |
| | `tools/psyq_link_region.py` | Link a specific address region from PsyQ libs. |
| | `tools/psyq_integrate.py` | Integrate linked PsyQ results back into the source tree. |
| | `tools/psyq_integrate.py` | Integrate linked PsyQ results back into the source tree. **P31 S78:** `--yaml <splat yaml>` (every main call passes `$(main_SPLAT_YAML)`) maps stub↔objects by SUBSEG RANGE with an exact-tiling check and PRINTS the located-but-unwired objects (`~~ N located object(s) / M ins OUTSIDE the stub subsegs`) — the completion contract's SDK-residue line; and a library object's DEFINED symbol whose recovered address the curated symbol file names differently is `--redefine-sym`'d to the curated name (R15; e.g. libapi 4.0 `A66.o` `firstfile`→`firstfile2`). Without `--yaml` the old contiguity mapping runs (overlay-free libraries only). |
| | `tools/make_libgs.sh` | Build/link the `libgs` block (cookbook §9). |
| | `tools/gen_lib_subsegs.py` | **(Phase 8)** Generate splat subseg lines + integrate stub list for a multi-block library (section-size-correct boundaries; cookbook §9.6). |
| | `tools/make_snd_used.py` | **(Phase 8)** Build the combined libspu+libsnd curated dir (alias dedup by byte-match, scattered-`.bss` exclusions; §9.6). |
@@ -798,7 +801,7 @@ Every script under `tools/` (plus the two report make-targets), grouped by purpo
| | `tools/corpus.py` `o0_sources()` / `is_o0()` | **(Phase 29 T13A)** The opt-level oracle, DERIVED from the Makefile's own `-O0` `CC1FLAGS` rules (explicit targets + `$(wildcard)`-built object lists) with a coverage assertion: an unrecognised rule form raises rather than mislabelling. Scoring an -O0 target's draft at -O2 makes the whole residual an artefact — the trap this phase hit four times. |
| | `tools/permuter_weights.py` | **(Phase 24 T5, cookbook §3b)** §31-directed permuter mutation: `classify(klass, where)` → `regalloc\|schedule\|cse\|None`, `render_settings_toml()` emits the `[weight_overrides]` table decomp-permuter merges over the gcc defaults (`main.py:336` / `helpers.py:merge`). Biases pass-selection toward the class's §31 levers (`perm_reorder_decls` RC-1/3, `perm_reorder_stmts` RC-2/S1, `perm_temp_for_expr` S2, `perm_commutative` cse) and away from value/type noise. No submodule edit. `klass=None` → gcc defaults (unchanged). |
| | `tools/p16_permute.py` | Per-fn permuter driver: `setup(fn, draft, asm_subdir, klass=, where=)` builds `base.c`+`target.o`+`settings.toml` (now with the T5 `[weight_overrides]`), `run_permuter` via `run_masked.py` (T2 floor-free masked scorer). `--klass` overrides the backlog auto-lookup. |
| | `tools/lint_symbol_refs.py` | **(Phase 24 T5c)** Guard against the Phase-21-class breakage: flags every `func_<ADDR>` token in committed `src/` whose address has a CURATED name in the symbol files and no `func_<ADDR>` symbol (a rename that would break a genuinely-clean rebuild but is masked by incremental builds — R22). Comment/string-aware. Exit 1 on stale refs. **Run after any symbols rename**; candidate for `make report`. Caught the T5b (macro-call) + T5c (INCLUDE_ASM) refs. |
| | `tools/lint_symbol_refs.py` | **(Phase 24 T5c)** Guard against the Phase-21-class breakage: flags every `func_<ADDR>` token in committed `src/` whose address has a CURATED name in the symbol files and no `func_<ADDR>` symbol (a rename that would break a genuinely-clean rebuild but is masked by incremental builds — R22). Comment/string-aware. Exit 1 on stale refs. **Run after any symbols rename**; candidate for `make report`. Caught the T5b (macro-call) + T5c (INCLUDE_ASM) refs. **P31 S78:** also scans the §265 verbatim `__asm__("...")` string bodies (`.ent\tfunc_X`, `.globl func_X`, `func_X:`), where the masked scan was blind and a `\b`-regex rename misses `\tfunc_X`; `__asm__`-label-bound addresses exempted (negative-controlled on the passing tree). |
| | `tools/api_draft.py` | Provider-agnostic LEAN drafter against the served model's OpenAI endpoint. `LEAN_SYS` carries the "translate every instruction, never an empty body" clause (Phase 23 — fixes the v2 empty-leaf overfit). |
| | `tools/serve_local.py` | **Serve the fine-tuned model on the GPU** (base+LoRA via Unsloth, `.venv-train`, OpenAI endpoint) — the in-repo replacement for LM Studio. Run: `LD_LIBRARY_PATH=$(ls -d .venv-train/lib/python3.12/site-packages/nvidia/*/lib \| tr '\n' :) .venv-train/bin/python tools/serve_local.py --adapter models/bfm-match-7b-v3 --name bfm-match-7b-v3 --port 1234`. (Prebuilt `llama-cpp-python` CUDA wheels SIGILL on this no-AVX-512 CPU; the Unsloth/torch path is reliable, no build.) |
| | `tools/export_pairs.py` / `format_finetune.py` / `train_lora.py` / `eval_lora.py` | The corpus→LoRA pipeline (`.venv-train`): mine (asm↔C) pairs incl. the `engine_core.h` **macro bodies** + `engine_types.h` structs (corpus-v3) → Qwen chat-template + compile-filter → Unsloth QLoRA (3080 Ti) → held-out gate-true eval. Datasets/weights gitignored (`datasets/`, `models/`, `.venv-train/`). |
+12
View File
@@ -643,3 +643,15 @@ library code sat as verbatim asm for twenty-odd phases.
**Would-have-sped-up-earlier-work verdict.** None of these needed a new technique or a better model.
All three are self-assertions a tool can make about its own output in under five minutes of code,
and each was worth thousands of instructions the moment it was added.
## S78 — the loader shipped the answer key: per-version SDK signatures name library bands you cannot link
`ghidra_psx_ldr/data/psyq/<ver>/<LIB>.LIB.json` — masked signatures + labels per object, 2.6 → 4.7 —
sat on disk since Phase 1. Regexed over the EXE bytes it names the library, the version and every
function of a band **without the `.LIB`**, and it would have settled main's `800c3` band (LIBPAD
4.2.1: twelve "wall" stubs, four §332 verdicts) in Phase 8, the day the 4.2 stamps were first read.
Accelerator: **before calling a band a compiler wall, score every signature set you have against it;
the version that places the most objects byte-exact is the linked one.** Second, cheaper lesson: the
gates only ever built main WITHOUT the SDK objects (worktrees carry no `.run/obj40`), so the LINKED
path was never gated — `make build BINARY=main` in the real tree is the only check of it; run it
after any change to `psyq_identify`/`psyq_integrate`.
+7 -3
View File
@@ -2,7 +2,7 @@
> **Generated by `tools/cookbook_index.py` — do not hand-edit** (R33). Regenerate after adding a cookbook section.
>
> `docs/matching-cookbook.md` is ~716 KB / 1154 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses.
> `docs/matching-cookbook.md` is ~716 KB / 1155 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses.
**How to use:** name what you SEE in the diff (a stolen delay slot, an extra `la`, a swapped register pair, a `conflicting types` error), find that symptom below, read those sections first. If nothing fits, THEN grind — and add a section when you win.
@@ -643,7 +643,7 @@
- **§423** — ★★★ — "MATCH IN ISOLATION + GATE REJECTS + CAUSE NOT DETERMINED" ⇒ GREP THE TU FOR A FILE-SCOPE TYPEDEF THE DRAFT ALSO CARRIES (P31 S71; byte-proven `ov_SC03_092/func_8017FA74`) <sub>L33780</sub>
- **§481** — ★★★ — `conflicting types` IS A SAME-SCOPE ERROR; ACROSS SCOPES IT IS ONLY A WARNING (P31 S77, `main:func_8001FC08`, 400 ins) <sub>L35901</sub>
### declarations, prototypes & K&R (120)
### declarations, prototypes & K&R (121)
- **§3-T4** — Branch polarity: invert the source condition to flip gcc's chosen branch <sub>L90</sub>
- **§8c** — Splitting a TU means rebuilding its DECLARATION ENVIRONMENT, not moving text (Phase 26 session 6) <sub>L456</sub>
@@ -765,6 +765,7 @@
- **§468** — THE `%lo`-FOLD EXTENDS TO STORES ONLY VIA `extern Struct SYM[]`, AND MASKING HID THE OPERAND ORDER <sub>L35380</sub>
- **§477** — ★★★ — THE `self_decl_tu` CLASS IS A SOLVED, MECHANICAL LANE: 16 DRAFTS, 16 BANKS (P31 S77) <sub>L35713</sub>
- **§481** — ★★★ — `conflicting types` IS A SAME-SCOPE ERROR; ACROSS SCOPES IT IS ONLY A WARNING (P31 S77, `main:func_8001FC08`, 400 ins) <sub>L35901</sub>
- **§487** — ★★★ — THE PSX LOADER'S PER-VERSION SIGNATURE SETS ARE A FREE PROVENANCE ORACLE: main's "WALL" BAND IS LIBPAD 4.2.1 (P31 S78) <sub>L36150</sub>
### jump tables & switches (70)
@@ -1079,7 +1080,7 @@
- **§442** — ★★★ — A RECOVERY RUNG THAT REWRITES A LEGAL CONSTRUCT INTO AN ILLEGAL ONE READS EXACTLY LIKE A CODEGEN WALL (P31 S75; `reconcile_tu`, 344 ins unblocked) <sub>L34647</sub>
- **§477** — ★★★ — THE `self_decl_tu` CLASS IS A SOLVED, MECHANICAL LANE: 16 DRAFTS, 16 BANKS (P31 S77) <sub>L35713</sub>
### build graph, splat & the harness (206)
### build graph, splat & the harness (207)
- **§4** — Flag/toolchain gotchas <sub>L190</sub>
- **Build** — mechanism — per-file opt override (splat resegmentation) <sub>L307</sub>
@@ -1287,6 +1288,7 @@
- **§483** — ★★★ — THE S77w WAVE HARVEST: SIX LEVERS, FOUR FROM BANKED (BYTE-PROVEN) BODIES <sub>L35967</sub>
- **§484** — ★★★ — "NO SINGLE NOLOAD BASE" IS NOT "UNLINKABLE": ASK WHETHER THE `.bss` OFFSETS ARE DISJOINT (P31 S77) <sub>L36023</sub>
- **§485** — ★★★ — THE PLACEMENT MAP WAS PARSING A PRETTY-PRINTER: 25 PsyQ OBJECTS WERE INVISIBLE, NOT ABSENT (P31 S77) <sub>L36069</sub>
- **§487** — ★★★ — THE PSX LOADER'S PER-VERSION SIGNATURE SETS ARE A FREE PROVENANCE ORACLE: main's "WALL" BAND IS LIBPAD 4.2.1 (P31 S78) <sub>L36150</sub>
### process, measurement & doctrine (141)
@@ -2929,6 +2931,7 @@
- **§484** — ★★★ — "NO SINGLE NOLOAD BASE" IS NOT "UNLINKABLE": ASK WHETHER THE `.bss` OFFSETS ARE DISJOINT (P31 S77) <sub>L36023</sub>
- **§485** — ★★★ — THE PLACEMENT MAP WAS PARSING A PRETTY-PRINTER: 25 PsyQ OBJECTS WERE INVISIBLE, NOT ABSENT (P31 S77) <sub>L36069</sub>
- **§486** — ★★★ — CARVING AN `-O0` ISLAND IN **main**: FIVE COUPLED PIECES, AND THE TWO THAT ANNOUNCE THEMSELVES (P31 S77) <sub>L36105</sub>
- **§487** — ★★★ — THE PSX LOADER'S PER-VERSION SIGNATURE SETS ARE A FREE PROVENANCE ORACLE: main's "WALL" BAND IS LIBPAD 4.2.1 (P31 S78) <sub>L36150</sub>
---
@@ -4095,3 +4098,4 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: `
| L36023 | §484 | ★★★ — "NO SINGLE NOLOAD BASE" IS NOT "UNLINKABLE": ASK WHETHER THE `.bss` OFFSETS ARE DISJ |
| L36069 | §485 | ★★★ — THE PLACEMENT MAP WAS PARSING A PRETTY-PRINTER: 25 PsyQ OBJECTS WERE INVISIBLE, NOT |
| L36105 | §486 | ★★★ — CARVING AN `-O0` ISLAND IN **main**: FIVE COUPLED PIECES, AND THE TWO THAT ANNOUNCE |
| L36150 | §487 | ★★★ — THE PSX LOADER'S PER-VERSION SIGNATURE SETS ARE A FREE PROVENANCE ORACLE: main's "WA |
+37
View File
@@ -3063,3 +3063,40 @@ five minutes to add that check is repaid the first time the tool is wrong and so
**Also recorded:** a yield table is evidence; a story about WHY the yield looks that way is a
hypothesis and needs its own negative control before it enters the cookbook, because the next session
will act on it (§479's three versions).
## S78 (2026-09-04) — the completion sprint is chartered on a census, and main's "wall" band turned out to be Sony's controller library
**Context and belief going in.** Drew asked the direct question: what actually remains, are the
waves done, is the rest tooling? The working belief from S77 was that main's residual stubs were
compiler-wall work (§332 "%lo in a delay slot", §474 wall-proofs) — genuine codegen the pinned cc1
cannot reproduce from C.
**What was measured.** Fleet: 51 stubs / 7,710 ins of 13.5 M (0.06%), every one classified by its
true blocker (`frontier_classify`); 180 verbatim bodies of which only ~9 are Square's or the CRT's
own asm; 5,827 ins of located-but-unlinked SDK objects sitting in subsegs labelled "game code"; five
unclaimed disc payloads. No class needs an agent wave. Then the provenance probe: the psx loader's
per-version PsyQ signature sets (never used before) place the `800c3` band byte-exact as **LIBPAD
4.2.1 + LIBAPI 4.2** — twelve of main's twenty-nine stubs, including all four §332 walls, are Sony's
DualShock library assembled in reorder mode, not game code. PsyQ 4.0 (the archive we link from) has
no LIBPAD; 4.6/4.7 differ except one object. The 4.2/4.2.1x `Ps` stamps identified in Phase 1 were
these two libraries all along.
**The pivot.** The finish is ordered around provenance and plumbing, not cracking: name the band
(#12, done: 46 names, Ghidra-mirrored), wire every placed-but-unwired SDK object (#3/#4 — the
residue the build now prints), hunt a 4.2.1/4.3 LIBPAD.LIB (#13) and otherwise finish the band as C
under the reorder island with real names (#5), then the mechanical/plumbing/near classes, the ~22
genuine redrafts as single journal-noted agents, the verbatim end-state, and the PhaseEnd.
**What the first task exposed.** Main's LINKED build had been RED at HEAD since the S77
`psyq_identify` fix (§485): newly-located in-gap objects merged libgte's 22 stub blocks into 3.
It read green at the gates because worktree gates have no `.run/obj40` and take the stub fallback —
the dual "with AND without SDK objects" invariant was only ever verified by hand. Fixed by wiring
stub↔objects by subseg range (+ exact tiling) and by redefining a library object's exported symbol
to the curated name (`firstfile`/`firstfile2`, which also caught a Phase-21 xdedup mislabel at
0x800430B8). And a rename hazard: verbatim `__asm__` bodies spell `\tfunc_X`, invisible to a `\b`
regex and to the string-masking linter — the linter now scans asm bodies (negative-controlled).
**Hindsight.** The signature JSONs were on disk since Phase 1; one afternoon with them in Phase 8
would have named the band, explained the 4.2 stamps, and kept the §332 wall verdicts from ever being
written. General form (now cookbook §487): a wall inside bytes no archive you hold can place is a
provenance question before it is a compiler question.
+52
View File
@@ -36146,3 +36146,55 @@ failure.
**PRICE IT FIRST (R37).** The `-O0` detector (`o0_detect`) flags exactly **two** open main stubs:
this one, and `func_80011380`, which already lives in `-O0` `boot.c` and is §474's proved floor. So
this carve unblocked ONE function, not a class. Worth knowing before budgeting for more.
#### §487 ★★★ — THE PSX LOADER'S PER-VERSION SIGNATURE SETS ARE A FREE PROVENANCE ORACLE: main's "WALL" BAND IS LIBPAD 4.2.1 (P31 S78)
**The instrument.** `ghidra_psx_ldr` ships `data/psyq/<ver>/<LIB>.LIB.json` for every PsyQ release
(260 … 470): per OBJECT, a masked-byte signature of its `.text` plus function labels with offsets.
Matched as a regex over the retail EXE bytes (`??` → any byte, 4-aligned hits only), a set that places
an object byte-exact tells you the LIBRARY, the VERSION, and every FUNCTION NAME in it — with no
`.LIB` archive in hand. Score per (version, library) by in-band hits; the version whose set places
the most objects exactly is the linked one.
**What it found.** The `800c3` band `0x8005CF68–0x8005FC68` — twelve open main stubs, four of them
recorded as §332 "%lo in a delay slot, no C can place it" walls — is **LIBPAD 4.2.1** (PADENTRY,
PADMAIN, PADCMD, PADIF, PADPORTD, PADSEQD, WAITRC2) plus **LIBAPI 4.2** (COUNTER, L02/L03, FIRST,
PAD, PATCH, CHCLRPAD). The 4.2 set places 4/11 libpad objects byte-exact; 4.3 swaps one (PADSEQD 292
vs 288 ins) and adds WAITRC2; 4.4+ place only WAITRC2; the 4.2 `Ps` stamp sits on `C114.OBJ`
(`_96_remove`) at the band's head and the 4.2.1x stamp on libpad's `.data`. PsyQ 4.0 has no LIBPAD
(the DualShock library arrived in 4.2) — which is exactly why twenty phases of "not linked by EXE"
never found it. 46 names applied (`docs/psyq-worklist.md` S78).
**The reading rule.** Where the placed set's labels line up with the split's function starts
(PADENTRY: 11/11, PADCMD: 9/9), name from the label. Where the object placed but the set's later
labels drift by a few words (PADMAIN 4.2 vs the EXE's 4.2.1: +4 at `_padSioRW2`, +12 at
`_padClrIntSio0`/`_padWaitRXready`), the function ORDER still names them — record that as
order-inferred, not sig-exact. Statics carry no labels (PADIF) and stay `func_`.
**Three laws.**
1. **A "compiler wall" inside a band no archive you hold can place is a PROVENANCE question first.**
§332b already showed the band was assembled in reorder mode; that is what Sony's build did to
LIBPAD. Before pricing a wall-proof, ask which library version owns the bytes — a different
`.LIB` may link it outright (task #13), and even without it, the real name + the SDK header
turn "unknown 133-ins function" into `_padInitSioMode`.
2. **Placement is not wiring.** With the §485-fixed `psyq_identify`, in-gap objects (FGO_01–06 fill
the 800b_5 "game code" subseg to the byte) made `psyq_integrate.contiguous_blocks()` merge
libgte's 22 stub blocks into 3 and killed every LINKED build of main — silently at the S77 gates,
because worktree gates carry no `.run/obj40` and take the stub fallback. Map stub↔objects by
subseg RANGE with an exact-tiling check (`--yaml`), and print what was placed but not wired: that
list IS the completion contract's SDK residue.
3. **A library object's exported name is a claim of ITS version; the curated file's name at that
address wins (R15).** libapi 4.0's `A66.o` exports `firstfile` at 0x80062248 while the EXE links
4.2, where that trampoline is `firstfile2` and `firstfile` is `FIRST.o`'s C wrapper at
0x80061FA8 (LIBMCRD.o's `jal` word `EA87010C` says so). `--redefine-sym` at object-prep time;
references to the old name then resolve through the recovered relocation address, never by name.
The same rule caught libcd `TOC.o`'s `CdGetToc` @0x800430B8 curated as `DecDCToutCallback` — an
xdedup-vs-Vagrant-Story mislabel (a linked, byte-identical SDK object outranks a cross-project
name match).
**Renaming hazard (R32/R39, closed in `lint_symbol_refs`).** The §265 verbatim bodies spell the
name inside `__asm__("… .ent\tfunc_X …")`. The C-side rename regex with `\b` misses `\tfunc_X`
(the escape's `t` is a word char), gas then dies with `.size expression for func_X does not evaluate
to a constant`, and the string-masking linter was blind to it by construction. The linter now scans
asm string bodies too; negative control: red on the pre-fix TUs (4 hits), green on the fixed tree
and on every previously-passing TU (the `func_8005C324`→`memcpy` `__asm__`-label binding exempted).
+60
View File
@@ -94,3 +94,63 @@ All hits are the **§9.5 short-object coincidental class** (≤8 ins, masked pat
**Ghidra corroboration (G1, sampled):** `DsMix` decompiles to `{ FUN_800d1bf8(); return 1; }` — a custom 2-line wrapper that **ignores its `vol` arg** (NOT the stock libsnd `DsMix`; the R13 tag in `symbols.resident.txt` is refuted). Other sampled functions are game logic (global accessors, engine init calling EXE REAL matches, entity-heading math calling the EXE's libgte `RATAN`). The resident's code makes **61 distinct EXE-range `jal` calls** (vs 37 internal) — it **calls** the EXE's resident SDK rather than embedding it.
**Conclusion / architecture:** the PsyQ SDK lives in the **EXE** (959 LINKED); the **resident is ~143 functions of custom engine code** that calls the EXE's SDK + engine via fixed addresses (no RAM-wasting SDK duplication in an always-loaded blob). The DetectPsyQ "4.7.0" was a single coincidental DsMix-region signature, not a linked footprint. **Phase 12 matches the resident engine by hand (REAL), not by linking (LINKED stays 0).** R24's per-binary-provenance principle holds, but for the resident the practical consequence is "nothing to link." *(Regenerate: `for L in libsnd libspu libgte libgpu; do d=.run/obj47/$L; mkdir -p $d; (cd $d && ar x ../../tools/psyq/conv47/psyq-4_7-converted/lib/$L.a); python3 tools/psyq_identify.py $d 0x800CEDFC 0x800D3408 --vram-base 0x800CEDF8 --exe extracted/retail/MAIN.CD.dir/FILE_010.dir/1.1; done`)*
---
## S78 (2026-09-04): the `800c3` "wall" band is **LIBPAD 4.2.1 + LIBAPI 4.2**, and the LINKED residue is now printed by the build
**How it was identified (a free oracle nobody had used).** `ghidra_psx_ldr` ships per-version PsyQ
signature sets — `~/ghidra_12.1_PUBLIC/Ghidra/Extensions/ghidra_psx_ldr/data/psyq/<ver>/<LIB>.LIB.json`,
one masked-byte signature + function labels per OBJECT, for 2.6 → 4.7. Matched against the retail EXE
bytes (cookbook §487), the **4.2** set places these byte-exact:
| object | vram | ins | functions (labels) |
|---|---|---|---|
| LIBAPI `COUNTER.OBJ` | 0x8005CF68 | 92 | SetRCnt · GetRCnt · StartRCnt · StopRCnt · ResetRCnt |
| LIBAPI `C114.OBJ` | 0x8005CE48 | 8 | `_96_remove` — **the 4.2 `Ps` stamp** (SETUP §5.1 "libnum 0") |
| LIBPAD `PADENTRY.OBJ` | 0x8005D0D8 | 300 | PadChkVsync · PadStartCom · PadStopCom · PadChkMtap · PadGetState · PadInfoMode · PadInfoAct · PadInfoComb · PadSetActAlign · PadSetMainMode · PadSetAct |
| LIBPAD `PADMAIN.OBJ` (4.2.1) | 0x8005D588 | ~756 | PadEnableCom · `_padSetVsyncParam` · `_padChkVsync` · `_padStartCom` · `_padStopCom` · `_padInitSioMode` · `_padSioRW` (+ `_padSioRW2`/`_padClrIntSio0`/`_padWaitRXready`, order-inferred: the 4.2 sig drifts +4/+12 here — the EXE holds the 4.2.1 revision) |
| LIBAPI `L02.OBJ`/`L03.OBJ` | 0x8005E168 | 4+4 | SysEnqIntRP · SysDeqIntRP |
| LIBPAD `PADCMD.OBJ` | 0x8005E188 | 600 | `_padSetAct` · `_padSetCmd` · `_padSendAtLoadInfo` · `_padRecvAtLoadInfo` · `_padGetActSize` · `_padLoadActInfo` · `_padSetActAlign` · `_padSetMainMode` · `_padCmdParaMode` |
| LIBPAD `PADIF.OBJ` | 0x8005EAE8 | ~376 | statics only (no public labels): `func_8005EAE8/EB28/EC00/ECC0/ED4C` |
| LIBPAD `PADPORTD.OBJ` | 0x8005F0C8 | 408 | PadInitDirect |
| LIBPAD `PADSEQD.OBJ` | 0x8005F728 | 288 | `_padInitDirSeq` · `_dirFailAuto` |
| LIBPAD `WAITRC2.OBJ` (4.3 sig) | 0x8005FBA8 | 48 | setRC2wait · chkRC2wait |
| LIBAPI `FIRST.OBJ` | 0x80061FA8 | 168 | firstfile (the 4.2 C wrapper; 4.0's `A66.o` trampoline at 0x80062248 is `firstfile2` in 4.2 naming) |
| LIBAPI `PAD.OBJ` | 0x80062388 | 192 | SetInitPadFlag · ReadInitPadFlag · PAD_init · InitPAD · StartPAD · StopPAD |
| LIBAPI `PATCH.OBJ` | 0x800626C8 | 40 | EnablePAD · DisablePAD · `_patch_pad` |
| LIBAPI `CHCLRPAD.OBJ` | 0x80062768 | 28 | `_remove_ChgclrPAD` |
The 4.2.1x `Ps` stamp at `0x80072954` ("libnum 12") stands directly in front of libpad's `.data` — the
callback tables `D_8007295C..D_800729D8` the band's functions index. So **all 12 of main's open stubs
in `800c3`** (incl. the four §332 "%lo-in-a-delay-slot" walls: `_padInitSioMode`, `_padStartCom`,
`func_8005ED4C`, `func_8005F450`) and the 8 SDK-C-REORDER verbatims are **Sony library code assembled
in reorder mode** — §332b's mechanism, with its provenance. Names applied to `config/symbols.us.txt` +
Ghidra (46; `firstfile` after retiring Ghidra's 4.0-sig `firstfile` at 0x80062248 → `firstfile2`).
**Which archives hold it.** Placed with `psyq_identify` after converting each to ELF: PsyQ **4.0**
(`lib40/`, no LIBPAD at all), **4.6** (`lib46/`, S78 fetch), **4.7** (`conv47/`): only
`PDMAIINI.o` (4.6/4.7, 68 ins @0x8005D8B4 = `_padStartCom`+`_padStopCom`) is byte-identical in the
band; 4.6/4.7 libpad otherwise differs (PADMAIN 884 ins in 4.4+, PADCMD 768). The loader's **4.3**
signature set matches PADENTRY/PADCMD/PADPORTD/WAITRC2 but not PADSEQD (292 vs 288). **A 4.2.1 or
4.3 LIBPAD.LIB is the archive that would LINK the whole band** (task #13); until then the band is
matched as C under the `REORDER_TUS` island with the real names.
**The LINKED residue, now a build output.** `psyq_integrate --yaml` (S78) wires only the objects
inside each library's stub subsegs and PRINTS the rest as `~~ N located object(s) / M ins OUTSIDE the
stub subsegs` — the completion contract's "SDK residue empties" line, read straight off `make build`.
At S78 close it reads, for libgte: **13 objects / 1,264 ins** — `MSC01/02/05/09` (800b, 276 ins,
100% of that "game code" subseg), `SMP_00` (800b_2), `SMP_05` (800b_3), `FGO_01–06` (800b_5, 804 ins,
100%), `PATCHGTE` (800b_6, 40 ins, 100%). Plus, outside libgte's window: `SYS.o` (800c, 3,109),
`2D_BG0/1` (800b_7, 1,022), `VM_NO1` (sgap_7, 305), `VM_NOWON` (sgap_8, 300), `VM_F` (sgap_6, 237),
libapi's 800c3 trampolines (176), `FIRST.o` (168). Task #3/#4 wire these.
**Why the build was RED at HEAD (found S78).** The S77 `psyq_identify` fix (§485) started locating
those in-gap objects, and `psyq_integrate.contiguous_blocks()` then merged libgte's 22 stub blocks
into 3 (`3 object blocks but 22 stubs`) — every `make build BINARY=main` with `.run/obj40/libgte`
present died at the link. It passed the S77 gates because the gate worktrees have no `.run/obj40` and
take the stub fallback. Two fixes, both in `psyq_integrate.py`: (1) `--yaml`: stub↔objects by SUBSEG
RANGE with an exact-tiling check, residue printed; (2) a library object's DEFINED symbol whose
recovered address the curated file names differently is `--redefine-sym`'d to the curated name (R15)
— `A66.o` `firstfile`→`firstfile2`, and it also exposed `TOC.o` `CdGetToc`@0x800430B8 mis-curated as
`DecDCToutCallback` (an xdedup-vs-VS mislabel; libcd 4.0's linked object is the stronger oracle).
+22
View File
@@ -32,6 +32,28 @@ Instead of roadmap-v2 P31's per-function grind, Phase 31 organizes the 12,059 re
fixed, six of them mine.** Discovered and mapped the **ASSEMBLY-POSING-AS-C class** (199 bodies,
`config/verbatim_manifest.json` is the authoritative census); retired `asm_in_c.py` for a
manifest + drift guard (R33). See the S75 FINAL 🛑 block at the end of this file.
- S78 (2026-09-04): **completion sprint chartered** (census + confirmed order, see the S78 OPEN block).
**#12 DONE:** the `800c3` band named from the psx loader's 4.2/4.3 signature sets — **46 libpad/libapi
names** (`PadInitDirect`, `_padSetAct`, `PadEnableCom`, `_padInitSioMode`…) + `firstfile`/`firstfile2`
(4.2 naming) + `CdGetToc` (0x800430B8 was mis-curated `DecDCToutCallback`, a Phase-21 xdedup-vs-VS
label; the linked libcd TOC.o is the byte oracle). Applied to `config/symbols.us.txt` (count 1081),
the band's TUs + `src/800_b_2.c` caller, the verbatim manifest, `config/wave_exclude.txt`, and
Ghidra (73 renames incl. the Phase-21 backlog, via the NEW headless `ApplySymbols.java` /
`tools/ghidra_apply_symbols.sh` — R9-verified ×4). Provenance: SETUP §5.1 corrected (libnum 0 =
libapi 4.2 `C114`@0x8005CE48, libnum 12 = libpad 4.2.1x), `docs/psyq-worklist.md` S78, cookbook
**§487**, decision-log + accelerators S78, `tools/psyq/CHECKSUMS.sha256` (+4.6/4.5 archives).
**Two instrument findings on the way:** (1) main's LINKED build was RED at HEAD since the S77
`psyq_identify` fix — in-gap libgte objects merged 22 stub blocks into 3; unseen because gate
worktrees carry no `.run/obj40` (stub fallback). Fixed: `psyq_integrate --yaml` (stub↔objects by
subseg RANGE + exact tiling; the unwired residue is PRINTED: libgte 13 objs / 1,264 ins) and
`--redefine-sym` of a library object's exported name to the curated one (A66 `firstfile`→
`firstfile2`). (2) 47 MCP `batch_rename`/`rename_symbol` writes did NOT persist through the
sentinel stop ("Save succeeded", DB grew, names gone) → renames now go through ApplySymbols.
Also `lint_symbol_refs` now scans verbatim `__asm__` bodies (the `\tfunc_X` miss broke gas).
**R22:** clean `extract-all` 212/212 + `check-all` 212 green on the final config; main rebuilt
byte-identical `143dbb89…` after the last src-only fix (the `DecDCToutCallback` caller) → 213/213.
`tools-health` OK. Ghidra DB deliberately NOT staged (the mirror is text-derived and re-applicable;
`db.*.gbf` churn stays restart-noise).
- [ ] **Tclose — PhaseEnd** (gate 2). (Max)
## Standing verification (every task)
+17 -17
View File
@@ -5700,8 +5700,8 @@ extern u8 D_80078D98;
extern u32 D_800AE610;
extern u8 D_80078DA0;
extern void ResetCallback(void);
extern void func_8005F0C8(void *a0, void *a1);
extern void func_8005D0F8(void);
extern void PadInitDirect(void *a0, void *a1);
extern void PadStartCom(void);
void func_80018918(void) {
u8 *p;
@@ -5720,8 +5720,8 @@ void func_80018918(void) {
} while (i < 2);
func_80018FC8();
ResetCallback();
func_8005F0C8(&D_80078DA0, &D_80078DA0 + 0x4C);
func_8005D0F8();
PadInitDirect(&D_80078DA0, &D_80078DA0 + 0x4C);
PadStartCom();
}
extern s32 func_80018A20(s32 arg0);
@@ -5760,10 +5760,10 @@ extern u8 D_80062BBD;
extern u8 D_800747B8;
extern u8 D_800747B9;
extern s32 func_8005D184(s32);
extern s32 func_8005D244(s32, s32, s32);
extern void func_8005D4B8(s32, void*);
extern void func_8005D538(s32, void*, s32);
extern s32 PadGetState(s32);
extern s32 PadInfoMode(s32, s32, s32);
extern void PadSetActAlign(s32, void*);
extern void PadSetAct(s32, void*, s32);
extern s32 func_80028D58(void);
extern void func_80018F88(void*);
extern void func_80018FC8(void);
@@ -5783,7 +5783,7 @@ s32 func_80018A20(s32 arg0) {
break;
}
switch (func_8005D184(chan)) {
switch (PadGetState(chan)) {
case 0:
if (arg0 == 0) {
if (D_800AE610++ >= 10) {
@@ -5801,7 +5801,7 @@ s32 func_80018A20(s32 arg0) {
return 1;
}
D_800AE610 = 0;
if (func_8005D244(chan, 2, 0) != 0) {
if (PadInfoMode(chan, 2, 0) != 0) {
return 1;
}
if (func_80028D58() == 0) {
@@ -5815,8 +5815,8 @@ s32 func_80018A20(s32 arg0) {
} else {
func_80018FC8();
}
func_8005D538(chan, &D_80062BBC, 2);
func_8005D4B8(chan, &D_80062BAC);
PadSetAct(chan, &D_80062BBC, 2);
PadSetActAlign(chan, &D_80062BAC);
return 1;
case 6:
@@ -5824,7 +5824,7 @@ s32 func_80018A20(s32 arg0) {
return 1;
}
D_800AE610 = 0;
if (func_8005D244(chan, 2, 0) == 0) {
if (PadInfoMode(chan, 2, 0) == 0) {
return 1;
}
if (func_80028D58() == 0) {
@@ -5835,8 +5835,8 @@ s32 func_80018A20(s32 arg0) {
} else {
func_80018FC8();
}
func_8005D538(chan, &D_800747B8, 2);
func_8005D4B8(chan, &D_80062BB4);
PadSetAct(chan, &D_800747B8, 2);
PadSetActAlign(chan, &D_80062BB4);
return 1;
}
}
@@ -8852,7 +8852,7 @@ extern void DrawSyncCallback(s32);
extern void func_80059234(s32);
extern void func_80059658(s32);
extern int VSync(int mode);
extern void func_8005D118(void);
extern void PadStopCom(void);
extern void StopRCnt(void);
extern void func_80043300(void);
extern void ResetCallback(void);
@@ -8867,7 +8867,7 @@ void func_8001BDA0(void) {
VSync(0);
func_800596F4(0);
func_80059234(3);
func_8005D118();
PadStopCom();
StopRCnt();
func_80043300();
ResetCallback();
+2 -2
View File
@@ -6648,7 +6648,7 @@ extern s32 D_80076114;
extern u8 D_80076214;
extern s32 D_80078F10;
extern void D_800C7D30();
extern int DecDCToutCallback(void (*func)());
extern int CdGetToc(void (*func)());
extern s32 D_800A5BC8;
extern s32 D_800C6D28;
@@ -6676,7 +6676,7 @@ void func_80034C24(void) {
p[i] = 0;
}
D_800A5BC8 = DecDCToutCallback(D_800C7D30);
D_800A5BC8 = CdGetToc(D_800C7D30);
D_800C6D28 = 0;
}
+1 -1
View File
@@ -15,7 +15,7 @@ extern s32 func_8005C4DC();
extern s32 firstfile2();
extern void func_80062144();
s32 func_80061FA8(char *name, s32 mode)
s32 firstfile(char *name, s32 mode)
{
u8 *src;
u8 *dst;
+21 -21
View File
@@ -3,9 +3,9 @@
__asm__(
".text\n"
".align 2\n"
".globl func_80062388\n"
".ent\tfunc_80062388\n"
"func_80062388:\n"
".globl SetInitPadFlag\n"
".ent\tSetInitPadFlag\n"
"SetInitPadFlag:\n"
".frame $sp,0,$31\n"
".mask 0x00000000,0\n"
".fmask 0x00000000,0\n"
@@ -14,30 +14,30 @@ __asm__(
"jr $ra\n"
"sw $a0, %lo(D_80072A24)($at)\n"
".set\treorder\n"
".end\tfunc_80062388\n"
".end\tSetInitPadFlag\n"
);
extern s32 D_80072A24;
s32 func_80062394(void)
s32 ReadInitPadFlag(void)
{
return D_80072A24;
}
extern void func_80062768(void);
extern void _remove_ChgclrPAD(void);
extern void func_8005CF08(void);
extern void func_800626F0(void);
extern void _patch_pad(void);
extern void func_8005CF18(void);
extern s32 ChangeClearPAD(s32 mode);
extern s32 func_8006252C(void);
extern s32 PAD_init2(s32, s32, s32, s32);
extern s32 D_80072A24;
void func_800623A4(s32 a0, s32 a1, s32 a2, s32 a3)
void PAD_init(s32 a0, s32 a1, s32 a2, s32 a3)
{
func_80062768();
_remove_ChgclrPAD();
func_8005CF08();
func_800626F0();
_patch_pad();
func_8005CF18();
ChangeClearPAD(0);
((s32 (*)())func_8006252C)();
@@ -47,20 +47,20 @@ void func_800623A4(s32 a0, s32 a1, s32 a2, s32 a3)
extern void func_80062768(void);
extern void _remove_ChgclrPAD(void);
extern void func_8005CF08(void);
extern void func_800626F0(void);
extern void _patch_pad(void);
extern void func_8005CF18(void);
extern s32 ChangeClearPAD(s32 mode);
extern s32 func_8006252C(void);
extern void InitPAD2(s32 a0, s32 a1, s32 a2, s32 a3);
extern s32 D_80072A24;
void func_80062434(s32 a0, s32 a1, s32 a2, s32 a3)
void InitPAD(s32 a0, s32 a1, s32 a2, s32 a3)
{
func_80062768();
_remove_ChgclrPAD();
func_8005CF08();
func_800626F0();
_patch_pad();
func_8005CF18();
ChangeClearPAD(0);
((s32 (*)())func_8006252C)();
@@ -70,24 +70,24 @@ void func_80062434(s32 a0, s32 a1, s32 a2, s32 a3)
extern void StartPAD2(void);
extern s32 ChangeClearPAD(s32 mode);
extern void func_800626C8(void);
extern void EnablePAD(void);
s32 func_800624C4(void)
s32 StartPAD(void)
{
StartPAD2();
ChangeClearPAD(0);
func_800626C8();
EnablePAD();
return 1;
}
extern void func_800626DC(void);
extern void DisablePAD(void);
extern void StopPAD2(void);
extern s32 func_800625A4(void);
extern s32 D_80072A24;
void func_800624F4(void)
void StopPAD(void)
{
func_800626DC();
DisablePAD();
StopPAD2();
func_800625A4();
D_80072A24 = 0;
+17 -17
View File
@@ -3,9 +3,9 @@
__asm__(
".text\n"
".align 2\n"
".globl func_800626C8\n"
".ent\tfunc_800626C8\n"
"func_800626C8:\n"
".globl EnablePAD\n"
".ent\tEnablePAD\n"
"EnablePAD:\n"
".frame $sp, 0, $31\n"
".mask 0x00000000, 0\n"
".fmask 0x00000000, 0\n"
@@ -16,15 +16,15 @@ __asm__(
"jr $t1\n"
"nop\n"
".set\treorder\n"
".end\tfunc_800626C8\n"
".end\tEnablePAD\n"
);
__asm__(
".text\n"
".align 2\n"
".globl func_800626DC\n"
".ent\tfunc_800626DC\n"
"func_800626DC:\n"
".globl DisablePAD\n"
".ent\tDisablePAD\n"
"DisablePAD:\n"
".frame $sp, 0, $31\n"
".mask 0x00000000, 0\n"
".fmask 0x00000000, 0\n"
@@ -35,15 +35,15 @@ __asm__(
"jr $t1\n"
"nop\n"
".set\treorder\n"
".end\tfunc_800626DC\n"
".end\tDisablePAD\n"
);
__asm__(
".text\n"
".align 2\n"
".globl func_800626F0\n"
".ent\tfunc_800626F0\n"
"func_800626F0:\n"
".globl _patch_pad\n"
".ent\t_patch_pad\n"
"_patch_pad:\n"
".frame $sp, 0, $31\n"
".mask 0x00000000, 0\n"
".fmask 0x00000000, 0\n"
@@ -78,7 +78,7 @@ __asm__(
"jr $ra\n"
"nop\n"
".set\treorder\n"
".end\tfunc_800626F0\n"
".end\t_patch_pad\n"
"nop\n"
"nop\n"
);
@@ -90,15 +90,15 @@ __asm__(
* FlushCache(); func_8005CF18(); return via saved $ra.
* NOTE: maspsx did NOT auto-insert load-delay nops here (after
* "lw $v0,364($v0)" and "lw $ra,%lo(D_80078D28)($ra)") — both written by
* hand, matching the banked sibling func_800626F0 in this same TU; this
* hand, matching the banked sibling _patch_pad in this same TU; this
* contradicts §179-B rule 4 as observed on this build.
*/
__asm__(
".text\n"
".align 2\n"
".globl func_80062768\n"
".ent\tfunc_80062768\n"
"func_80062768:\n"
".globl _remove_ChgclrPAD\n"
".ent\t_remove_ChgclrPAD\n"
"_remove_ChgclrPAD:\n"
".frame $sp, 0, $31\n"
".mask 0x00000000, 0\n"
".fmask 0x00000000, 0\n"
@@ -131,7 +131,7 @@ __asm__(
"jr $ra\n"
"nop\n"
".set\treorder\n"
".end\tfunc_80062768\n"
".end\t_remove_ChgclrPAD\n"
"nop\n"
"nop\n"
);
+89 -89
View File
@@ -346,28 +346,28 @@ s32 ResetRCnt(s32 spec) {
__asm__(".word 0x00000000");
extern s32 func_8005D8A0(void);
extern s32 _padChkVsync(void);
void func_8005D0D8(void) {
func_8005D8A0();
void PadChkVsync(void) {
_padChkVsync();
}
extern void func_8005D8B4(void);
extern void _padStartCom(void);
void func_8005D0F8(void) {
func_8005D8B4();
void PadStartCom(void) {
_padStartCom();
}
extern void func_8005D980(void);
extern void _padStopCom(void);
void func_8005D118(void) {
func_8005D980();
void PadStopCom(void) {
_padStopCom();
}
extern s32 D_800729A8;
extern s32 D_80072990;
s32 func_8005D138(s32 arg0) {
s32 PadChkMtap(s32 arg0) {
if (D_800729A8 != 0) {
return *(u8 *)(D_80072990 + (arg0 >> 4) * 0xF0 + 0xE8) == 8;
}
@@ -377,7 +377,7 @@ s32 func_8005D138(s32 arg0) {
extern void* (*D_80072970)(void);
s32 func_8005D184(s32 arg0) {
s32 PadGetState(s32 arg0) {
void* v0;
register s32 v1 __asm__("$3");
@@ -426,7 +426,7 @@ return_byte:
extern void* (*D_80072970)(void);
s32 func_8005D244(s32 arg0, s32 arg1, s32 arg2) {
s32 PadInfoMode(s32 arg0, s32 arg1, s32 arg2) {
void *p;
p = (*D_80072970)();
@@ -453,7 +453,7 @@ s32 func_8005D244(s32 arg0, s32 arg1, s32 arg2) {
}
INCLUDE_ASM("asm/nonmatchings/800c3", func_8005D33C);
INCLUDE_ASM("asm/nonmatchings/800c3", PadInfoAct);
extern void* (*D_80072970)(void);
@@ -461,7 +461,7 @@ extern void* (*D_80072970)(void);
extern void* (*D_80072970)(void);
s32 func_8005D410(s32 arg0, s32 arg1, s32 arg2) {
s32 PadInfoComb(s32 arg0, s32 arg1, s32 arg2) {
u8 *p;
p = (u8 *)(*D_80072970)();
@@ -482,22 +482,22 @@ s32 func_8005D410(s32 arg0, s32 arg1, s32 arg2) {
}
extern void* (*D_80072970)(void);
extern s32 func_8005E79C(void *a0, void *a1);
extern s32 _padSetActAlign(void *a0, void *a1);
void func_8005D4B8(void *a0, void *a1) {
((s32 (*)())func_8005E79C)(D_80072970(), a1);
void PadSetActAlign(void *a0, void *a1) {
((s32 (*)())_padSetActAlign)(D_80072970(), a1);
}
extern void* (*D_80072970)(void);
void func_8005D4F0(s32 arg0, s32 arg1, s32 arg2) {
func_8005E8E8(D_80072970(), (u8)arg1, (u8)arg2);
void PadSetMainMode(s32 arg0, s32 arg1, s32 arg2) {
_padSetMainMode(D_80072970(), (u8)arg1, (u8)arg2);
}
extern void* (*D_80072970)(void);
void func_8005D538(s32 arg0, void *arg1, s32 arg2) {
func_8005E188(D_80072970(), arg1, arg2);
void PadSetAct(s32 arg0, void *arg1, s32 arg2) {
_padSetAct(D_80072970(), arg1, arg2);
}
__asm__("nop\nnop\n");
@@ -505,7 +505,7 @@ __asm__("nop\nnop\n");
u32 func_8005D588(u32 arg0) {
u32 PadEnableCom(u32 arg0) {
extern void (*D_80072960)(void *);
extern u32 D_80072994;
@@ -546,7 +546,7 @@ u32 func_8005D588(u32 arg0) {
return ret;
}
void func_8005D6A0(void) {
void _padSetVsyncParam(void) {
extern s32 D_8007898C;
extern void func_8005D734(void);
extern void func_8005D6CC(void);
@@ -588,7 +588,7 @@ extern s32 D_800729C4;
asm(
".section .text\n"
".set noreorder\n"
"func_8005D8A0:\n"
"_padChkVsync:\n"
"lui $v0, %hi(D_800729C4)\n"
"lw $v0, %lo(D_800729C4)($v0)\n"
"lui $at, %hi(D_800729C4)\n"
@@ -596,11 +596,11 @@ asm(
"sw $zero, %lo(D_800729C4)($at)\n"
".set reorder\n");
s32 func_8005D8A0(void);
s32 _padChkVsync(void);
INCLUDE_ASM("asm/nonmatchings/800c3", func_8005D8B4);
INCLUDE_ASM("asm/nonmatchings/800c3", _padStartCom);
extern void func_8005CF08(void);
extern void func_8005CF18(void);
@@ -608,7 +608,7 @@ extern s32 ChangeClearRCnt(s32 intr, s32 mode);
extern s32 SysDeqIntRP(s32 priority, void *intr);
extern unsigned char D_80078988[];
void func_8005D980(void)
void _padStopCom(void)
{
func_8005CF08();
ChangeClearRCnt(3, 1);
@@ -616,14 +616,14 @@ void func_8005D980(void)
func_8005CF18();
}
INCLUDE_ASM("asm/nonmatchings/800c3", func_8005D9C4);
INCLUDE_ASM("asm/nonmatchings/800c3", _padInitSioMode);
extern s32 D_800729A0;
extern s32 (*D_800729E0[])();
extern s32 (*D_8007295C)();
s32 func_8005E0AC(void);
void func_8005FBA8(s32 a0);
s32 _padClrIntSio0(void);
void setRC2wait(s32 a0);
void func_8005DBD8(void) {
s32 (*fp)();
@@ -638,8 +638,8 @@ void func_8005DBD8(void) {
ret = fp();
if (ret >= 0) {
if (D_800729A0 != 0) {
func_8005FBA8(0x3C);
if (func_8005E0AC() == 0) {
setRC2wait(0x3C);
if (_padClrIntSio0() == 0) {
(*D_8007295C)(-3);
}
}
@@ -657,9 +657,9 @@ extern s32 *D_800729C0;
extern volatile s32 D_80078F24;
extern volatile s32 D_800C5320;
s32 func_8005FBC8(void);
s32 chkRC2wait(void);
s32 func_8005DCA0(s32 ctx, s32 cmd) {
s32 _padSioRW(s32 ctx, s32 cmd) {
u8 tmp;
s32 first;
u16 t;
@@ -677,7 +677,7 @@ s32 func_8005DCA0(s32 ctx, s32 cmd) {
if ((*(volatile u16 *)((s8 *)D_800729C0 + 0x4) & 1) == 0) {
do {} while ((*(volatile u16 *)((s8 *)D_800729C0 + 0x4) & 1) == 0);
}
while (func_8005FBC8() == 0) {}
while (chkRC2wait() == 0) {}
{
register u8 nv __asm__("$2");
nv = ~cmd;
@@ -706,7 +706,7 @@ s32 func_8005DCA0(s32 ctx, s32 cmd) {
first = tmp;
if ((*ptr & 0x80) == 0) {
do {
if (func_8005FBC8() != 0) {
if (chkRC2wait() != 0) {
goto err;
}
} while ((*D_800729BC & 0x80) == 0);
@@ -727,13 +727,13 @@ err:
}
/* func_8005DE78 — libcd command issue with a root-counter-1 timeout spin.
* Structure is func_8005DCA0's (same TU) with func_8005FBC8's body INLINED as the
/* _padSioRW2 — libcd command issue with a root-counter-1 timeout spin.
* Structure is _padSioRW's (same TU) with chkRC2wait's body INLINED as the
* loop test; the four levers that closed it:
* 1. `u8 tmp; s32 first; tmp = *(volatile u8 *)p; first = tmp;` — the volatile QI
* load blocks combine from folding the u8->s32 promotion into the lbu, so the
* zero-extend survives as its own `andi $s2,$v0,0xFF` (same idiom that produces
* `andi $v1,$v0,0xFFFF` after the 0x1F801120 lhu in banked func_8005FBC8).
* `andi $v1,$v0,0xFFFF` after the 0x1F801120 lhu in banked chkRC2wait).
* 2. `if (A || B) {store t} else {store 0x22}` — do_jump's TRUTH_ORIF drop-through
* label puts the `t` arm as the fall-through; the `&&` spelling swaps the arms.
* 3. The 0xE store is VOLATILE: reorg's resource_conflicts_p returns 1 whenever
@@ -753,10 +753,10 @@ extern volatile s32 D_80078F24;
extern volatile s32 D_800C5320;
extern s32 D_800729A0;
void func_8005FBA8(s32 a0);
s32 func_8005FBC8(void);
void setRC2wait(s32 a0);
s32 chkRC2wait(void);
s32 func_8005DE78(s32 ctx, s32 cmd) {
s32 _padSioRW2(s32 ctx, s32 cmd) {
u8 tmp;
s32 first;
u16 t;
@@ -773,7 +773,7 @@ s32 func_8005DE78(s32 ctx, s32 cmd) {
t = 0x22;
}
do {} while ((*(volatile u16 *)((s8 *)D_800729C0 + 0x4) & 2) == 0);
func_8005FBA8(0x190);
setRC2wait(0x190);
tmp = *(volatile u8 *)D_800729C0;
first = tmp;
if (*(u8 *)(ctx + 0x44) != 0 || (first >> 4) != 8) {
@@ -806,8 +806,8 @@ s32 func_8005DE78(s32 ctx, s32 cmd) {
} while ((*D_800729BC & 0x80) == 0);
}
if (*(u8 *)(ctx + 0xE8) != 8 && D_800729A0 == 2) {
func_8005FBA8(0x3C);
while (func_8005FBC8() == 0) {}
setRC2wait(0x3C);
while (chkRC2wait() == 0) {}
}
*(u8 *)D_800729C0 = cmd;
*(u8 *)(ctx + 0x45) += 1;
@@ -823,9 +823,9 @@ s32 func_8005DE78(s32 ctx, s32 cmd) {
extern s32 *D_800729BC;
extern s32 *D_800729C0;
s32 func_8005FBC8(void);
s32 chkRC2wait(void);
s32 func_8005E0AC(void) {
s32 _padClrIntSio0(void) {
s32 *ptr1 = D_800729BC;
s32 *ptr2;
u16 v1_val;
@@ -835,7 +835,7 @@ s32 func_8005E0AC(void) {
*ptr1 = -0x81;
if ((*(u16 *)((s8 *)pre_ptr2 + 0x4) & 0x80) != 0) {
do {
if (func_8005FBC8() != 0) {
if (chkRC2wait() != 0) {
return 0;
}
} while ((*(u16 *)((s8 *)D_800729C0 + 0x4) & 0x80) != 0);
@@ -854,7 +854,7 @@ extern s32 *D_800729C0;
extern s32 *D_800729C0;
void func_8005E13C(void) {
void _padWaitRXready(void) {
s32 *ptr;
ptr = D_800729C0;
@@ -863,7 +863,7 @@ void func_8005E13C(void) {
;
}
/* The word at 0x8005E164 is an orphan inter-function pad: func_8005E13C's own
/* The word at 0x8005E164 is an orphan inter-function pad: _padWaitRXready's own
* .size is 0x28 (ends 0x8005E164) but SysEnqIntRP (config/symbols.us.txt) is
* fixed at 0x8005E168 — a 4-byte gap belonging to neither function. It is
* currently supplied by the INCLUDE_ASM stub's own verbatim .s inclusion;
@@ -897,12 +897,12 @@ __asm__(
"nop\n"
);
void func_8005E188(s32 arg0, s32 arg1, s8 arg2) {
void _padSetAct(s32 arg0, s32 arg1, s8 arg2) {
*(s32*)(arg0 + 0x28) = arg1;
*(u8*)(arg0 + 0x34) = arg2;
}
void func_8005E194(void *arg0, u8 arg1, u32 arg2, u8 arg3) {
void _padSetCmd(void *arg0, u8 arg1, u32 arg2, u8 arg3) {
*(u8 *)((u8 *)arg0 + 0x36) = arg1;
*(u32 *)((u8 *)arg0 + 0x2C) = arg2;
*(u8 *)((u8 *)arg0 + 0x35) = arg3;
@@ -912,7 +912,7 @@ extern void func_8005EA54();
extern void func_8005EA68(void *arg0, s32 arg1);
extern void func_8005EAA8(void *arg0, s32 arg1);
void func_8005E1A4(void *arg0) {
void _padSendAtLoadInfo(void *arg0) {
switch (*(u8 *)((u8 *)arg0 + 0x46)) {
case 2:
func_8005EA54(arg0);
@@ -949,10 +949,10 @@ typedef struct {
/* 0xEC */ u32 wEC;
} Ctx_8005E228;
s32 func_8005E374();
s32 func_8005E3AC();
s32 _padGetActSize();
s32 _padLoadActInfo();
s32 func_8005E228(Ctx_8005E228 *s) {
s32 _padRecvAtLoadInfo(Ctx_8005E228 *s) {
u8 t;
switch (s->b46) {
case 2:
@@ -973,12 +973,12 @@ s32 func_8005E228(Ctx_8005E228 *s) {
if (t < s->bEA) {
return 0;
}
if (func_8005E374(s) >= 0x81) {
if (_padGetActSize(s) >= 0x81) {
s->b46 = 0xFE;
s->b49 = 2;
} else {
s->b46 = 0xFF;
((s32 (*)())func_8005E3AC)(s, (u8 *)s + 0x63);
((s32 (*)())_padLoadActInfo)(s, (u8 *)s + 0x63);
s->b46 = 2;
}
return 0;
@@ -987,7 +987,7 @@ s32 func_8005E228(Ctx_8005E228 *s) {
}
s32 func_8005E374(u8 *a0) {
s32 _padGetActSize(u8 *a0) {
s32 t = ((a0[0xE3] + 1) / 2) * 4;
s32 m = (((a0[0xE9] * 5) + 3) & 0xFFC) + 4;
return t + m + *(u32 *)(a0 + 0xEC);
@@ -999,7 +999,7 @@ extern s32 (*D_80072978)(void);
extern void func_8005E480(void *arg0);
extern s32 func_8005E528(Ctx *s);
s32 func_8005E3AC(Ctx *s, s32 size) {
s32 _padLoadActInfo(Ctx *s, s32 size) {
register s32 ret __asm__("$2");
register s32 t __asm__("$5");
s32 tmp;
@@ -1142,7 +1142,7 @@ s32 func_8005E528(Ctx *s) {
extern void func_8005E804(u8 *arg0);
extern s32 func_8005E820(void *a0);
s32 func_8005E79C(void *a0, void *a1) {
s32 _padSetActAlign(void *a0, void *a1) {
extern s32 (*D_80072978)(void);
s32 v0 = ((s32 (*)(void *, void *))D_80072978)(a0, a1);
if (v0 != 0)
@@ -1218,7 +1218,7 @@ s32 func_8005E820(void *a0)
return 0;
}
INCLUDE_ASM("asm/nonmatchings/800c3", func_8005E8E8);
INCLUDE_ASM("asm/nonmatchings/800c3", _padSetMainMode);
void func_8005E980(void)
{
@@ -1253,9 +1253,9 @@ s32 func_8005E9D4(s32 a0)
return 0;
}
extern void func_8005EA34(void *arg0, s32 arg1);
extern void _padCmdParaMode(void *arg0, s32 arg1);
void func_8005EA34(void *arg0, s32 arg1) {
void _padCmdParaMode(void *arg0, s32 arg1) {
*(u8 *)((u8 *)arg0 + 0x36) = 0x43;
*(s32 *)((u8 *)arg0 + 0x2C) = (s32)((u8 *)arg0 + 0x24);
*(u8 *)((u8 *)arg0 + 0x24) = arg1;
@@ -1301,11 +1301,11 @@ __asm__(".text\n\tnop\n\tnop\n\tnop\n");
extern void (*D_80072974)(void *);
extern u32 D_800729DC;
s32 func_8005DCA0(s32 ctx, s32 cmd);
s32 _padSioRW(s32 ctx, s32 cmd);
void func_8005EAE8(void *arg0) {
D_800729DC = ((s32 (*)(void *))D_80072974)(arg0);
func_8005DCA0((s32)arg0, -2);
_padSioRW((s32)arg0, -2);
}
/*
@@ -1356,9 +1356,9 @@ void func_8005EB28(void *param_1) {
D_80072974((void *)(*(s32 *)((u8 *)param_1 + 0xC) + 0xF0));
}
if (*(volatile u8 *)((u8 *)param_1 + 0x36) == 0) {
func_8005DE78((s32)param_1, 0x42);
_padSioRW2((s32)param_1, 0x42);
} else {
func_8005DE78((s32)param_1, *(u8 *)((u8 *)param_1 + 0x36));
_padSioRW2((s32)param_1, *(u8 *)((u8 *)param_1 + 0x36));
}
}
@@ -1385,7 +1385,7 @@ void func_8005EB28(void *param_1) {
* if (*(u8 *)((char *)arg0 + 0x36) == 0) {
* a1 = D_800729A8;
* }
* v1 = func_8005DE78(arg0, a1);
* v1 = _padSioRW2(arg0, a1);
* if (v1 < 0) {
* return v1;
* }
@@ -1424,7 +1424,7 @@ void func_8005EB28(void *param_1) {
* if (*(u8 *)((char *)arg0 + 0x36) == 0) {
* a1 = D_800729A8;
* }
* v1 = func_8005DE78(arg0, a1);
* v1 = _padSioRW2(arg0, a1);
* if (v1 < 0) {
* return v1;
* }
@@ -1461,7 +1461,7 @@ s32 func_8005EC00(void *arg0) {
a1 = D_800729A8;
}
v1 = func_8005DE78((s32)arg0, a1);
v1 = _padSioRW2((s32)arg0, a1);
if (v1 < 0) {
return v1;
}
@@ -1493,7 +1493,7 @@ INCLUDE_ASM("asm/nonmatchings/800c3", func_8005ECC0);
*/
INCLUDE_ASM("asm/nonmatchings/800c3", func_8005ED4C);
INCLUDE_ASM("asm/nonmatchings/800c3", func_8005F0C8);
INCLUDE_ASM("asm/nonmatchings/800c3", PadInitDirect);
void func_8005F228(void *arg0) {
u8 *p;
@@ -1619,9 +1619,9 @@ __asm__(".word 0x00000000\n");
__asm__(
".text\n"
".align\t2\n"
".globl\tfunc_8005F728\n"
".ent\tfunc_8005F728\n"
"func_8005F728:\n"
".globl\t_padInitDirSeq\n"
".ent\t_padInitDirSeq\n"
"_padInitDirSeq:\n"
".set\tnoreorder\n"
"lui $v0, %hi(func_8005F75C)\n"
"addiu $v0, $v0, %lo(func_8005F75C)\n"
@@ -1637,12 +1637,12 @@ __asm__(
"jr $ra\n"
"sw $v0, %lo(D_8007297C)($at)\n"
".set\treorder\n"
".end\tfunc_8005F728\n"
".end\t_padInitDirSeq\n"
);
extern void func_8005EA34(void *arg0, s32 arg1);
extern void func_8005E1A4(void *arg0);
extern void _padCmdParaMode(void *arg0, s32 arg1);
extern void _padSendAtLoadInfo(void *arg0);
s32 func_8005F75C(void *arg0) {
void *v0;
@@ -1676,11 +1676,11 @@ s32 func_8005F75C(void *arg0) {
goto L8005F7F8;
L8005F7D8:
func_8005EA34(arg0, 1);
_padCmdParaMode(arg0, 1);
goto L8005F820;
L8005F7E8:
func_8005EA34(arg0, 0);
_padCmdParaMode(arg0, 0);
goto L8005F820;
L8005F7F8:
@@ -1691,7 +1691,7 @@ L8005F7F8:
goto L8005F820;
}
}
func_8005E1A4(arg0);
_padSendAtLoadInfo(arg0);
L8005F820:
return 0;
@@ -1699,12 +1699,12 @@ L8005F820:
INCLUDE_ASM("asm/nonmatchings/800c3", func_8005F830);
/* func_8005FA94 — cookbook §265 VERBATIM-ASM bank (file-scope form), generated by
* tools/asm_verbatim.py from asm/nonmatchings/800c3/func_8005FA94.s.
/* _dirFailAuto — cookbook §265 VERBATIM-ASM bank (file-scope form), generated by
* tools/asm_verbatim.py from asm/nonmatchings/800c3/_dirFailAuto.s.
* Byte-equivalent to the INCLUDE_ASM stub by construction; the function is NOT
* decompiled (§265 ACCOUNTING). Immediates/offsets are decimal for maspsx (§383).
*/
INCLUDE_ASM("asm/nonmatchings/800c3", func_8005FA94);
INCLUDE_ASM("asm/nonmatchings/800c3", _dirFailAuto);
s32 func_8005FB70(void *arg0) {
register s32 ff __asm__("$2");
@@ -1725,9 +1725,9 @@ __asm__(".nop\n.nop\n.nop");
__asm__(
".text\n"
".align\t2\n"
".globl\tfunc_8005FBA8\n"
".ent\tfunc_8005FBA8\n"
"func_8005FBA8:\n"
".globl\tsetRC2wait\n"
".ent\tsetRC2wait\n"
"setRC2wait:\n"
".set\tnoreorder\n"
"lui $v0, 0x1F80\n"
"ori $v0, $v0, 0x1120\n"
@@ -1738,14 +1738,14 @@ __asm__(
"jr $ra\n"
"sw $v0, %lo(D_80078F24)($at)\n"
".set\treorder\n"
".end\tfunc_8005FBA8\n"
".end\tsetRC2wait\n"
);
extern volatile s32 D_80078F24;
extern volatile s32 D_800C5320;
s32 func_8005FBC8(void) {
s32 chkRC2wait(void) {
u16 val1;
s32 a0;
u16 status;
+1 -1
View File
@@ -2,7 +2,7 @@
INCLUDE_ASM("asm/nonmatchings/libcd1", StSetRing);
INCLUDE_ASM("asm/nonmatchings/libcd1", DecDCToutCallback);
INCLUDE_ASM("asm/nonmatchings/libcd1", CdGetToc);
INCLUDE_ASM("asm/nonmatchings/libcd1", func_800430DC);
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env bash
# tools/ghidra_apply_symbols.sh — mirror config/symbols.us.txt (or given files) into the Ghidra program,
# headless, with a real save (R15/G6). Precondition: the MCP server is STOPPED (tools/ghidra_mcp_stop.sh);
# the write open needs the project lock. Verify afterwards with tools/ghidra_mcp_verify.sh <addr> <name> (R9).
# tools/ghidra_apply_symbols.sh [PROG] [symbols files...] (defaults: SLUS_007.26 config/symbols.us.txt)
set -uo pipefail
GHIDRA="${GHIDRA_INSTALL_DIR:-$HOME/ghidra_12.1_PUBLIC}"
PROJ_DIR="$HOME/bfm-decomp/ghidra"; PROJ="bfm"
PROG="${1:-SLUS_007.26}"; shift || true
SYMS=("$@"); [ ${#SYMS[@]} -eq 0 ] && SYMS=("$HOME/bfm-decomp/config/symbols.us.txt")
SCRIPTS="$HOME/bfm-decomp/tools/ghidra_scripts"
if ss -tln 2>/dev/null | grep -qE ":8080([^0-9]|$)"; then
echo "apply-symbols: ERROR — MCP server serving on :8080. Run tools/ghidra_mcp_stop.sh first."; exit 2
fi
cd "$HOME/bfm-decomp"
out=$(timeout 600 "$GHIDRA/support/analyzeHeadless" "$PROJ_DIR" "$PROJ" \
-process "$PROG" -noanalysis -scriptPath "$SCRIPTS" -postScript ApplySymbols.java "${SYMS[@]}" 2>&1)
rc=$?
echo "$out" | grep -E "BFMAPPLY|moved holder|fail @|Save succeeded|ERROR|Exception" | head -40
echo "apply-symbols: analyzeHeadless exit=$rc"
+83
View File
@@ -0,0 +1,83 @@
// ApplySymbols.java — MIRROR the curated symbol file INTO Ghidra (rule R15 / G6), headless.
//
// WHY (P31 S78): 47 renames made through the headless MCP server (batch_rename / rename_symbol)
// did NOT survive the sentinel stop — "Save succeeded", the DB grew, the names were gone (R9 caught
// it). The curated text file `config/symbols.us.txt` is the source of truth anyway (R15), so the
// mirror is now a deterministic headless postScript: read `name = 0xADDR; // func|data`, and for every
// address inside program memory set the function's name (or create/primary a label) to the curated
// name. analyzeHeadless commits + saves on exit (the DefineFunctions.java precedent). Idempotent.
//
// Name collisions: a curated name currently held by ANOTHER address is moved first — to that
// address's own curated name when it has one (firstfile/firstfile2 4.0-vs-4.2), else to
// `<name>__at_<addr>` so nothing is silently dropped. Prints BFMAPPLY counts; verify with
// tools/ghidra_mcp_verify.sh <addr> <name> (R9).
//
// Args: <symbols file> [<symbols file> ...] (paths relative to the CWD analyzeHeadless ran from)
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.exception.DuplicateNameException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.*;
public class ApplySymbols extends GhidraScript {
private final Map<Long, String> want = new TreeMap<>();
private int renamedFn = 0, labels = 0, unchanged = 0, skipped = 0, failed = 0, moved = 0;
@Override
protected void run() throws Exception {
String[] args = getScriptArgs();
if (args == null || args.length < 1) { println("BFMAPPLY ERROR: no symbols file given"); return; }
Pattern p = Pattern.compile("^\\s*([A-Za-z_]\\w*)\\s*=\\s*0x([0-9A-Fa-f]+)\\s*;");
for (String path : args) {
for (String ln : Files.readAllLines(Paths.get(path))) {
Matcher m = p.matcher(ln);
if (m.find()) want.put(Long.parseLong(m.group(2), 16), m.group(1));
}
}
for (Map.Entry<Long, String> e : want.entrySet()) apply(e.getKey(), e.getValue(), 0);
println("BFMAPPLY renamed_funcs=" + renamedFn + " labels=" + labels + " unchanged=" + unchanged
+ " moved_holders=" + moved + " skipped_outside_memory=" + skipped + " failed=" + failed
+ " wanted=" + want.size());
}
private Address addrOf(long off) {
return currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(off);
}
private void apply(long off, String name, int depth) {
Address a = addrOf(off);
if (!currentProgram.getMemory().contains(a)) { skipped++; return; }
SymbolTable st = currentProgram.getSymbolTable();
Function f = currentProgram.getFunctionManager().getFunctionAt(a);
Symbol cur = f != null ? f.getSymbol() : st.getPrimarySymbol(a);
if (cur != null && name.equals(cur.getName())) { unchanged++; return; }
try {
if (f != null) { f.setName(name, SourceType.USER_DEFINED); renamedFn++; }
else { st.createLabel(a, name, SourceType.USER_DEFINED).setPrimary(); labels++; }
} catch (DuplicateNameException dup) {
if (depth > 3) { failed++; println(" fail @0x" + Long.toHexString(off) + " " + name + ": " + dup.getMessage()); return; }
// the name is held elsewhere: move the holder out of the way, then retry
for (Symbol h : st.getSymbols(name)) {
long hoff = h.getAddress().getOffset();
if (hoff == off) continue;
String hwant = want.get(hoff);
String to = (hwant != null && !hwant.equals(name)) ? hwant : name + "__at_" + Long.toHexString(hoff);
try {
Function hf = currentProgram.getFunctionManager().getFunctionAt(h.getAddress());
if (hf != null) hf.setName(to, SourceType.USER_DEFINED); else h.setName(to, SourceType.USER_DEFINED);
moved++;
println(" moved holder of '" + name + "' @0x" + Long.toHexString(hoff) + " -> " + to);
} catch (Exception ex) { failed++; println(" fail moving holder @0x" + Long.toHexString(hoff) + ": " + ex.getMessage()); return; }
}
apply(off, name, depth + 1);
} catch (Exception ex) {
failed++; println(" fail @0x" + Long.toHexString(off) + " " + name + ": " + ex.getMessage());
}
}
}
+18
View File
@@ -99,6 +99,24 @@ def main():
continue
if a in curated: # renamed to a curated name, no auto-name symbol -> DANGLING
stale.append((rel, i, m.group(0), curated[a]))
# Blind spot #4 (P31 S78): the §265 verbatim `__asm__("...")` bodies. `strip_comments_strings` blanks
# every string literal, so a renamed `func_<ADDR>` that survives INSIDE an asm body (`.ent\tfunc_X`,
# `.end\tfunc_X`, `.globl func_X`, `jal\tfunc_X`, `func_X:`) is invisible above — and gas then dies
# with `.size expression for func_X does not evaluate to a constant`. Scan the string bodies too,
# and do NOT rely on `\b`: the literal escape `\t` ends in the word char `t`, so `\tfunc_X` has no
# word boundary before the token (the exact miss that produced the first S78 red build).
for cf in files:
rel = os.path.relpath(cf, REPO)
raw = open(cf, errors="replace").read()
for sm in re.finditer(r'__asm__\s*\(((?:\s*"(?:[^"\\]|\\.)*")+)\s*\)', raw):
body = sm.group(1)
line0 = raw.count("\n", 0, sm.start()) + 1
for m in re.finditer(r'(?<![0-9A-Za-z_])(?:func_|D_)([0-9A-Fa-f]{6,8})(?![0-9A-Za-z_])', body):
a = "0x" + m.group(1).lower()
if a in autosym or a in asm_labeled: # blind spot #3 applies here too (memcpy binding)
continue
if a in curated:
stale.append((rel, line0, m.group(0) + " (inside __asm__ body)", curated[a]))
if stale:
print(f"[lint_symbol_refs] {len(stale)} STALE func_<ADDR> ref(s) — renamed in symbols, "
f"clean-build will FAIL (fix: rename to the curated name):")
+103 -7
View File
@@ -32,6 +32,31 @@ from psyq_link import recover_sym_addrs, AS, sh, DATA_SECTIONS
from psyq_link_region import classify, placement
def stub_ranges(yaml_path, stubs, vram_base):
"""{stub_name: [vram_lo, vram_hi)} for the named code subsegs of a splat yaml (vram = fileoff + vram_base;
a subseg ends where the next subseg row begins). Loud on a stub the yaml does not name (R43)."""
import yaml as _yaml
y = _yaml.safe_load(open(yaml_path))
rows = []
for seg in y["segments"]:
if isinstance(seg, dict) and "subsegments" in seg:
for r in seg["subsegments"]:
if isinstance(r, list) and len(r) >= 3:
rows.append((int(r[0]), str(r[2])))
elif isinstance(r, list) and len(r) == 1:
rows.append((int(r[0]), None))
rows.sort()
out = {}
for i, (off, name) in enumerate(rows):
if name in stubs:
end = rows[i + 1][0] if i + 1 < len(rows) else off
out[name] = (off + vram_base, end + vram_base)
missing = [st for st in stubs if st not in out]
if missing:
sys.exit(f"integrate: stub subseg(s) {missing} not found in {yaml_path}")
return out
def contiguous_blocks(order):
"""Split vram-ordered objects into contiguous runs (a non-library gap starts a new block)."""
blocks, cur, end = [], [], None
@@ -67,9 +92,24 @@ def trial_undefined(ld_path, extra_syms=None):
def integrate(elf_dir, ld_path, objdir, syms_path, stubs, lo=None, hi=None,
*, vram_base, exe_path, symbols_path):
*, vram_base, exe_path, symbols_path, yaml_path=None):
exe = open(exe_path, "rb").read()
order = sorted(placement(elf_dir, lo, hi, vram_base, exe_path).items(), key=lambda kv: kv[1][0])
if yaml_path:
# P31 S78: the fixed psyq_identify (§485) locates objects inside subsegs that are NOT this
# library's stub blocks (e.g. libgte's FGO_01-06 fill the 800b_5 "game code" gap exactly), and
# contiguous_blocks() then MERGES adjacent blocks -> "3 object blocks but 22 stubs" -> the whole
# main link dies. Placement is not the same thing as wiring: only objects inside the stub subsegs
# named on this call are wired; the others are the LINKED RESIDUE and are printed, not swallowed
# (the completion contract's "residue empties" line reads exactly this).
ranges = stub_ranges(yaml_path, stubs, vram_base)
residue = [(nm, v, n) for nm, (v, n) in order if not any(a <= v < b for a, b in ranges.values())]
order = [(nm, vn) for nm, vn in order if any(a <= vn[0] < b for a, b in ranges.values())]
if residue:
print(f" ~~ {len(residue)} located object(s) / {sum(n for _, _, n in residue)} ins OUTSIDE the "
f"stub subsegs of {os.path.basename(elf_dir)} — byte-placed but NOT wired (LINKED residue):")
for nm, v, n in residue:
print(f" 0x{v:08X} {nm:14s} {n:5d} ins")
recovered, weaken_by, bases_by = {}, {}, {}
for name, (vram, _) in order:
bases, weaken, sym_addr = classify(os.path.join(elf_dir, name), vram, exe, vram_base)
@@ -79,19 +119,72 @@ def integrate(elf_dir, ld_path, objdir, syms_path, stubs, lo=None, hi=None,
recovered[s] = a
# 1. prepare objects (persistent)
# P31 S78 — CURATED NAMES WIN (R15) FOR A LIBRARY OBJECT'S *DEFINED* SYMBOLS TOO. A 4.0 object can
# export a name that the EXE's newer library assigned to a DIFFERENT address: libapi 4.0's A66.o
# exports `firstfile` (0x80062248), but the EXE links libapi 4.2, where that trampoline is
# `firstfile2` and `firstfile` is FIRST.o's C wrapper at 0x80061FA8 (LIBMCRD.o's `jal` word
# EA87010C targets 0x80061FA8 — the bytes say so). Once 0x80061FA8 carries its real name in C, the
# two object definitions collide at link. So: every symbol an object DEFINES whose recovered
# address the curated symbol file names differently is `--redefine-sym`'d to the curated name.
# Safe by construction: another object's reference to the OLD name is then undefined at the trial
# link and resolves through `recovered` to the address its own relocation bytes encode.
curated_by_addr = {}
for ln in open(symbols_path):
m = re.match(r"(\w+)\s*=\s*0x([0-9A-Fa-f]+)", ln)
if m:
curated_by_addr.setdefault(int(m.group(2), 16), m.group(1))
os.makedirs(objdir, exist_ok=True)
for name, _ in order:
for name, (vram, _) in order:
args = []
for S in (".text",) + DATA_SECTIONS:
args += ["--set-section-alignment", f"{S}=4"]
for w in weaken_by[name]:
args += ["--weaken-symbol", w]
defined = subprocess.run([f"{AS}nm", "--defined-only", os.path.join(elf_dir, name)],
capture_output=True, text=True).stdout
for dl in defined.splitlines():
parts = dl.split()
if len(parts) == 3 and parts[1] in "TtDdRrBb" and not parts[2].startswith("."):
sym = parts[2]
# a .text symbol's EXE address = object vram + its section offset (nm prints the offset)
addr = vram + int(parts[0], 16) if parts[1] in "Tt" else recovered.get(sym)
cn = curated_by_addr.get(addr) if addr is not None else None
if cn and cn != sym:
args += ["--redefine-sym", f"{sym}={cn}"]
print(f" == {name}: exported `{sym}` @0x{addr:08X} is curated `{cn}` -> redefined (R15)")
sh(f"{AS}objcopy", *args, os.path.join(elf_dir, name), os.path.join(objdir, name))
blocks = contiguous_blocks(order)
if len(blocks) != len(stubs):
sys.exit(f"integrate: {len(blocks)} object blocks but {len(stubs)} stub(s) given "
f"({[len(b) for b in blocks]} objs/block)")
if yaml_path:
# Stub<->objects by SUBSEG RANGE (P31 S78), not by run-contiguity: two adjacent stub subsegs are
# one contiguous byte run (libgte2..libgte7 touch), and the fixed psyq_identify reports section
# words incl. the alignment pad, so contiguity-splitting can no longer reproduce the yaml's blocks.
# Each stub must be tiled EXACTLY by its objects (first at lo, each abutting, last ending at hi
# up to the 8-byte section alignment) — anything else is a carve error and fails loud (R43).
by_stub = {st: [] for st in stubs}
for nm, (v, n) in order:
for st, (a, b) in ranges.items():
if a <= v < b:
by_stub[st].append((nm, v, n))
blocks = []
for st in stubs:
objs = sorted(by_stub[st], key=lambda t: t[1])
a, b = ranges[st]
if not objs:
sys.exit(f"integrate: stub subseg '{st}' [0x{a:08X},0x{b:08X}) has NO located object")
cur = a
for nm, v, n in objs:
if v != cur:
sys.exit(f"integrate: stub '{st}' not tiled — expected an object at 0x{cur:08X}, "
f"found {nm} at 0x{v:08X}")
cur = v + n * 4
if not (b - 8 < cur <= b):
sys.exit(f"integrate: stub '{st}' ends at 0x{b:08X} but its objects end at 0x{cur:08X}")
blocks.append(objs)
else:
blocks = contiguous_blocks(order)
if len(blocks) != len(stubs):
sys.exit(f"integrate: {len(blocks)} object blocks but {len(stubs)} stub(s) given "
f"({[len(b) for b in blocks]} objs/block)")
# 2. rewrite the linker script
ld = open(ld_path).read()
@@ -215,11 +308,14 @@ def main():
ap.add_argument("--exe", required=True, help="target binary path")
ap.add_argument("--symbols", required=True,
help="symbol-address file for stub-name->address resolution")
ap.add_argument("--yaml", default=None,
help="splat yaml of the target binary: wire ONLY objects inside the named stub subsegs; "
"print the rest as the LINKED residue (P31 S78)")
a = ap.parse_args()
lo = a.window[0] if len(a.window) > 0 else None
hi = a.window[1] if len(a.window) > 1 else None
integrate(a.elf_dir, a.ld_path, a.objdir, a.syms_ld, a.stubs.split(","), lo, hi,
vram_base=int(a.vram_base, 0), exe_path=a.exe, symbols_path=a.symbols)
vram_base=int(a.vram_base, 0), exe_path=a.exe, symbols_path=a.symbols, yaml_path=a.yaml)
if __name__ == "__main__":