Files
BFM-decomp/docs/verification.md
T
Drew T 4f7c3b64a3 docs(phase-33): commit-map + citations resolved to the rewritten history (C4–C7 — the tip commit)
- docs/commit-map.tsv: 4,032 rows (ordinal of the ORIGINAL main -> rewritten hash, author/committer dates, subject);
  1 pruned row of zeros (ordinal 1712, "session archive update"); 0 old hashes asserted; ordinal 1 unchanged by the
  rewrite (byte-identical)
- resolve_tokens: 1,238 commit:NNNN tokens -> shortest-unique new hashes in 98 files (docs, phase-ends, logs, tool
  docstrings, 2 C comments, the A5 evidence logs); residue left as tokens: commit:1712 x4 (the pruned commit),
  commit:orphan-24 x2, commit:orphan-26, commit:orphan-35 (cited commits that exist in no lineage)
- the rewrite (C4): filter-repo 2.47.0 on a bare clone of the C2 tip, 311 s, exactly 1 pruned, main 4,032 -> 4,031;
  the pre-rewrite history is mirrored in the private archive repo and in the local bundle
- the proof (C5): verify_rewrite 4,031 pairs / 0 failures; absent_scan 0 offenders; gate_scan 0 offenders on the clone
- adoption (C6): 100 text files differ at the tip, 0 purge paths, 0 added/deleted; leftover refs dropped; no gc yet
- resolver skips tools/public_rewrite/ (its self-test fixtures are the token grammar, not citations); repo-local
  identity is the GitHub noreply address from here on; CURRENT_PHASE: C4–C7 logged, checkpoint -> NEXT = C8
2026-09-06 23:28:39 -06:00

9.2 KiB
Raw Blame History

Verify it yourself — the byte-identity contract, and how to check it with your own disc

BFM-decomp's claim is narrow and machine-checkable: 218 binaries (the main executable SLUS_007.26, the resident engine blob, 138 location overlays and 78 code modules) rebuild byte-for-byte from the C in src/, compared against the originals extracted from a redump-verified USA disc. This page is the recipe, the expected output of every step, and the record of the last full run. Nothing ROM-derived is in the repository (tools/audit_public.py guards that), so every check below that touches game bytes needs YOUR disc dump. What CI proves without a disc is at the end.

0. What you need

Item Detail
The disc Brave Fencer Musashi (USA) (SLUS-00726), redump layout: 4-track BIN/CUE. Track 1 SHA1 b44f0f0a19936f23b26188b658e13201a6a9c211, CRC32 c238191b. A Track-1-only dump also works (the 3 CD-audio tracks are then reported as unverified, never silently passed).
Linux (WSL2 Ubuntu 24.04 is what the project uses) binutils-mipsel-linux-gnu, cpp-mipsel-linux-gnu, python3.12, git, make — make bootstrap prints the exact apt line and installs the rest (venv, submodules, the tracked gcc-2.7.2 cc1 tarballs, sha256-checked).
Disk / time ≈3 GB for the build tree; the full clean rebuild takes ≈5 min on 16 cores (measured 4 m 18 s on a fresh clone, single user 45 CPU-min).

The PsyQ SDK objects are optional and never needed for byte-identity: without them the main executable links the project's own INCLUDE_ASM fallback tiles for Sony's library regions and is still byte-identical (this is the WITHOUT leg of make sdk-dual, and it is what every fresh clone builds). See docs/SETUP.md §P33 B4 if you own the SDK.

1. The recipe (R22: a CLEAN rebuild — never an incremental one)

git clone --recurse-submodules https://github.com/Druthulu/BFM-decomp.git && cd BFM-decomp
make bootstrap                    # -> "check-env: OK"  (one WARN: run make disc-extract)
mkdir -p disks && cp '/path/to/Brave Fencer Musashi (USA)'*.{bin,cue} disks/
make disc-extract                 # -> "disc-extract: OK"  (extracts the disc, compares 1,801 files to the committed manifest)
make clean && make -j"$(nproc)" extract-all && make -j"$(nproc)" check-all
                                  # -> "extract-all: 217 extracted, 0 failed of 217 (+ main, serial)"
                                  # -> "check-all: 218 passed, 0 failed of 218"     <- THE contract line
make sdk-dual                     # optional, only with the SDK objects -> "sdk-dual: OK — main 143dbb89… byte-identical WITH and WITHOUT the PsyQ objects"
make tools-health                 # -> "tools-health: OK — sigs fresh; corpus(+resident) + cdecl + binaries + report(lint+dedup) + cookbook-index all green."
make report                       # -> the three 100% lines below, "INCLUDE_ASM stubs : 0"

Every make target exits non-zero on any failure; read the exit code, not the presence of an output file (a failed build leaves the previous binary in place — rule R53). make help lists every target with one line each.

What each step proves

