mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 22:45:39 -04:00
3207d52491
- extract_proto_exe.py: subdir-aware proto main-EXE extraction (reuses iso9660); extracted
sep8 SLUS_007.26 (413,696 B) + aug31 MUSASHI/USA_DEMO.EXE (415,744 B, base 0x80018000)
- ghidra_import.sh: reusable headless import; both protos imported into the bfm project
(sep8 1726 funcs, aug31 1737 funcs, both PsyQ 4.0.0), R9-verified
- DumpFunctionSignatures.java + match_protos.py: 3-tier (exact/norm/seq) cross-binary
correspondence; MIPS normalizer validated by anchors
- FINDINGS: (T2) no debug symbols in either proto — Hidden Palace "no symbols" VERIFIED;
recon "Sep-8 less-stripped" REFUTED by per-file byte compare. (T3) Sep-8 99.6% byte-identical
to retail (only 3 funcs differ: DebugMenuHandler, CdReadSectorReadyCB, SaveLoadRoutine);
Aug-31 66% norm-identical, 862 1:1 correspondences. (T4) demo shares retail's 18-entry
game-mode dispatch architecture but the handler code diverged — Q#10 resolved
- VERDICT (docs/proto-correspondence.md): NO-GO as a Gen1 label/symbol accelerator; GO to retain
Sep-8 (Phase-6 compiler corroborant) + both (Gen2 assets); proto-side labels in
config/symbols.proto-{sep8,demo}.txt (R13-tagged, never feed symbols.us.txt)
- reorg extracted/ into per-ROM subfolders (extracted/retail/, extracted/proto/); nested
gitignore allowlist; extractor defaults updated; manifest --verify PASS
- memory-map.md: Phase-3.5 block + demo dispatch anchors; Q#10 RESOLVED; §5 proto notes VERIFIED
- ghidra_mcp_start.sh: PROG arg to serve a prototype
- rules R13 (proto-provenance/confidence tagging), R14 (verify recon counts vs bytes)
- bumps project version 1.3.0 -> 1.3.1
138 lines
12 KiB
Markdown
138 lines
12 KiB
Markdown
# PhaseEnd — Phase 3.5: Prototype Research Spike
|
||
**Date:** 2026-06-14 · **Project Version:** 1.3.1 · **Phase Status:** Complete
|
||
|
||
> Inserted half-phase (Drew's directive at Phase-3 close): assess whether the two CRC-verified US
|
||
> prototypes accelerate Gen1 matching, **before** the build toolchain (which resumes as Phase 4).
|
||
> Filename uses an underscore (`Phase3_5`) so the glob load order sorts Phase3 → Phase3_5 → Phase4.
|
||
|
||
## Build Log
|
||
|
||
**Files created/changed and complete — do not recreate:**
|
||
- `tools/bfm_extract/extract_proto_exe.py` — extract a main EXE from a prototype disc; reuses the general
|
||
`iso9660` reader, `--dir` for subdirectories (the demo's real EXE is in `MUSASHI/`), magic-only
|
||
validation (proto sizes/SHA1s differ from retail). Companion to the retail-locked `extract_exe.py`.
|
||
- `tools/ghidra_import.sh` — reusable headless import of any PS-X EXE into the `bfm` project (PSX-loader
|
||
auto-detect → auto-analysis incl. PsyQ signatures + DetectPsyQ → PsyQ-4.0 types via `ImportPsyqGdt.java`
|
||
→ `DumpProgramInfo.java`). Precondition: MCP server stopped (exclusive project lock).
|
||
- `tools/ghidra_scripts/DumpFunctionSignatures.java` — **read-only** per-function 3-tier fingerprint
|
||
(`h_exact` raw bytes / `h_norm` MIPS-normalized / `h_seq` mnemonic-only) + ordered call targets →
|
||
`.run/sig.<prog>.jsonl`. Consumed by `match_protos.py`.
|
||
- `tools/match_protos.py` — cross-binary correspondence: per-tier counts, 1:1 unique `h_norm` pairs,
|
||
anchor sanity check; emits `config/symbols.proto-*.txt`. Consumes the `.run/sig.*.jsonl` dumps.
|
||
- `docs/proto-correspondence.md` — **the deliverable**: the evidence-backed go/no-go report.
|
||
- `config/symbols.proto-sep8.txt` (953) / `config/symbols.proto-demo.txt` (682) — retail names mapped onto
|
||
the protos via 1:1 `h_norm` correspondence. **R13-tagged: proto-side, UNVERIFIED, never merge into
|
||
`config/symbols.us.txt`.** Phase-6/Gen2 navigation aid.
|
||
- `docs/memory-map.md` — added the **Phase-3.5 block** (proto correspondence summary + DEMO dispatch
|
||
anchors), resolved **Open Q#10**, upgraded §5 proto notes ("no symbols") to **VERIFIED**.
|
||
- `.gitignore` — nested allowlist for `extracted/retail/` (3 committed files re-included); `extracted/proto/`
|
||
fully ignored.
|
||
- `tools/bfm_extract/extract.py` · `extract_exe.py` · `crosscheck.py` — DEFAULT output/extracted paths
|
||
→ `extracted/retail` (per-ROM subfolders).
|
||
- `tools/ghidra_mcp_start.sh` — `PROG` now `${1:-SLUS_007.26}` (serve a prototype by passing its name).
|
||
- **Renamed (git mv, history preserved):** `extracted/{SLUS_007.26,manifest.jsonl,manifest.sha1}` →
|
||
`extracted/retail/` (the extracted/ reorg; the 34 gitignored bulk items moved alongside).
|
||
|
||
**Local artifacts (gitignored / outside the repo — present on this machine; a fresh clone redoes them):**
|
||
- `extracted/proto/sep8_SLUS_007.26` (413,696 B, sha1 `43006a314513d962528ddc90ee496c781867366a`) +
|
||
`extracted/proto/aug31_USA_DEMO.EXE` (415,744 B, base 0x80018000, sha1
|
||
`6150b0f839972ac52214e3510e7d7f0e2c194624`) — extracted proto main EXEs.
|
||
- Ghidra `bfm` project now holds **3 programs**: `SLUS_007.26` (retail) + `sep8_SLUS_007.26` (1726 funcs)
|
||
+ `aug31_USA_DEMO.EXE` (1737 funcs); all PsyQ 4.0.0; R9-verified. (The retail DB was NOT modified.)
|
||
- `extracted/retail/` bulk (the Phase-2 disc extraction, moved here); `.run/sig.*.jsonl` ×3,
|
||
`.run/correspondence.*.tsv` ×2, `.run/proto-import.log` — scratch.
|
||
|
||
**Tools/packages installed:** None (used the existing Ghidra 12.1 + Python stack).
|
||
|
||
**Verification results (literal):**
|
||
- **Proto extraction:** sep8 `SLUS_007.26` 413,696 B, sha1 `43006a31…`; aug31 `USA_DEMO.EXE` 415,744 B,
|
||
base 0x80018000, sha1 `6150b0f8…`; both `PS-X EXE` magic verified. `extracted/` reorg: `extract.py
|
||
--verify --out extracted/retail` **PASS** (manifest paths are out_root-relative → move transparent);
|
||
git shows 3 renames; **zero ROM bulk staged**.
|
||
- **Ghidra import:** sep8 **1726 funcs / PsyQ 4.0.0**, aug31 **1737 funcs / PsyQ 4.0.0**; both
|
||
`Import succeeded` + **R9-verified** by read-only re-open.
|
||
- **T2 (debug-info):** main EXEs string-identical (retail=sep8=351, aug31=331; only `\DEBUG.BIN;1` +
|
||
`SetGraphDebug`); disc-wide retail/sep8 debug-string-identical (`_dbg_RE1L@55`, `C:\TIMPACK\` in **both**;
|
||
`DEBUG`-substrings retail 63 / sep8 59 = garbage). **No symbols in any proto — Hidden Palace claim
|
||
VERIFIED; the recon "Sep-8 less-stripped" signal REFUTED.**
|
||
- **T3 (correspondence, substantial ≥8 ins):** sep8 h_exact **99.4%** / h_norm **99.7%** / h_seq 99.7%,
|
||
1072 1:1 pairs; aug31 h_exact 16.0% / h_norm **65.9%** / h_seq 99.0%, 690 1:1 (862 all sizes). Normalizer
|
||
validated by anchors (`LzssDecodeSector`, `CdReadRequest` matched across the demo's shift+rebuild).
|
||
Sep-8→retail pre-release diff = exactly **3 substantial funcs** (`DebugMenuHandler`,
|
||
`CdReadSectorReadyCB` 424 ins, `SaveLoadRoutine`).
|
||
- **T4 (anchor):** demo dispatch table @0x8006AE8C = **18 entries** (= retail's 18, same idx[10]==idx[15]
|
||
duplicate); demo `GameModeDispatch` 0x80018b48, `gameMode` 0x800c1eb6; slot **[7]** 0x800194cc (= retail
|
||
`DebugMenuHandler` slot, **code diverged**). **Q#10 resolved.**
|
||
- **T6:** `config/symbols.proto-sep8.txt` 953 names, `config/symbols.proto-demo.txt` 682 names, R13-tagged.
|
||
|
||
**Milestone achieved:** `docs/proto-correspondence.md` states an evidence-backed go/no-go — **SPLIT:
|
||
NO-GO** as a Gen1 label/symbol accelerator (no symbols in either proto, *verified* by byte compare; the
|
||
free-label lead refuted), **GO** to retain Sep-8 (Phase-6 compiler-determinism corroborant; 99.6%
|
||
byte-identical, 3-function pre-release diff) and both (Gen2 assets) — backed by a per-proto debug-info
|
||
inventory, quantified retail↔proto correspondence (Sep-8 99.6% / Aug-31 66% norm, 862 1:1), and the
|
||
Aug-31 anchor alignment (18-entry dispatch table located, slot[7] mapped) resolving Q#10; proto-side
|
||
labels imported (`config/symbols.proto-*.txt`).
|
||
|
||
**Next:** Phase 4 — Matching-build toolchain (WSL). Start with: apt toolchain + Python 3.12 venv +
|
||
splat64 installed; submodules (asm-differ, m2c, maspsx, decomp-permuter) added and pinned.
|
||
|
||
## Deviations
|
||
| Item | Plan | Actual | Reason |
|
||
|---|---|---|---|
|
||
| Spike outcome | open (free-label lead hypothesized "GO") | NO-GO for Gen1 accel; GO only as asset | Bytes refuted the symbol/label hypothesis (T2); protos have FEWER names than retail's 952 |
|
||
| `extracted/` layout | single `extracted/` root | reorganized → `extracted/retail/` + `extracted/proto/` | Drew directive mid-phase (multiple ROMs now); inserted cleanup task |
|
||
| T6 lift direction | name protos **and** annotate retail w/ proto provenance | one-way retail→proto only; **retail untouched** | verdict: protos add nothing retail lacks → nothing to annotate; preserves crown-jewel DB (G6) |
|
||
| T6 application | apply names in the Ghidra proto programs + export | `config/symbols.proto-*.txt` only; **Ghidra-side naming deferred** | premature given NO-GO (protos are future assets); the text file is the durable record |
|
||
| T2 xref step | map debug strings → functions via MCP | moot — no new debug strings exist in any main EXE | negative finding; nothing to map |
|
||
| Recon debug signal | (4th explore agent: "Sep-8 = GO, strong") | refuted | naive disc-wide grep counted coincidental `X:\`/`DEBUG` byte sequences (→ R14) |
|
||
| `BfmVtExactMatch.java` (Version Tracking) | available for T6 on GO | not created/needed | correspondence computed in Python; the bounded lift needs no Ghidra writes |
|
||
| MCP for the spike | live MCP for xref/anchor | mostly standalone read-only `analyzeHeadless` | lock-serialized + avoids `/mcp` re-attach churn; only one decompile needed |
|
||
|
||
## Commit Message
|
||
```
|
||
feat(phase-3.5): prototype research spike — go/no-go (protos don't accelerate Gen1 matching)
|
||
|
||
- extract_proto_exe.py: subdir-aware proto main-EXE extraction (reuses iso9660); extracted
|
||
sep8 SLUS_007.26 (413,696 B) + aug31 MUSASHI/USA_DEMO.EXE (415,744 B, base 0x80018000)
|
||
- ghidra_import.sh: reusable headless import; both protos imported into the bfm project
|
||
(sep8 1726 funcs, aug31 1737 funcs, both PsyQ 4.0.0), R9-verified
|
||
- DumpFunctionSignatures.java + match_protos.py: 3-tier (exact/norm/seq) cross-binary
|
||
correspondence; MIPS normalizer validated by anchors
|
||
- FINDINGS: (T2) no debug symbols in either proto — Hidden Palace "no symbols" VERIFIED;
|
||
recon "Sep-8 less-stripped" REFUTED by per-file byte compare. (T3) Sep-8 99.6% byte-identical
|
||
to retail (only 3 funcs differ: DebugMenuHandler, CdReadSectorReadyCB, SaveLoadRoutine);
|
||
Aug-31 66% norm-identical, 862 1:1 correspondences. (T4) demo shares retail's 18-entry
|
||
game-mode dispatch architecture but the handler code diverged — Q#10 resolved
|
||
- VERDICT (docs/proto-correspondence.md): NO-GO as a Gen1 label/symbol accelerator; GO to retain
|
||
Sep-8 (Phase-6 compiler corroborant) + both (Gen2 assets); proto-side labels in
|
||
config/symbols.proto-{sep8,demo}.txt (R13-tagged, never feed symbols.us.txt)
|
||
- reorg extracted/ into per-ROM subfolders (extracted/retail/, extracted/proto/); nested
|
||
gitignore allowlist; extractor defaults updated; manifest --verify PASS
|
||
- memory-map.md: Phase-3.5 block + demo dispatch anchors; Q#10 RESOLVED; §5 proto notes VERIFIED
|
||
- ghidra_mcp_start.sh: PROG arg to serve a prototype
|
||
- rules R13 (proto-provenance/confidence tagging), R14 (verify recon counts vs bytes)
|
||
- bumps project version 1.3.0 -> 1.3.1
|
||
```
|
||
|
||
## Rules Added This Phase
|
||
| Rule | Reason |
|
||
|---|---|
|
||
| **R13 — Proto-provenance & confidence tagging.** Every prototype/cross-build-derived datum carries source build (`sep8`/`demo`/…), match tier (`exact`/`norm`/`fuzzy`), and verification status (`verified-retail` only if independently confirmed in retail; else `unverified`). `config/symbols.us.txt` and the curated retail Ghidra DB receive ONLY `verified-retail` data; unverified proto-derived names live exclusively in `config/symbols.proto-*.txt` + reports (never merged into `symbols.us.txt`); retail comments carrying proto info are prefixed `[PROTO:… UNVERIFIED]`. | Drew directive 2026-06-14: keep the deferred full-lift safe and never corrupt the crown-jewel symbol list with uncertain cross-build data. Extends G5/G6. |
|
||
| **R14 — Verify recon/sub-agent summary counts against the bytes.** A sub-agent's or reconnaissance pass's summarized counts/signals are claims, not ground truth; confirm against the actual bytes before relying on them. | A recon "Sep-8 is less-stripped (strong GO signal)" was a false positive — coincidental `X:\`/`DEBUG` byte sequences in compressed data — refuted by per-file byte comparison. Extends G1/X2. |
|
||
|
||
## PhaseEnd Changelog
|
||
**v1.3.0 → v1.3.1** — Phase 3.5 (inserted prototype research spike) complete. Both US prototypes extracted,
|
||
imported (PsyQ 4.0.0), and diffed against retail via a new read-only 3-tier signature pipeline. **Go/no-go:
|
||
the prototypes do NOT accelerate Gen1 matching** — neither carries symbols/debug-info/labels retail lacks
|
||
(*verified*; the demo's scene-select shares retail's 18-mode dispatch *architecture* but its handler code
|
||
diverged and is unnamed, so the "free labels" lead is refuted). They are **retained** as a Phase-6
|
||
compiler-determinism corroborant (Sep-8 = 99.6% byte-identical to retail; the entire pre-release delta is 3
|
||
functions) and Gen2 assets (Aug-31 = the same engine rebuilt, SC02 region, 862 1:1 correspondences). Open
|
||
Q#10 resolved. `extracted/` reorganized into per-ROM subfolders. New reusable tooling (proto extractor,
|
||
headless importer, signature dumper + matcher). Rules R13 (proto-provenance tagging) and R14 (verify recon
|
||
vs bytes). **Deferred (Drew):** the exhaustive Version-Tracking + manual near-miss full-lift to a later phase.
|
||
|
||
## 🛑 Stop Here
|
||
PhaseEnd written; `CURRENT_PHASE.md` absorbed and removed. **Drew commits AND pushes** this PhaseEnd
|
||
(R6/R8). Start a fresh session for **Phase 4 — Matching-build toolchain**. Keep this file forever.
|