diff --git a/.run/backlog.jsonl b/.run/backlog.jsonl index 852d7933d9..e772c1c9ca 100644 --- a/.run/backlog.jsonl +++ b/.run/backlog.jsonl @@ -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//nonmatchings//.s => src//.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 ", "08060517 j .L8018145C"], [18, "08000047 j\t11c ", "08060517 j .L8018145C"], [26, "1440002c bnez\tv0,11c ", "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 ", "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 ", "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 ", "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 ", "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//nonmatchings//.s => src//.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 ", "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 ", "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//nonmatchings//.s => src//.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//nonmatchings//.s => src//.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//nonmatchings//.s => src//.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//nonmatchings//.s => src//.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//nonmatchings//.s => src//.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//nonmatchings//.s => src//.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//nonmatchings//.s => src//.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//nonmatchings//.s => src//.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//nonmatchings//.s => src//.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//nonmatchings//.s => src//.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 ", "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 ", "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 ", "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 ", "08060517 j .L8018145C"], [18, "08000047 j\t11c ", "08060517 j .L8018145C"], [26, "1440002c bnez\tv0,11c ", "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 ", "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 ", "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 ", "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 ", "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 ", "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 ", "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//nonmatchings//.s => src//.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} diff --git a/Makefile b/Makefile index 7825eaa86c..6dd747a906 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/config/symbols.us.txt b/config/symbols.us.txt index 0aeaf6e111..4a78bc3fad 100644 --- a/config/symbols.us.txt +++ b/config/symbols.us.txt @@ -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) diff --git a/config/verbatim_manifest.json b/config/verbatim_manifest.json index abe19c489f..a0e7e4f207 100644 --- a/config/verbatim_manifest.json +++ b/config/verbatim_manifest.json @@ -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" diff --git a/config/wave_exclude.txt b/config/wave_exclude.txt index 41b504a049..f7aa0fba26 100644 --- a/config/wave_exclude.txt +++ b/config/wave_exclude.txt @@ -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 diff --git a/docs/SETUP.md b/docs/SETUP.md index 96c077a8c2..72c3e6fd50 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -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//.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//`; 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 https://github.com/ tools/reference/`. **`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/_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 `__at_`. 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) → `.c` each. Headless harvest Ghidra-C pre-pass (Phase 17); no live MCP / `/mcp` needed. Run: stop MCP, `analyzeHeadless ghidra bfm -process -noanalysis -postScript DecompileFunctions.java `. | | | `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 ` + `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 ` (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_` token in committed `src/` whose address has a CURATED name in the symbol files and no `func_` 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_` token in committed `src/` whose address has a CURATED name in the symbol files and no `func_` 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/`). | diff --git a/docs/accelerators.md b/docs/accelerators.md index 08f7024c7f..9b9e2ae264 100644 --- a/docs/accelerators.md +++ b/docs/accelerators.md @@ -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//.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`. diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md index d663f0579f..72c7baecfc 100644 --- a/docs/cookbook-index.md +++ b/docs/cookbook-index.md @@ -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`) L33780 - **§481** — ★★★ — `conflicting types` IS A SAME-SCOPE ERROR; ACROSS SCOPES IT IS ONLY A WARNING (P31 S77, `main:func_8001FC08`, 400 ins) L35901 -### declarations, prototypes & K&R (120) +### declarations, prototypes & K&R (121) - **§3-T4** — Branch polarity: invert the source condition to flip gcc's chosen branch L90 - **§8c** — Splitting a TU means rebuilding its DECLARATION ENVIRONMENT, not moving text (Phase 26 session 6) L456 @@ -765,6 +765,7 @@ - **§468** — THE `%lo`-FOLD EXTENDS TO STORES ONLY VIA `extern Struct SYM[]`, AND MASKING HID THE OPERAND ORDER L35380 - **§477** — ★★★ — THE `self_decl_tu` CLASS IS A SOLVED, MECHANICAL LANE: 16 DRAFTS, 16 BANKS (P31 S77) L35713 - **§481** — ★★★ — `conflicting types` IS A SAME-SCOPE ERROR; ACROSS SCOPES IT IS ONLY A WARNING (P31 S77, `main:func_8001FC08`, 400 ins) L35901 +- **§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) L36150 ### 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) L34647 - **§477** — ★★★ — THE `self_decl_tu` CLASS IS A SOLVED, MECHANICAL LANE: 16 DRAFTS, 16 BANKS (P31 S77) L35713 -### build graph, splat & the harness (206) +### build graph, splat & the harness (207) - **§4** — Flag/toolchain gotchas L190 - **Build** — mechanism — per-file opt override (splat resegmentation) L307 @@ -1287,6 +1288,7 @@ - **§483** — ★★★ — THE S77w WAVE HARVEST: SIX LEVERS, FOUR FROM BANKED (BYTE-PROVEN) BODIES L35967 - **§484** — ★★★ — "NO SINGLE NOLOAD BASE" IS NOT "UNLINKABLE": ASK WHETHER THE `.bss` OFFSETS ARE DISJOINT (P31 S77) L36023 - **§485** — ★★★ — THE PLACEMENT MAP WAS PARSING A PRETTY-PRINTER: 25 PsyQ OBJECTS WERE INVISIBLE, NOT ABSENT (P31 S77) L36069 +- **§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) L36150 ### 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) L36023 - **§485** — ★★★ — THE PLACEMENT MAP WAS PARSING A PRETTY-PRINTER: 25 PsyQ OBJECTS WERE INVISIBLE, NOT ABSENT (P31 S77) L36069 - **§486** — ★★★ — CARVING AN `-O0` ISLAND IN **main**: FIVE COUPLED PIECES, AND THE TWO THAT ANNOUNCE THEMSELVES (P31 S77) L36105 +- **§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) L36150 --- @@ -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 | diff --git a/docs/decision-log.md b/docs/decision-log.md index 7a1e2af65d..dcf068a84a 100644 --- a/docs/decision-log.md +++ b/docs/decision-log.md @@ -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. diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md index c6d4d855da..f6f7bdda38 100644 --- a/docs/matching-cookbook.md +++ b/docs/matching-cookbook.md @@ -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//.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). diff --git a/docs/psyq-worklist.md b/docs/psyq-worklist.md index 6bd601e07c..a4ebf0c3a2 100644 --- a/docs/psyq-worklist.md +++ b/docs/psyq-worklist.md @@ -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//.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). diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md index 66fcab2484..4a979f0fab 100644 --- a/phase-ends/CURRENT_PHASE.md +++ b/phase-ends/CURRENT_PHASE.md @@ -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) diff --git a/src/800.c b/src/800.c index 36b981985c..ad1bc0a54f 100644 --- a/src/800.c +++ b/src/800.c @@ -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(); diff --git a/src/800_b_2.c b/src/800_b_2.c index 210e173e51..cd03509f8f 100644 --- a/src/800_b_2.c +++ b/src/800_b_2.c @@ -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; } diff --git a/src/800c2.c b/src/800c2.c index bc0aae5a05..1982901df2 100644 --- a/src/800c2.c +++ b/src/800c2.c @@ -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; diff --git a/src/800c2_2.c b/src/800c2_2.c index 263273ba29..b796b43e98 100644 --- a/src/800c2_2.c +++ b/src/800c2_2.c @@ -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; diff --git a/src/800c2_3.c b/src/800c2_3.c index 04a2764cb7..1af2276fd5 100644 --- a/src/800c2_3.c +++ b/src/800c2_3.c @@ -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" ); diff --git a/src/800c3.c b/src/800c3.c index b55b4b54f9..b2ac114fb5 100644 --- a/src/800c3.c +++ b/src/800c3.c @@ -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; diff --git a/src/libcd1.c b/src/libcd1.c index c915b7a5cb..edfd307230 100644 --- a/src/libcd1.c +++ b/src/libcd1.c @@ -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); diff --git a/tools/ghidra_apply_symbols.sh b/tools/ghidra_apply_symbols.sh new file mode 100644 index 0000000000..531ddd6dbe --- /dev/null +++ b/tools/ghidra_apply_symbols.sh @@ -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 (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" diff --git a/tools/ghidra_scripts/ApplySymbols.java b/tools/ghidra_scripts/ApplySymbols.java new file mode 100644 index 0000000000..6d3e9409af --- /dev/null +++ b/tools/ghidra_scripts/ApplySymbols.java @@ -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 +// `__at_` so nothing is silently dropped. Prints BFMAPPLY counts; verify with +// tools/ghidra_mcp_verify.sh (R9). +// +// Args: [ ...] (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 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 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()); + } + } +} diff --git a/tools/lint_symbol_refs.py b/tools/lint_symbol_refs.py index dfe12c3667..a7a4da2670 100644 --- a/tools/lint_symbol_refs.py +++ b/tools/lint_symbol_refs.py @@ -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_` 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'(? ref(s) — renamed in symbols, " f"clean-build will FAIL (fix: rename to the curated name):") diff --git a/tools/psyq_integrate.py b/tools/psyq_integrate.py index fa8dc59abe..5ece5a05be 100644 --- a/tools/psyq_integrate.py +++ b/tools/psyq_integrate.py @@ -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__":