Step Proves Expected last line
make bootstrap the toolchain is present and pinned (cc1 tarballs sha256 500a459b… / 42bb0df9…, maspsx submodule at the pinned commit, binutils) check-env: OK
make disc-extract your disc is the redump image and extracts to the SAME 1,801 files the project was built against (extracted/retail/manifest.jsonl + .sha1, committed) disc-extract: OK (or PARTIAL: 1,798/1,798 code+data verified; 3 .DA unverified for Track-1-only)
make extract-all splat splits every binary from the extracted payloads (asm/ and the linker scripts are regenerated, never edited) extract-all: 217 extracted, 0 failed of 217 (+ main, serial)
make check-all every binary's build SHA1 equals config/check.<alias>.sha — main 143dbb89f34491258bbc27810d0a12ec8b43a8dd check-all: 218 passed, 0 failed of 218
make sdk-dual main is byte-identical both with Sony's real objects linked and with the fallback tiles sdk-dual: OK — …
make tools-health the two independent function-boundary oracles agree (0 phantom / 0 truncated / 0 pad-tail), the dedup registry validates (2,220 groups / 0 failures), the audits and derived indexes are fresh tools-health: OK — …
make report the three progress metrics, source-derived FLEET fn-count byte-ident: 363214 / 363214 = 100.00% · FLEET instr-weighted : 13492113 / 13492113 = 100.0% · FLEET distinct-code(uniq): 5820205 / 5820205 = 100.0% · MAIN game-code weighted : 45150 / 45150 = 100.0%

What is NOT our C (stated plainly)

  • 1,256 functions of the main executable are Sony's PsyQ library objects, linked byte-identical from the SDK when you have it and represented by assembly fallback tiles when you do not (src/lib*.c, src/apicard*.c — INCLUDE_ASM stubs whose bytes come from the disc). Reimplementing Sony's libraries from source is out of scope.
  • 5 functions fleet-wide are hand-written assembly in the original (config/verbatim_manifest.json, PERMANENT rows); they are kept as verbatim __asm__ bodies, audited by tools/verbatim_check.py --strict.
  • Everything else — every game-code function in all 218 binaries — is C.

2. The last recorded run

The project's own full run is recorded, log by log, under .run/P33/verify/ (tracked: NN_<step>.log, each ending in EXIT=<rc> and a timestamp, plus SUMMARY.md), produced by tools/verify_contract.sh on the committed tree. The table below is copied from that SUMMARY.md; regenerate it with the script, never by hand.

  • Tree: 3e0ecfacc (2026-09-06) · Host: Linux 6.18.33.1-microsoft-standard-WSL2, 32 CPUs, JOBS=16 · Run: 2026-09-07T03:11:58Z
# Step EXIT wall contract line
00 tree 0 1s HEAD 3e0ecfacc 2026-09-06 fix(phase-33): audit_frontier's LINKED-stub count reads the Stub records (the refer
01 check-env 0 0s check-env: OK — Phase-4 toolchain ready.
02 family-hseq 0 11s family_hseq regenerated: 217 binaries scanned, 0 open instances
03 r22-clean-fleet 0 157s check-all: 218 passed, 0 failed of 218
04 sdk-dual 0 28s sdk-dual: OK — main 143dbb89f34491258bbc27810d0a12ec8b43a8dd byte-identical WITH and WITHOUT the PsyQ objects (maps: .run/P33/verify/main_
05 tools-health 0 356s tools-health: OK — sigs fresh; corpus(+resident) + cdecl + binaries + report(lint+dedup) + cookbook-index all green.
06 audit-frontier 0 9s audit-frontier: reference = corpus.stubs over 218 binaries -> 1258 open stubs
07 audit-disc 0 36s UNCLAIMED code payloads: 0
08 report 0 211s FLEET distinct-code(uniq): 5820205 / 5820205 = 100.0% (90984/90984 unique fns; the DISTINCT-RE number)

Every NN_<step>.log is tracked under .run/P33/verify/; the tools-health log also carries sig-main-oracle: main is now INDEPENDENT — 0 in-domain stubs, 0 PHANTOM, 0 TRUNCATED, 0 PAD-TAIL and the report INCLUDE_ASM stubs : 0, Open near-misses: 0. Total wall 14 min on 32 CPUs.

The C3 preparatory commit that followed removed the ROM-derived paths from the index with git rm --cached — no tracked-content byte changed, so this run's evidence holds for that tip as well; C8 repeats the run on the rewritten tree.

The same run was performed after every banked batch of Phases 30–32 (218/218 at every one; the P32 close run is .run/P32/t4e/r22_check.log) and the history-rewrite of the public flip is followed by one more (C8) on the adopted tree — a content-preserving rewrite changes no tracked byte, and that run proves it.

3. What CI proves without the disc

.github/workflows/no-rom.yml runs on every push and pull request:

  • audits — no ROM-derived bytes, purge paths or >50 MiB files among the tracked files (tools/audit_public.py, whose ROM-hash set is derived from the committed manifest + every config/check.*.sha); every source is text with portable includes; the verbatim manifest has no drift; the derived indexes (cookbook, Ghidra roster) are fresh; the LZSS decoder's unit tests; no stale symbol references.
  • compile-only — every eligible translation unit (4,170 of 4,287; the rest are the library tiles that .include disc-derived assembly) goes through cpp → gcc-2.7.2 cc1 → maspsx → GNU as with the Makefile's exact flags. A PR compiles four representative binaries (≈1 min); the whole fleet runs weekly and on demand.

CI cannot compare bytes to the originals — that is your step 1. The two together are the full claim.

4. Reverse-engineering artifacts you can also regenerate

The Ghidra project is not in the repository (its database embeds the game's bytes). Its hand-authored content is tracked as text under config/ghidra/ (ROSTER.md lists the programs) and tools/ghidra_rebuild.sh <program> --proof rebuilds a program from your disc + the symbol files + that text and proves the result equals it (PROOF PASS). The 28 RAM images the memory map was derived from are local-only; dumps/CHECKSUMS.sha1 records their identity.