Files
BFM-decomp/phase-ends/PhaseEnd_Phase5.md
T
Drew T d55882b4b8 feat(phase-5): splat config + all-asm byte-identical build of SLUS_007.26
- config/splat.us.exe.yaml: splat PSX config (platform psx, compiler PSYQ,
  subalign 2, gp_value 0x80074750, base_path .., main segment align 4); one
  asm text seg [0x800] + data seg [0x531DC], header via splat's header segtype
- Makefile: implement extract (splat split) / build (as -> ld(splat .ld +
  undefined_*_auto) -> objcopy) / check (SHA1 vs config/check.us.sha, auto-run)
  / expected (asm-differ baseline) / clean; check-env untouched
- config/check.us.sha: committed build-check hash (validation stage 2)
- config/symbols.us.txt: now hand-curated — 15 2D_* -> gfx2D_* (illegal leading
  digit broke as), +D_800629D4 label; header flags re-merge + Ghidra-mirror (G6)
- .gitignore: ignore regenerable splat outputs (asm/, include macros,
  undefined_*_auto.txt); refine the earlier commit-asm/ note
- docs: SETUP.md §4.5 binutils 2.42 = byte-clean (no 2.35 downgrade), §5.3 +
  ledger #8 RESOLVED -G0, §6.3 as-built; memory-map.md gp0 -> -G0 + text/data split
- MILESTONE: make extract && make build && make check -> build/us/SLUS_007.26
  SHA1 143dbb89... == original (BYTE-IDENTICAL), 100% asm, check fails on corruption
- rule R15 (symbol file = curated, valid-identifier build input, Ghidra-mirrored)
- bumps project version 1.4.0 -> 1.5.0
2026-06-14 12:05:38 -06:00

