feat(phase-4): matching-build toolchain (WSL) — make check-env green

- apt: build-essential, binutils-mipsel-linux-gnu 2.42 (+gcc-mipsel 12.x), ninja
  1.11.1, python3-pip/venv, libelf-dev, clang-format, p7zip, bchunk, bsdmainutils
- .venv + splat64 0.41.0 ([mips]: spimdisasm 1.41.0, rabbitizer 1.16.2, PyYAML 6.0.3)
- 4 pinned submodules under tools/: maspsx@874855c5, decomp-permuter@b44b0622,
  asm-differ@2ad4a4a4, m2c@4266cc28 (.gitmodules)
- old-gcc 0.17 cc1 candidates -> tools/bin/gcc-2.7.2-{psx,cdk}/ (32-bit i386 static;
  tarballs are flat + same-named -> per-subdir extraction); CHECKSUMS.sha256 committed
  (gitignore exception !/tools/bin/*.sha256); psx cc1 self-id "GNU C 2.7.2 [AL 1.1,
  MM 40] Sony Playstation"
- Makefile: check-env (.ONESHELL bash) asserts python>=3.12, venv import splat, both
  cc1 (stdin smoke), maspsx, mipsel as/ld/objcopy, sha1(EXE)==EXPECTED_EXE_SHA1;
  binutils>=2.38 -> WARN (verdict deferred to Phase 5, §4.5); extract/build/check/
  expected/clean are loud-failing Phase-5 stubs (names per §6.3)
- docs/SETUP.md: as-built versions; §4.7 corrected (i386, flat-tarball fix); §4.8
  deferred to Phase 6; ledger #5 confirmed (Ubuntu 24.04.4), #6 (2.42), #7 (sha256)
- MILESTONE: make check-env exits 0; zero ROM-derived bytes staged
- bumps project version 1.3.1 -> 1.4.0
This commit is contained in:
Drew T
2026-06-14 03:56:07 -06:00
parent 3207d52491
commit ffe2352db2
10 changed files with 297 additions and 10 deletions
+5 -1
View File
@@ -31,7 +31,11 @@
# Toolchain downloads & caches (not source)
/.venv/
__pycache__/
/tools/bin/
# Compiler binaries are ignored (regenerable downloads); the committed *.sha256
# checksum record is re-included so a fresh clone can verify its download (sotn
# pattern). Contents-exclude form (not /tools/bin/) so the !re-include can apply.
/tools/bin/*
!/tools/bin/*.sha256
/tools/psyq*/
/tools/pcsx-redux/
*.tar.gz
+12
View File
@@ -0,0 +1,12 @@
[submodule "tools/maspsx"]
path = tools/maspsx
url = https://github.com/mkst/maspsx.git
[submodule "tools/asm-differ"]
path = tools/asm-differ
url = https://github.com/simonlindholm/asm-differ.git
[submodule "tools/m2c"]
path = tools/m2c
url = https://github.com/matt-kempster/m2c.git
[submodule "tools/decomp-permuter"]
path = tools/decomp-permuter
url = https://github.com/simonlindholm/decomp-permuter.git
+130
View File
@@ -0,0 +1,130 @@
# Makefile — Brave Fencer Musashi decompilation (SLUS-00726, USA)
# =============================================================================
# Phase 4 deliverable. The ONLY live target is `check-env` (the Phase-4
# milestone: toolchain preflight). The split/build/check/expected/clean targets
# have their NAMES fixed here per docs/SETUP.md §6.3, but are loud-failing stubs
# until Phase 5 implements them. Run builds natively from the ext4 clone (H2/R2).
# =============================================================================
SHELL := /bin/bash
.ONESHELL:
.DEFAULT_GOAL := help
# --- paths & tooling ---------------------------------------------------------
PYTHON := python3
VENV := .venv
VENV_PY := $(VENV)/bin/python
MIPS_PREFIX := mipsel-linux-gnu-
AS := $(MIPS_PREFIX)as
LD := $(MIPS_PREFIX)ld
OBJCOPY := $(MIPS_PREFIX)objcopy
CC1_PSX := tools/bin/gcc-2.7.2-psx/cc1
CC1_CDK := tools/bin/gcc-2.7.2-cdk/cc1
MASPSX := tools/maspsx/maspsx.py
EXE := extracted/retail/SLUS_007.26
# cc1 smoke flags — the §5.4 first-candidate set; the real triple is pinned only
# after Phase-6 fingerprinting. Used here purely to prove cc1 executes.
CC1_SMOKE_FLAGS := -quiet -O2 -G0 -mips1 -mcpu=3000 -mgas -msoft-float -fgnu-linker
# binutils regression line (docs/SETUP.md §4.5): >= 2.38 is a WARN (PS1-matching
# regression suspect; 2.35 known-good). The verdict is revisited in Phase 5.
BINUTILS_WARN_MAJOR := 2
BINUTILS_WARN_MINOR := 38
.PHONY: help check-env extract build check expected clean
# -----------------------------------------------------------------------------
help:
@echo "BFM-decomp — make targets:"
echo " make check-env Phase-4 toolchain preflight (the only live target)"
echo " make extract [Phase 5] splat split -> asm/ + linker scripts"
echo " make build [Phase 5] full pipeline -> build/us/SLUS_007.26 (+ SHA1 check)"
echo " make check [Phase 5] standalone SHA1 verification"
echo " make expected [Phase 5] snapshot build/us -> expected/ (asm-differ baseline)"
echo " make clean [Phase 5] remove build output"
# -----------------------------------------------------------------------------
# check-env: assert every Phase-4 toolchain component. Runs ALL checks (does not
# stop at the first failure) so the report is complete, then exits nonzero if any
# hard check failed. binutils >= 2.38 is a WARN, never a FAIL (§4.5).
check-env:
@fail=0
echo "== BFM-decomp environment preflight (Phase 4 check-env) =="
echo
# 1) Python >= 3.12 (system python3 drives tooling + the EXE-hash import)
pyver=$$($(PYTHON) -c 'import sys; print("%d.%d" % sys.version_info[:2])' 2>/dev/null)
if $(PYTHON) -c 'import sys; raise SystemExit(0 if sys.version_info[:2] >= (3,12) else 1)' 2>/dev/null; then
echo "[PASS] python3 $$pyver (>= 3.12)"
else
echo "[FAIL] python3 $${pyver:-not-found} (need >= 3.12)"; fail=1
fi
# 2) venv present + splat importable
if [ -x "$(VENV_PY)" ]; then
if $(VENV_PY) -c 'import splat' 2>/dev/null; then
sv=$$($(VENV_PY) -c 'import importlib.metadata as m; print(m.version("splat64"))' 2>/dev/null)
echo "[PASS] venv 'import splat' OK (splat64 $${sv:-?})"
else
echo "[FAIL] venv present but 'import splat' failed (run: $(VENV_PY) -m pip install 'splat64[mips]>=0.41.0,<1.0.0')"; fail=1
fi
else
echo "[FAIL] $(VENV_PY) missing (run: $(PYTHON) -m venv $(VENV) && $(VENV)/bin/pip install 'splat64[mips]>=0.41.0,<1.0.0')"; fail=1
fi
# 3) cc1 candidates executable — R12-clean smoke (stdin -> /dev/null, no temp file)
for cc1 in "$(CC1_PSX)" "$(CC1_CDK)"; do
if [ -x "$$cc1" ] && echo 'int _ce(){return 0;}' | "$$cc1" $(CC1_SMOKE_FLAGS) -o /dev/null 2>/dev/null; then
echo "[PASS] cc1 runs: $$cc1"
else
echo "[FAIL] cc1 not runnable: $$cc1 (see docs/SETUP.md §4.7)"; fail=1
fi
done
# 4) maspsx submodule populated
if [ -f "$(MASPSX)" ]; then
echo "[PASS] maspsx present: $(MASPSX)"
else
echo "[FAIL] $(MASPSX) missing (run: git submodule update --init)"; fail=1
fi
# 5) mipsel binutils on PATH (as / ld / objcopy)
for t in $(AS) $(LD) $(OBJCOPY); do
if command -v $$t >/dev/null 2>&1; then
echo "[PASS] $$t: $$($$t --version | head -1)"
else
echo "[FAIL] $$t not on PATH (apt install binutils-mipsel-linux-gnu)"; fail=1
fi
done
# 5b) binutils regression line: >= 2.38 -> WARN (not FAIL); §4.5
asver=$$($(AS) --version 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+' | head -1)
if [ -n "$$asver" ]; then
amaj=$${asver%%.*}; amin=$${asver##*.}
if [ "$$amaj" -gt $(BINUTILS_WARN_MAJOR) ] || { [ "$$amaj" -eq $(BINUTILS_WARN_MAJOR) ] && [ "$$amin" -ge $(BINUTILS_WARN_MINOR) ]; }; then
echo "[WARN] mipsel binutils $$asver >= 2.38 — PS1-matching regression suspect (2.35 known-good); revisit in Phase 5 (docs/SETUP.md §4.5)"
else
echo "[PASS] mipsel binutils $$asver (< 2.38)"
fi
fi
# 6) committed EXE hash == EXPECTED_EXE_SHA1 (reused constant; fresh-clone-safe)
if [ -f "$(EXE)" ]; then
want=$$($(PYTHON) -c 'from tools.bfm_extract.extract_exe import EXPECTED_EXE_SHA1 as h; print(h)' 2>/dev/null)
got=$$(sha1sum "$(EXE)" | cut -d' ' -f1)
if [ -n "$$want" ] && [ "$$got" = "$$want" ]; then
echo "[PASS] $(EXE) sha1 $$got == EXPECTED_EXE_SHA1"
else
echo "[FAIL] $(EXE) sha1 $${got:-none} != expected $${want:-unknown}"; fail=1
fi
else
echo "[FAIL] $(EXE) missing (committed retail EXE)"; fail=1
fi
echo
if [ "$$fail" -ne 0 ]; then
echo "check-env: FAIL — see the [FAIL] lines above."
exit 1
fi
echo "check-env: OK — Phase-4 toolchain ready."
# -----------------------------------------------------------------------------
# Phase-5 targets: names fixed now (docs/SETUP.md §6.3), implemented in Phase 5.
# Loud-failing no-op stubs — never a silent exit 0 (would falsely read as success).
extract build check expected clean:
@echo "make: target '$@' is a Phase-5 target — not implemented yet."
echo " (Its name is fixed now per docs/SETUP.md §6.3; Phase 5 implements it.)"
exit 1
+21 -9
View File
@@ -16,11 +16,11 @@ All components run inside WSL2 Ubuntu 24.04 (single ext4 clone). The "Side" colu
| ghidra_psx_ldr | release 2026.06.04 (`ghidra_12.1_PUBLIC_20260604_ghidra_psx_ldr.zip`) | WSL2 (Linux) | 1 |
| PCSX-Redux | Linux build (AppImage/flatpak; no version pin; record build on install) | WSL2 (Linux) | 3 |
| WSL2 distro | Ubuntu-24.04 (Python 3.12 ships with it) | WSL2 (Linux) | 4 |
| splat | pip `splat64[mips]` `>=0.41.0,<1.0.0`; freeze exact version once Phase 5 is green | WSL2 (Linux) | 4 |
| splat | pip `splat64[mips]` `>=0.41.0,<1.0.0` — **as-built 0.41.0** (Phase 4); freeze exact once Phase 5 green | WSL2 (Linux) | 4 |
| Vintage compiler | decompals/old-gcc **release 0.17**: `gcc-2.7.2-psx` + `gcc-2.7.2-cdk` | WSL2 (Linux) | 4 |
| maspsx | git submodule, `mkst/maspsx` (decomp.me pins commit `874855c53f65f8fa57447e1da6bde6236dbef9d5` — reasonable default pin) | WSL2 (Linux) | 4 |
| asm-differ / m2c / decomp-permuter | git submodules (URLs in §4.6) | WSL2 (Linux) | 4 |
| binutils (mipsel) | apt `binutils-mipsel-linux-gnu` — **>=2.38 regression check required**, 2.35 known-good per open-ribbon | WSL2 (Linux) | 4 |
| binutils (mipsel) | apt `binutils-mipsel-linux-gnu` — **as-built 2.42** (Phase 4; ≥2.38 → check-env WARN, verdict deferred to Phase 5), 2.35 known-good | WSL2 (Linux) | 4 |
---
@@ -236,6 +236,8 @@ sudo apt-get update && sudo apt-get install -y \
```
> ⚠️ **binutils regression check (mandatory before trusting builds):** open-ribbon documents that `binutils-mipsel-linux-gnu >= 2.38` generated broken binaries; **2.35 is the known-good reference**. Ubuntu 24.04 ships newer binutils — **VERIFY on 24.04**: after Phase 5's first full build, if the SHA1 check mysteriously fails with correct-looking asm, suspect the assembler first (`mipsel-linux-gnu-as --version`), and pin/downgrade or build binutils 2.35 if confirmed. Record the verdict here.
>
> **As-built (Phase 4, 2026-06-14, ledger #6):** apt installed **binutils-mipsel-linux-gnu 2.42** (as/ld/objcopy all 2.42; mipsel-gcc 12.4.0). 2.42 ≥ 2.38, so `make check-env` emits a **[WARN]** (not FAIL) and the regression verdict is **deferred to Phase 5's first full build** exactly as above — no preemptive downgrade.
### §4.6 Python venv + splat + submodules
@@ -258,9 +260,11 @@ Submodules (add under `tools/`):
Pin all four (sotn precedent: blindly updating submodules breaks tooling). Note: sotn's asm-differ `--overlay` flag is **sotn-fork-specific**, not upstream — for BFM overlay diffing use upstream's `-o` object mode or port their fork later.
**As-built (Phase 4, 2026-06-14):** `.venv` created (Python 3.12.3); installed **splat64 0.41.0** (`splat64[mips]`) — deps spimdisasm 1.41.0, rabbitizer 1.16.2, PyYAML 6.0.3, colorama 0.4.6, intervaltree 3.1.0, tqdm 4.67.1; `import splat` OK. Submodule pins as adopted: maspsx `874855c5`, decomp-permuter `b44b0622` (both per the table); **asm-differ `2ad4a4a4`** and **m2c `4266cc28`** (each HEAD-at-adoption). Their pip deps are **not** installed yet (Phase 6, when first invoked); `tools/requirements-python.txt` is frozen only after Phase 5 is green.
### §4.7 Vintage compilers (old-gcc 0.17)
Linux x86-64 prebuilts from decompals/old-gcc, **release 0.17**:
Linux prebuilts from decompals/old-gcc, **release 0.17** (32-bit i386 static — see the correction below):
```bash
mkdir -p ~/bfm-decomp/tools/bin && cd ~/bfm-decomp/tools/bin
@@ -268,13 +272,17 @@ wget https://github.com/decompals/old-gcc/releases/download/0.17/gcc-2.7.2-psx.t
wget https://github.com/decompals/old-gcc/releases/download/0.17/gcc-2.7.2-cdk.tar.gz
sha256sum gcc-2.7.2-*.tar.gz # record hashes in a committed tools/bin/*.sha256 on first download,
# then verify with `sha256sum --check` on every fresh setup (sotn pattern)
tar xzf gcc-2.7.2-psx.tar.gz ; tar xzf gcc-2.7.2-cdk.tar.gz
# The 0.17 tarballs are FLAT (no top-level dir) and SHARE filenames (cc1, cpp, gcc, ...)
# -> extract each into its OWN subdir, or the second clobbers the first (Phase-4 finding):
mkdir -p gcc-2.7.2-psx gcc-2.7.2-cdk
tar xzf gcc-2.7.2-psx.tar.gz -C gcc-2.7.2-psx
tar xzf gcc-2.7.2-cdk.tar.gz -C gcc-2.7.2-cdk
```
- `gcc-2.7.2-psx` = community GCC 2.7.2 PSX build (primary candidate).
- `gcc-2.7.2-cdk` = **cygnus-2.7.2-970404**, the exact base of PsyQ 4.0/4.1's CC1PSX (added in old-gcc 0.14).
- **TBD:** the sha256 values themselves — not captured in research; record at first download.
- These are x86-64 Linux ELF binaries — they are *why* the build side must be Linux/WSL2 at all.
- **sha256 (RECORDED Phase 4, old-gcc 0.17, ledger #7):** `gcc-2.7.2-psx.tar.gz` = `500a459b3485e885a8d302cac23c2a4632f3900e03a09153f6190699fd723571`; `gcc-2.7.2-cdk.tar.gz` = `42bb0df96db11a9b5d2e23d78bdc962791f40046280d3d360da93fe5eef6f0bb`. Committed to `tools/bin/CHECKSUMS.sha256` (gitignore exception `!/tools/bin/*.sha256`); re-verify with `sha256sum --check tools/bin/CHECKSUMS.sha256`.
- **CORRECTION (Phase 4):** these are **32-bit i386 statically-linked** ELF binaries (NOT x86-64 as previously written) — they run on x86-64 WSL2 via the kernel's IA-32 emulation (verified: `cc1` smoke-compiles to MIPS asm and self-identifies as `GNU C 2.7.2 [AL 1.1, MM 40] Sony Playstation`). Still Linux-only — *why* the build side must be Linux/WSL2. As-built layout: `tools/bin/gcc-2.7.2-psx/cc1` + `tools/bin/gcc-2.7.2-cdk/cc1` (matches the §6.2 path).
### §4.8 Optional: PsyQ 4.0/4.1 binaries for arbitration (via Wine)
@@ -287,10 +295,14 @@ For byte-exact arbitration when maspsx output is in doubt, the **real** PsyQ Win
Keep these under `tools/` on ext4 (not committed); they are a tie-breaker, not the daily pipeline. (decomp.me runs these same Win32 tools under Wine for its psyq presets — the precedent that this works headless.)
> **DEFERRED to Phase 6 (Drew decision, Phase 4):** not staged in Phase 4 — fetched only if/when maspsx output is disputed during fingerprinting. Wine is not installed. The §4.8 "optional native PsyQ binaries" checkbox is consciously skipped for Phase 4.
### §4.9 `make check-env` (Phase 4 exit milestone)
Phase 4's observable milestone: a `check-env` make target that asserts every §4 component (venv + splat import, cc1 binaries executable, maspsx present, mipsel-as/ld/objcopy on PATH, python >= 3.12) and exits 0 when invoked directly in the WSL clone (see §6.1).
**As-built (Phase 4, 2026-06-14):** the root `Makefile` implements `check-env` (`.ONESHELL` bash; default goal `help`). Beyond the components above it also asserts **sha1(committed `extracted/retail/SLUS_007.26`) == `EXPECTED_EXE_SHA1`** (imported from `tools/bfm_extract/extract_exe.py` — fresh-clone-safe; the disc-walk `--verify-disc` needs the gitignored `disks/` and is intentionally NOT in check-env) and WARNs on binutils ≥ 2.38. **`make check-env` exits 0** (milestone met). `extract/build/check/expected/clean` exist as loud-failing Phase-5 stubs (names fixed per §6.3).
---
## §5 Compiler candidate ladder (Phase 6 fingerprinting)
@@ -457,9 +469,9 @@ A Track-1 match proves the dump is the canonical redump dump, which transitively
| 2 | MCP `types`/`struct` resolution of attached-archive (.gdt) types | **RESOLVED 2026-06-13** — import (`resolve()`) the .gdt types into the program headlessly (`tools/ghidra_scripts/ImportPsyqGdt.java`); MCP `types` then resolves them fully (§2.5 step 5) |
| 3 | GhidrAssistMCP struct-tool ergonomics under matching-decomp load | **UNPROVEN** — psxrecomp never exercised heavy struct creation |
| 4 | PCSX-Redux web-server port config field (8080 collision) | **RESOLVED 2026-06-13** — `pcsx.json` → `emulator.Debug.WebServer=true` + `emulator.Debug.WebServerPort=8081`; dump at `GET http://127.0.0.1:8081/api/v1/cpu/ram/raw` (verified 2 MB; EXE-in-RAM byte-match) |
| 5 | WSL distro is Ubuntu 24.04 (the single all-in-WSL host) | confirm via `/etc/os-release` (§4.1); username no longer load-bearing (no `wsl.exe --cd` targets) |
| 6 | binutils ≥2.38 regression on Ubuntu 24.04's shipped binutils | **VERIFY** (§4.5; 2.35 known-good per open-ribbon) |
| 7 | sha256 hashes of old-gcc 0.17 tarballs | **TBD** record at first download (§4.7) |
| 5 | WSL distro is Ubuntu 24.04 (the single all-in-WSL host) | **CONFIRMED 2026-06-14 (Phase 4)** — `/etc/os-release` = Ubuntu 24.04.4 LTS (VERSION_ID 24.04) |
| 6 | binutils ≥2.38 regression on Ubuntu 24.04's shipped binutils | **AS-BUILT 2.42 recorded (Phase 4)**; `make check-env` WARNs (not FAIL); empirical verdict still deferred to Phase 5's first full build (§4.5) |
| 7 | sha256 hashes of old-gcc 0.17 tarballs | **RECORDED 2026-06-14 (Phase 4)** — psx `500a459b…`, cdk `42bb0df9…` in `tools/bin/CHECKSUMS.sha256` (§4.7) |
| 8 | `gp_value` in SLUS_007.26 header → -G0 vs -G8 | **TBD** (§5.3) |
| 9 | ASPSX tier for game code: 2.56 vs 2.67 | **OPEN** — Phase 6 empirical (§5.2 tell) |
| 10 | Cross-OS networking | **N/A under all-in-WSL** — MCP is local loopback (§4.2); no mirrored mode, firewall rule, or host-IP discovery |
+123
View File
@@ -0,0 +1,123 @@
# PhaseEnd — Phase 4: Matching-build toolchain (WSL)
**Date:** 2026-06-14 · **Project Version:** 1.4.0 · **Phase Status:** Complete
## Build Log
**Files created/changed and complete — do not recreate:**
- `Makefile` — **new**, repo root. The live target is **`check-env`** (the Phase-4 milestone preflight):
`.ONESHELL` bash, default goal `help`. Asserts python ≥ 3.12, venv `import splat`, both cc1 candidates
(R12-clean stdin smoke), `tools/maspsx/maspsx.py`, the three mipsel binutils (as/ld/objcopy), and
**sha1(committed `extracted/retail/SLUS_007.26`) == `EXPECTED_EXE_SHA1`** (imported from
`tools/bfm_extract/extract_exe.py` — no magic literal). binutils ≥ 2.38 → **[WARN]**, not FAIL (§4.5).
`extract/build/check/expected/clean` are **loud-failing no-op stubs** (names fixed per §6.3; Phase 5
implements them). Consumed by: the daily build (Phase 5 extends this file).
- `.gitmodules` — **new**; 4 submodules under `tools/`.
- `tools/maspsx`, `tools/asm-differ`, `tools/m2c`, `tools/decomp-permuter` — **new** submodule gitlinks
(pinned, see Verification). Their working-tree *contents* are gitignored-by-submodule (a fresh clone
runs `git submodule update --init`).
- `tools/bin/CHECKSUMS.sha256` — **new, committed**; sha256 of the two old-gcc 0.17 tarballs. The ONLY
thing committed out of the otherwise-ignored `tools/bin/`. Verify with `sha256sum --check`.
- `.gitignore` — **modified**: `/tools/bin/` → `/tools/bin/*` + `!/tools/bin/*.sha256` (contents-exclude
form so the checksum record commits while all compiler binaries/tarballs stay ignored).
- `docs/SETUP.md` — **modified**: as-built versions (binutils 2.42, splat 0.41.0 + deps, gcc tarball
sha256, submodule pins, check-env); **§4.7 corrected** (cc1 is 32-bit i386 not x86-64; flat-tarball →
per-subdir extraction fix); §4.8 deferred-to-Phase-6 note; ledger **#5/#6/#7 resolved**; pin-summary
splat/binutils rows updated.
- `phase-ends/CURRENT_PHASE.md` — **absorbed into this file and deleted** (P8).
- `phase-ends/PhaseEnd_Phase4.md` — this file.
**Local artifacts (gitignored / outside the repo — present on this machine, do NOT recreate; a fresh clone redoes them):**
- `.venv/` — Python 3.12.3 venv. Recreate: `python3 -m venv .venv && .venv/bin/pip install 'splat64[mips]>=0.41.0,<1.0.0'`.
- `tools/bin/gcc-2.7.2-psx/` + `tools/bin/gcc-2.7.2-cdk/` — old-gcc 0.17 prebuilts (32-bit i386 static
`cc1`/`cc1plus`/`cpp`/`gcc`/`g++`) + the two `.tar.gz`. Recreate per the corrected §4.7.
- Submodule working trees under `tools/{maspsx,asm-differ,m2c,decomp-permuter}` — `git submodule update --init`.
**Tools/packages installed:**
- **apt:** build-essential (make 4.3, g++ 13.3.0), **binutils-mipsel-linux-gnu 2.42** + cpp/gcc-mipsel-linux-gnu
12.x, python3-pip 24.0, python3-venv (3.12), ninja-build 1.11.1, libelf-dev, clang-format 18, p7zip-full,
bchunk, bsdmainutils (curl/wget/unzip/git/coreutils already present, ensured).
- **venv (pip):** splat64 0.41.0; deps spimdisasm 1.41.0, rabbitizer 1.16.2, PyYAML 6.0.3, colorama 0.4.6,
intervaltree 3.1.0, tqdm 4.67.1.
- **downloaded (gitignored):** old-gcc 0.17 `gcc-2.7.2-psx.tar.gz` + `gcc-2.7.2-cdk.tar.gz`.
**Verification results (literal):**
- **MILESTONE — `make check-env` → exit 0:** `[PASS]` python3 3.12; venv `import splat` (splat64 0.41.0);
cc1 runs `tools/bin/gcc-2.7.2-psx/cc1` **and** `…-cdk/cc1`; maspsx present; mipsel `as`/`ld`/`objcopy`
all 2.42; `extracted/retail/SLUS_007.26` sha1 `143dbb89f34491258bbc27810d0a12ec8b43a8dd` ==
`EXPECTED_EXE_SHA1`. Plus `[WARN]` mipsel binutils 2.42 ≥ 2.38. `check-env: OK`.
- `git submodule status`: **maspsx `874855c5` ✓**, **decomp-permuter `b44b0622` ✓** (both pinned per the
table), asm-differ `2ad4a4a4` (HEAD@adoption), m2c `4266cc28` (HEAD@adoption).
- `sha256sum --check tools/bin/CHECKSUMS.sha256`: **both OK** — psx `500a459b…`, cdk `42bb0df9…`.
- cc1 binaries are **32-bit i386 statically-linked** ELF (run via IA-32 emulation); psx cc1 smoke emits
`GNU C 2.7.2 [AL 1.1, MM 40] Sony Playstation` + valid MIPS asm; psx/cdk cc1 are **distinct** (different
sha256 — the naive flat extraction would have silently kept only one).
- **Hygiene:** `git add tools/bin/` stages **only** `CHECKSUMS.sha256`; `git status` shows **zero
ROM-derived/binary bytes** would stage (`.venv`, compiler binaries, `.tar.gz` all ignored). bare `make`
→ help; `make extract` → loud fail (`make: *** Error 1`).
- Ubuntu 24.04.4 LTS confirmed (ledger #5).
- **Nothing committed** (R8): all work is staged/untracked and uncommitted, awaiting Drew's phase-end commit.
**Milestone achieved:** `make check-env` exits 0 in the WSL ext4 clone — both cc1 candidates execute and
emit MIPS asm, splat imports in the venv, the mipsel binutils are present, and the committed `SLUS_007.26`
sha1 equals `EXPECTED_EXE_SHA1` — the matching-build toolchain is stood up and self-verifying.
**Next:** Phase 5 — splat config + build skeleton (all-asm byte-match). Start with `config/splat.us.exe.yaml`
authored (section boundaries iterated until a clean link), `config/symbols.us.txt` already seeded from
Phase 3. (Phase 5 RE-reads gp_value for -G0/-G8, ledger #8; implements the Makefile's stub targets.)
## Deviations
| Item | Plan | Actual | Reason |
|---|---|---|---|
| cc1 architecture | "x86-64 Linux ELF" (§4.7) | **32-bit i386 statically-linked** | old-gcc 0.17 ships i386 binaries; run on x86-64 via IA-32 emulation; §4.7 corrected |
| old-gcc extraction | `tar xzf psx ; tar xzf cdk` flat (§4.7) | per-subdir `-C gcc-2.7.2-{psx,cdk}` | tarballs are flat **and** share filenames → flat extraction clobbers psx with cdk; §4.7 command fixed |
| check-env "dump hash" | disc-level implied by milestone | sha1(committed EXE) == `EXPECTED_EXE_SHA1`, reused constant | fresh-clone-safe (disc-walk needs gitignored `disks/`); reuses existing code (no magic literal) |
| cc1 liveness check | "cc1 runs (--version)" | trivial **stdin** compile | gcc-2.7.2 cc1 rejects `--version`; stdin→/dev/null compile is the real test, and R12-clean (no temp file) |
| §4.8 native PsyQ binaries | optional Phase-4 checkbox | **deferred to Phase 6** | Drew decision; tie-breaker only if maspsx output is disputed during fingerprinting |
| submodule pip deps + requirements freeze | implied by "installed" | **deferred** (Phase 6 / after Phase-5 green) | milestone names only splat/cc1/maspsx/binutils; avoids polluting the to-be-frozen `requirements-python.txt` |
| binutils version | 2.35 known-good target | **2.42 installed + WARN**, verdict deferred | §4.5 mandates deferral to Phase 5's first full build; Ubuntu 24.04 ships 2.42 |
| Makefile scope | check-env only (milestone) | check-env + Phase-5 target **name stubs** | §6.3 fixes the names now; loud-failing stubs prevent a silent false-success build |
## Commit Message
```
feat(phase-4): matching-build toolchain (WSL) — make check-env green
- apt: build-essential, binutils-mipsel-linux-gnu 2.42 (+gcc-mipsel 12.x), ninja
1.11.1, python3-pip/venv, libelf-dev, clang-format, p7zip, bchunk, bsdmainutils
- .venv + splat64 0.41.0 ([mips]: spimdisasm 1.41.0, rabbitizer 1.16.2, PyYAML 6.0.3)
- 4 pinned submodules under tools/: maspsx@874855c5, decomp-permuter@b44b0622,
asm-differ@2ad4a4a4, m2c@4266cc28 (.gitmodules)
- old-gcc 0.17 cc1 candidates -> tools/bin/gcc-2.7.2-{psx,cdk}/ (32-bit i386 static;
tarballs are flat + same-named -> per-subdir extraction); CHECKSUMS.sha256 committed
(gitignore exception !/tools/bin/*.sha256); psx cc1 self-id "GNU C 2.7.2 [AL 1.1,
MM 40] Sony Playstation"
- Makefile: check-env (.ONESHELL bash) asserts python>=3.12, venv import splat, both
cc1 (stdin smoke), maspsx, mipsel as/ld/objcopy, sha1(EXE)==EXPECTED_EXE_SHA1;
binutils>=2.38 -> WARN (verdict deferred to Phase 5, §4.5); extract/build/check/
expected/clean are loud-failing Phase-5 stubs (names per §6.3)
- docs/SETUP.md: as-built versions; §4.7 corrected (i386, flat-tarball fix); §4.8
deferred to Phase 6; ledger #5 confirmed (Ubuntu 24.04.4), #6 (2.42), #7 (sha256)
- MILESTONE: make check-env exits 0; zero ROM-derived bytes staged
- bumps project version 1.3.1 -> 1.4.0
```
## Rules Added This Phase
| Rule | Reason |
|---|---|
| **None** | Phase 4's findings are *deviations / doc-corrections* (cc1 is i386 not x86-64; the flat-tarball extraction trap; binutils 2.42 WARN; §4.8 deferral), not governance rules. **Noted practice (not elevated to a rule):** build/preflight targets should be *fresh-clone-safe* and *reuse single-source constants* (no magic literals, no gitignored deps) — applied in `check-env` (imports `EXPECTED_EXE_SHA1`, hashes the committed EXE). Elevate later if Phase 5's build targets benefit. |
## PhaseEnd Changelog
**v1.3.1 → v1.4.0** — Phase 4 complete. The matching-build toolchain is stood up and self-verifying in the
WSL ext4 clone: the apt cross-toolchain (binutils-mipsel **2.42**), a Python 3.12 venv with **splat64
0.41.0**, four pinned submodules (maspsx/asm-differ/m2c/decomp-permuter), and the old-gcc 0.17 cc1
candidates (`gcc-2.7.2-psx` + `gcc-2.7.2-cdk`) — all asserted by a new **`make check-env`** target that
**exits 0**. Two SETUP.md corrections caught by the bytes: the cc1 prebuilts are **32-bit i386** (not
x86-64), and the 0.17 tarballs are **flat & same-named** so each must extract into its own subdir. binutils
2.42 is WARN-flagged with the regression verdict **deferred to Phase 5's first build** (§4.5). Ledger
#5/#6/#7 resolved; §4.8 native-PsyQ arbitration deferred to Phase 6; submodule pip deps + requirements
freeze deferred. **No new rules.** Next: Phase 5 (splat config + all-asm byte-match).
## 🛑 Stop Here
PhaseEnd written; `CURRENT_PHASE.md` absorbed and removed. **Drew commits AND pushes** this PhaseEnd
(R6/R8 — the single Phase-4 commit lands everything: Makefile, .gitmodules, submodule gitlinks,
tools/bin/CHECKSUMS.sha256, .gitignore, docs/SETUP.md, PhaseEnd_Phase4.md). Start a **fresh session for
Phase 5 — splat config + build skeleton**. Keep this file forever.
+1
Submodule tools/asm-differ added at 2ad4a4a4f7
+2
View File
@@ -0,0 +1,2 @@
500a459b3485e885a8d302cac23c2a4632f3900e03a09153f6190699fd723571 gcc-2.7.2-psx.tar.gz
42bb0df96db11a9b5d2e23d78bdc962791f40046280d3d360da93fe5eef6f0bb gcc-2.7.2-cdk.tar.gz
Submodule
+1
Submodule tools/m2c added at 4266cc2817
Submodule
+1
Submodule tools/maspsx added at 874855c53f