- 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
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)
make clean && extract && build && check→ SHA1143dbb89…byte-identical with all newly-linked SDK objects AND without them (.run/obj40/absent → stub fallback) — both green.make reportshows REAL / LINKED / NON_MATCHING / stubs; LINKED grown by the newly-linked objects, stubs reduced accordingly, REAL up by the harvested game leaves; deterministic.- 0 NON_MATCHING in the default build preserved (G4).
- Every footprint-confirmed library is linked OR documented as an honest deferral (
docs/psyq-worklist.md) — no silent gaps (P9). git statusshows 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.pyLINKED category. DONE: linked subsegs sourced from the Makefile'spsyq_integratecalls (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 +
-Tsyms → 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
.bsscommons 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)
make clean && extract && build && check→ SHA1143dbb89…byte-identical with all 8 newly-linked PsyQ libraries AND without any SDK objects (fresh-clone all-stubs fallback) — both green.make reportdeterministic: 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%.- 0 NON_MATCHING in the default build (the 7 are
#ifdef-guarded) — G4 preserved. - Every footprint library linked OR documented honest deferral (
docs/psyq-worklist.md). git statusclean (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_identifysurvey →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.