123 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PhaseEnd — Phase 5: splat config + build skeleton (all-asm byte-match)
**Date:** 2026-06-14 · **Project Version:** 1.5.0 · **Phase Status:** Complete
## Build Log
**Files created/changed and complete — do not recreate:**
- `config/splat.us.exe.yaml` — **new.** The splat config for the main EXE. Derived from splat 0.41.0's own
`create_psx_config` template (platform `psx`, compiler `PSYQ`, `subalign: 2`, `section_order` rodata/text/
data/bss, `find_file_boundaries: False`, `gp_value: 0x80074750`). `base_path: ..` (the yaml lives in
`config/`, so paths anchor at the repo root). One `code` segment split into a `[0x800] asm` text
subsegment + a `[0x531DC] data` subsegment, `align: 4` on the segment (see Deviations). Consumed by
`make extract`.
- `config/check.us.sha` — **new, committed.** `143dbb89… SLUS_007.26` — the canonical build-check hash
(validation stage 2). Consumed by `make check`.
- `config/symbols.us.txt` — **modified (now HAND-CURATED).** 15 `2D_*` → `gfx2D_*` renames (a leading digit
is an illegal as/C identifier — it broke `as`); added the `D_800629D4` data label (boot-code-referenced
address in the text→data boundary region that splat did not auto-label). Header rewritten to flag that
ExportSymbols.java overwrites this file → re-apply curations + mirror to Ghidra (G6). Consumed by splat.
- `Makefile` — **modified.** The five Phase-5 stub targets replaced with real implementations: `extract`
(splat split), `build` (assemble `asm/*.s` → `ld` via the splat linker script + `undefined_*_auto.txt` →
`objcopy -O binary` → `build/us/SLUS_007.26`), `check` (SHA1 vs `config/check.us.sha`, auto-run by
`build`), `expected` (snapshot a verified build → `expected/build/`), `clean` (remove all regenerable
outputs). Added vars `SPLAT/CPP/OUT/ELF/LD_SCRIPT/ASFLAGS/ASPSX_VERSION/OBJS`. `check-env` untouched.
- `.gitignore` — **modified.** Ignore the regenerable splat outputs (`/asm/`, the four generated
`include/` macros, `undefined_{syms,funcs}_auto.txt`); the earlier "commit asm/" note refined with
rationale (durable record = `config/symbols.us.txt`). `/build/` + `/expected/` already ignored.
- `docs/SETUP.md` — **modified.** §4.5 binutils **VERDICT: 2.42 byte-clean** (no downgrade); §5.3 + ledger
#8 **RESOLVED: -G0**; §6.3 **As-built (Phase 5)** target table note; ledger #6 resolved. Original
deferred-verdict text preserved (additive).
- `docs/memory-map.md` — **modified.** §1 `gp0` row → **-G0 CONFIRMED**; added the **Text→data split**
block (file/vram boundary, the mixed transition region, `vram = fileoff + 0x8000F800`).
- `phase-ends/PhaseEnd_Phase5.md` — this file.
- `phase-ends/CURRENT_PHASE.md` — **absorbed into this file and deleted** (P8).
**Local artifacts (gitignored / regenerable — do NOT recreate; `make extract` rebuilds them):**
- `asm/{header.s, 800.s, data/531DC.data.s}` — the splat disassembly (header reproduced via splat's
structured `header` segtype; text + data).
- `include/{include_asm.h, macro.inc, labels.inc, gte_macros.inc}` — splat-generated assembler macros.
- `build/us/SLUS_007.26.ld` — the splat-generated linker script (`_gp=0x80074750`; `ALIGN(.,4)`).
- `undefined_syms_auto.txt` (899) + `undefined_funcs_auto.txt` (8) — splat-generated linker symbol defs.
- `build/` (objects, `.elf`, the 413,696-byte binary) + `expected/build/` (the asm-differ baseline).
**Tools/packages installed:** None — used the existing Phase-4 toolchain (splat64 0.41.0, mipsel-binutils
2.42, the cc1 candidates) entirely. (cc1/maspsx were not invoked — the build is all-assembly.)
**Verification results (literal):**
- **`make extract && make build && make check` → `build/us/SLUS_007.26`, 413,696 B, SHA1
`143dbb89f34491258bbc27810d0a12ec8b43a8dd` == original (BYTE-IDENTICAL).** Reproduced from a full
`make clean` cycle.
- **Check is a real gate:** a 1-byte corruption makes `make check` exit non-zero; a rebuild restores `[ OK ]`.
- `make check-env` still exits 0 (no Phase-4 regression).
- **binutils 2.42 byte-clean** with `as -march=r3000 -mtune=r3000 -no-pad-sections -O1 -G0` — the §4.5
"≥2.38 regression" risk did not materialise; no 2.35 downgrade.
- **-G0 confirmed:** the disassembly has **0** `($gp)` base accesses and **0** `%gp_rel` relocations.
- `git status`: only `config/`, `Makefile`, `.gitignore`, `docs/` tracked; `asm/ build/ expected/` +
generated macros + `undefined_*_auto.txt` ignored — **zero generated/ROM bulk staged.**
**Milestone achieved:** `make build` rebuilds `SLUS_007.26` **byte-for-byte (SHA1-identical)** from
disassembly alone at 100% assembly, with the SHA1 check auto-running and provably failing on corruption —
the split, linker script, and as→ld→objcopy tooling proven end-to-end.
**Next:** Phase 6 — Compiler fingerprint + first matched functions. Start with selecting 3–5 medium leaf
functions as fingerprint probes (⭐⭐ **Max** — the highest-stakes task in Gen1 per `docs/effort-map.md`).
Phase 6 also introduces the `c`/INCLUDE_ASM scaffold (flip the code subsegment to `c`, wire `decompile.py`
+ asm-differ, establish INCLUDE_ASM/NON_MATCHING headers) — the Makefile already has the dormant
cpp→cc1→maspsx path and the §5.4 candidate ladder is queued.
## Deviations
| Item | Plan | Actual | Reason |
|---|---|---|---|
| Code segment type | `c`/INCLUDE_ASM primary; `asm` as fallback | **`asm` (all-asm)** | The plan's documented fallback, and the better fit: the phase title is "all-asm byte-match" and the roadmap puts INCLUDE_ASM/NON_MATCHING setup in Phase 6. Keeps the unpinned compiler out of Phase 5. Drew-ratified. |
| Execution order | T1 split → T2 Makefile → T3 byte-match | Byte-identity proven by a **manual round-trip during T1**, before the Makefile | Isolated and cleared the High-risk binutils-2.42 variable first (as→ld→objcopy only); the Makefile then just transcribed the working chain. |
| binutils 2.42 verdict | possibly downgrade to 2.35 (§4.5) | **No downgrade — 2.42 is byte-clean** | The build is SHA1-identical with 2.42; the regression warning didn't bite our flags. |
| `asm/` git policy | gitignore (my plan) vs the repo's existing "commit asm/" note | **gitignored** (regenerable via `make extract`) | `make extract` deterministically regenerates it from committed yaml+symbols → build scaffolding, not durable work. `.gitignore` note refined; Drew-ratified. |
| Section-boundary effort | feared a fighting link (T3 Max-escalation) | The link was clean; the only real fights were **15 leading-digit symbol names** + **one un-labelled boundary address** + an **`align: 4`** tweak | splat round-trips bytes, so byte-identity was robust to the imperfect text/data split (as predicted). |
| `config/symbols.us.txt` role | seeded Ghidra export | became the **hand-curated** build input | Build validity (identifiers) + a boot-referenced label had to be fixed in the splat input; ExportSymbols now a careful re-merge, not a blind overwrite (→ R15). |
## Commit Message
```
feat(phase-5): splat config + all-asm byte-identical build of SLUS_007.26
- config/splat.us.exe.yaml: splat PSX config (platform psx, compiler PSYQ,
subalign 2, gp_value 0x80074750, base_path .., main segment align 4); one
asm text seg [0x800] + data seg [0x531DC], header via splat's header segtype
- Makefile: implement extract (splat split) / build (as -> ld(splat .ld +
undefined_*_auto) -> objcopy) / check (SHA1 vs config/check.us.sha, auto-run)
/ expected (asm-differ baseline) / clean; check-env untouched
- config/check.us.sha: committed build-check hash (validation stage 2)
- config/symbols.us.txt: now hand-curated — 15 2D_* -> gfx2D_* (illegal leading
digit broke as), +D_800629D4 label; header flags re-merge + Ghidra-mirror (G6)
- .gitignore: ignore regenerable splat outputs (asm/, include macros,
undefined_*_auto.txt); refine the earlier commit-asm/ note
- docs: SETUP.md §4.5 binutils 2.42 = byte-clean (no 2.35 downgrade), §5.3 +
ledger #8 RESOLVED -G0, §6.3 as-built; memory-map.md gp0 -> -G0 + text/data split
- MILESTONE: make extract && make build && make check -> build/us/SLUS_007.26
SHA1 143dbb89... == original (BYTE-IDENTICAL), 100% asm, check fails on corruption
- rule R15 (symbol file = curated, valid-identifier build input, Ghidra-mirrored)
- bumps project version 1.4.0 -> 1.5.0
```
## Rules Added This Phase
| Rule | Reason |
|---|---|
| **R15 — `config/symbols.us.txt` is the curated, build-valid symbol source.** It is hand-curated (seeded from `ExportSymbols.java`, then refined for the build); re-exporting is a **careful re-merge, never a blind overwrite**. Every name must be a valid as/C identifier (no leading digit, etc.). All curations — renames and added labels — are **mirrored back into Ghidra** so a future re-export stays valid and consistent (extends G5/G6). | Phase 5: `2D_*` names broke `as` (leading digit illegal); the fix lives only in this file, which `ExportSymbols` would silently overwrite, and Ghidra must carry the change to stay the static oracle. This recurs at scale in Gen2. |
## PhaseEnd Changelog
**v1.4.0 → v1.5.0** — Phase 5 complete. The repo now **rebuilds `SLUS_007.26` byte-for-byte (SHA1-identical)
from disassembly alone** via `make extract && make build && make check` — splat split → mipsel-`as` → `ld`
(splat linker script) → `objcopy`, at 100% assembly (no C). The build is **compiler-independent** (no
cc1/maspsx invoked), so it is solid before the Phase-6 fingerprint. Two roadmap unknowns fell out for free:
**binutils 2.42 is byte-clean** (the §4.5 ≥2.38 regression risk cleared — no 2.35 downgrade) and **ledger #8
= -G0** (zero `$gp`-relative addressing in the disassembly). The splat config uses splat's own PSX template
(PSYQ, subalign 2, gp 0x80074750) with a single `align: 4` tweak (the word- but not 16-aligned text→data
boundary at vram 0x800629DC). `config/symbols.us.txt` became the hand-curated build input (15 `2D_*`→`gfx2D_*`
for illegal identifiers, +`D_800629D4` label) → **R15**. Decisions (Drew-ratified): the code segment stays
**all-`asm`** (Phase 6 owns the INCLUDE_ASM/.c scaffold per the roadmap), and the regenerable splat outputs
(`asm/`, generated macros, `undefined_*_auto.txt`) are **gitignored**. No tools installed. One rule (R15).
## 🛑 Stop Here
PhaseEnd written; `CURRENT_PHASE.md` absorbed and removed. **Drew commits AND pushes** this PhaseEnd plus the
whole Phase-5 change set (R6/R8). Start a **fresh session for Phase 6 — Compiler fingerprint + first matched
functions**. Keep this file forever.