Files
BFM-decomp/phase-ends/logs/Phase8.md
T
Drew T 1f5cc43981 feat(phase-8): close-out — PhaseEnd_Phase8 + worklog archived (v1.8.0)
- PhaseEnd_Phase8.md: 8 PsyQ libraries linked byte-identical, byte-identical coverage
  20.31% -> 50.24% (LINKED 340 -> 959), 9 game-code matches (REAL 43 -> 52), milestone
  confirmed by Drew (gate 2)
- rule R22 (verify byte-matches from a clean rebuild, never incremental)
- CURRENT_PHASE.md -> phase-ends/logs/Phase8.md (R19)
- bumps project version 1.7.0 -> 1.8.0
2026-06-15 19:22:36 -06:00

7.8 KiB

CURRENT PHASE — Phase 8: Finish the EXE — remaining PsyQ libraries + final harvest

Gen2, Phase 8 (first Gen2 phase). Plan APPROVED by Drew 2026-06-15 (gate 1 passed). Full plan: /home/musashi/.claude/plans/plan-mode-enabled-max-wobbly-manatee.md (mirrored here as the in-repo crash-recovery log, P3). Execution effort: xHigh default; conditional Max if a library fights past cookbook §9; Max for the PhaseEnd. Owner decisions (2026-06-15): progress metric = add a LINKED category to progress.py; exit bar = full matching ceiling (link every footprint-confirmed library; defer any that fight as honest documented stubs). Commit cadence: per-session/per-task checkpoints, commit + (Drew) push irreplaceable work (R20, loosens R8).

Goal / milestone (byte-checkable gate)

  1. make clean && extract && build && check → SHA1 143dbb89… byte-identical with all newly-linked SDK objects AND without them (.run/obj40/ absent → stub fallback) — both green.
  2. make report shows REAL / LINKED / NON_MATCHING / stubs; LINKED grown by the newly-linked objects, stubs reduced accordingly, REAL up by the harvested game leaves; deterministic.
  3. 0 NON_MATCHING in the default build preserved (G4).
  4. Every footprint-confirmed library is linked OR documented as an honest deferral (docs/psyq-worklist.md) — no silent gaps (P9).
  5. git status shows zero ROM-derived/generated bulk staged.

