Pre-existing latent breakage (Phase-21 close commit:0292, "+62 PsyQ names"), found during T5b's
R22 fleet verify. A genuinely-clean `make clean` + re-extract + build of `main` failed with
dozens of `can't open asm/nonmatchings/800c3/func_*.s` — clean-rebuild broken since Phase 21,
masked all along by incremental builds reusing stale pre-rename .s/.o (the exact R22 failure mode).
- Root cause (byte-proven): Phase-21 xdedup renamed 62 PsyQ library functions to their proper
names (InitHeap, FlushCache, GetTPage, SysEnqIntRP, SpuWrite, CdMix, __main …) in
symbols.us.txt, but never regenerated/renamed the committed src/*.c stub refs that call them by
the OLD func_<ADDR> name. splat's FRESH regeneration of a stub .c uses the CURATED names (move
src/800c3.c aside -> splat writes INCLUDE_ASM(InitHeap) + emits InitHeap.s); the committed stubs
were simply stale.
- Fix: rename all 62 INCLUDE_ASM(func_<ADDR>) -> the curated name across 12 files (800c.c 1,
800c3.c 22, apicard1/2/4 4/6/2, boot.c 1, libcd1.c 8, libetc.c 6, libgpu.c 3, sgap.c 1,
snd1.c 7, snd2.c 1). Pure rename to match splat's canonical output; byte-neutral.
- VERIFIED: main clean-builds 143dbb89 from a fully clean tree; full clean fleet check-all 136/136.
- Lesson (cookbook): a symbols.us.txt rename must be propagated to (a) shared-macro bodies
(engine_core.h — the T5b GetTPage fix) AND (b) INCLUDE_ASM stub refs (this), AND verified by a
genuinely-clean check-all (make clean + full re-extract), never incremental. Added a lint check.
- libspu and libsnd interleave in 0x3A444..0x4239C (the 800-subseg tail), so they link
as ONE combined region rather than two tangled passes
- NEW tools/make_snd_used.py: build the curated combined dir — merge both libs by vram,
pick the byte-matching object per aliased address (link_object), exclude 4 addresses
that don't reconcile in-region (kept as byte-identical stubs):
0x3C438 S_R/S_W, 0x3D424 S_GRMDT/FB/T — scattered-.bss commons, cross-object (§9.1)
0x3D94C S_IH/UT_RON — false placement (inside libsnd SSSTART.o)
0x3FA64 VM_F (237 ins) — scattered-.bss commons (the one real loss)
- subsegs via gen_lib_subsegs.py (9 snd blocks + 8 sgap game/excluded-stub gaps);
integrate window 0x3A444..0x4239C; region byte-verified 60/60
- src/800.c trimmed at [0x3A444,0x4239C): kept 732 items < 0x3A444 (ALL matched C +
game + the deferred SSGM stub preserved), 0 real-C moved
- dual byte-gate PASS: 143dbb89 with and without the sound objects
- LINKED 710 -> 935 (+225); REAL still 43; byte-identical 48.66% (nearly half the EXE)
- deferred: SSGM.o @0x1BD80 (isolated, matched-C region, 8 ins)