Tasks

  • T0 — Write this CURRENT_PHASE.md (kickoff). (Tier-3)
  • T1 — Library placement survey + worklist → docs/psyq-worklist.md. DONE: 9 footprint libs (libgpu/libetc/libmcrd/libc2/libcard/libapi/libspu/libsnd/libgte = 199 placements) ranked ascending-difficulty; 3 SKIP (libmath/libc/libsn = 0 footprint); key findings: libgs "gaps" gsgap1/2/4/5 are libgte; heavy interleaving (800=game+libspu+libsnd+libetc, 800b≈libgte, 800b2=game+libgpu/libc2/libapi/libmcrd/libcard); cross-lib aliases (C112, UT_RON/S_IH, S_R/S_W).
  • T2 — progress.py LINKED category. DONE: linked subsegs sourced from the Makefile's psyq_integrate calls (single source of truth, auto-updates per integration); libcd+libgs 340 stubs→LINKED; byte-identical/matchable now 425/2093 = 20.31%; build unchanged (143dbb89).
  • [~] T3…N — Per-library integrate, ascending difficulty (resegment splat → trim src → Makefile gated psyq_integrate + -T syms → dual byte-gate → report → commit). (xHigh; Max-escalate if a lib fights) → report #2 after first lib lands; #3 when last placed lib done
    • libetc (5 objs, 35 fns) — clean single block at 800-tail; 5/5 byte-verified; dual byte-gate PASS; LINKED 340→375. (progress report #2)
    • libgpu (EXT+PRIM, 2 objs / +49 fns; curated libgpu_used) — dual byte-gate PASS; LINKED 375→424. SYS.o EXCLUDED = scattered-.bss §9.1 (GS_001 class), documented in worklist, stays a stub in 800c. Split 800b2→[800b2][libgpu][800c]. First hard case handled.
    • libmcrd (2 objs / +104 fns) — clean (27 .bss commons all recovered); 2 non-adjacent blocks (libmcrd1/libmcrd2) splitting 800c; dual byte-gate PASS; LINKED 424→528.
    • libc2 (17 objs / +62 fns) — C stdlib, 2 blocks (16-obj main libc2_1 + STRCAT libc2_2; PRNT jtbl OK). Hit + fixed the boundary gotcha: SETJMP.o .text=0x80 (8-align pad) not 0x78 → 800c3 boundary was 8 low → +8 global shift; fixed to 0x5CE18. Lesson recorded in worklist. dual byte-gate PASS; LINKED 528→590.
    • libgte (53/58 objs / +120 fns; 22 blocks) — reordered value-first. Built tools/gen_lib_subsegs.py (generates multi-block subseg lines w/ section-size boundaries) + integrate window. progress.py now resolves $(VAR) stub lists. 5 libgs-gap objects DEFERRED. dual byte-gate PASS; LINKED 590→710, byte-identical 37.93%.
    • libspu+libsnd COMBINED sound region (60/70 objs / +225 fns; 9 blocks) — the two libs interleave so linked as ONE region. New tools/make_snd_used.py (alias dedup by byte-match + exclude-by-address). 4 addresses excluded (scattered-.bss/false-pos: S_R/S_GRMDT/S_IH/VM_F), SSGM deferred. All matched C preserved (trim kept 732 < 0x3A444). dual byte-gate PASS; LINKED 710→935, byte-identical 48.66%.
    • libapi+libcard COMBINED 800c2 region (22 objs / +24 fns; 4 blocks; tools/make_apicard_used.py, 0 exclusions) — dual byte-gate PASS; LINKED 935→959, byte-identical 49.81%. libapi's 800c3 remnant (~22 objs) DEFERRED.
    • LIBRARY CEILING REACHED — 8 libs linked (959 LINKED fns); remaining are documented low-value deferrals (worklist).
  • T(N+1) — Deferred-library hard-case documentation (honest stub deferrals, structured comments, worklist notes). (xHigh)
  • T(N+2) — Game-code harvest (read cookbook+§5.4 first; sig-refresh → difficulty.md regen → cheap non-jtbl game leaves; bank, don't exhaust). (xHigh; optional breadth) → report #4
  • T(N+3) — Headers (include/psyq/*.h) + cookbook §9 flywheel (R16) + SETUP/memory-map refresh (R21). (xHigh)
  • T(N+4) — Phase 8 close: verify checkboxes (P7) → demo milestone → Drew confirms (gate 2) → PhaseEnd_Phase8.md + archive worklog (R19) + commit + Ghidra push (R20) + plain-English recap (R18) + hard stop (P8). (Tier-1 Max)

Current task pointer

T15 — AWAITING DREW'S MILESTONE CONFIRMATION (gate 2). All work tasks done. PhaseEnd (Tier-1) written only after Drew confirms the milestone.

✅ MILESTONE ACHIEVED (verified 2026-06-15)

  1. make clean && extract && build && check → SHA1 143dbb89… byte-identical with all 8 newly-linked PsyQ libraries AND without any SDK objects (fresh-clone all-stubs fallback) — both green.
  2. make report deterministic: REAL 52 (was 43; +9 game-code harvest) · LINKED 959 (was 340 libcd+libgs only; +619 from 8 libs) · NON_MATCHING 7 · empties 42 · stubs 1036. byte-identical/matchable 20.31% → 50.24%.
  3. 0 NON_MATCHING in the default build (the 7 are #ifdef-guarded) — G4 preserved.
  4. Every footprint library linked OR documented honest deferral (docs/psyq-worklist.md).
  5. git status clean (zero ROM/generated bulk staged).
  • 8 PsyQ libraries linked byte-identical: libetc, libgpu(EXT+PRIM), libmcrd, libc2, libgte(53/58), libspu+libsnd(60/64 combined), libapi+libcard(800c2). New tooling: gen_lib_subsegs.py, make_snd_used.py, make_apicard_used.py; progress.py LINKED category.
  • Documented deferrals (low-value, honest stubs): libgpu SYS.o + sound S_R/S_GRMDT/VM_F + GS_001 (scattered-.bss); libgte 5 libgs-gap objs; SSGM; libapi 800c3 remnant (~22). Build byte-identical regardless.

T13 game-code harvest DONE: 9 trivial game-code accessors matched (func_8002AEF8/AF08/AF60, func_8002D4B8/D7FC/D834, func_8002F648, func_80037358/37CC8 — getters/setters of D_* globals, byte-verified). REAL 43→52. (Gotcha found: matching changes need make clean rebuild — the incremental psyq_integrate .ld rewrite can go stale.) sig-refresh deferred (needs Ghidra stopped; difficulty.md regenerates next session).

Progress log

  • 2026-06-15 (session A, planning): Read PROJECT_CONTEXT + all PhaseEnds + effort-map + gen2-roadmap. Byte-grounded the Phase-8 scope (R14): harvest is ~90% library objects; progress.py counts linked libs as stubs; machinery ready (20 .LIBs, 14 .a, 14 built .run/obj40/* dirs). Two owner decisions taken (LINKED category; full ceiling). Plan approved (gate 1). T0 done — this file written.
  • 2026-06-15 (session A, exec): Baseline confirmed byte-identical (143dbb89). T1 done — psyq_identify survey → docs/psyq-worklist.md (9 footprint libs / 199 placements ranked; 3 skip). T2 done — progress.py LINKED category (340 fns; byte-identical 20.31%; build unchanged). Built the 16-task monitor list. Committed T1+T2 foundation checkpoint.

Blockers

  • None.