mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-26 13:33:34 -04:00
176 lines
13 KiB
Markdown
176 lines
13 KiB
Markdown
# Disc-completeness audit (Phase-27 T7)
|
||
|
||
> **Generated 2026-07-15.** Reproduce: `tools/disc_code_sweep.py` (committed). The question this
|
||
> answers is the one the whole-binary byte-gate is structurally blind to (R34): `make check-all` only
|
||
> touches binaries someone ONBOARDED, so a code payload nobody onboarded is invisible to it however
|
||
> green the fleet is. This reconciles the ONBOARDED set against every code-bearing payload ON THE DISC.
|
||
|
||
## What the disc holds (extracted PAC payloads, by type)
|
||
|
||
`extracted/retail/**` holds **1189** raw PAC payloads across 8 types (`docs/formats.md`):
|
||
|
||
| type | payloads | code-bearing | onboarded | note |
|
||
|---|---|---|---|---|
|
||
| 0 | 301 | 0 | 0 | data (graphics/blobs) |
|
||
| 1 | 166 | **40** | 1 | **resident-class code modules** — the resident is one; 39 more are NOT onboarded |
|
||
| 2 | 201 | 0 | 0 | data (decodes ~100% "valid" but 0% `jr $ra` — the false-positive class) |
|
||
| 3 | 201 | 0 | 0 | data |
|
||
| 4 | 138 | 138 | **138** | location overlays — **COMPLETE** (134 at PAC entry 0 + 4 SC07 at entry 1) |
|
||
| 6 | 29 | 0 | 0 | data |
|
||
| 7 | 139 | 0 | 0 | data |
|
||
| 8 | 14 | 0 | 0 | data |
|
||
|
||
**Code detection (`disc_code_sweep.py`):** decode the first 4096 words as MIPS-LE (reusing
|
||
`sig_image.make_insn`, GTE-aware) and require BOTH `valid ≥ 0.90` AND `jr $ra` density `≥ 0.01`.
|
||
The `jr $ra` gate is decisive: `isValid()` alone is far too permissive (structured type-0/type-2 data
|
||
decodes ~100% valid), but real MIPS code carries a `jr $ra` roughly once per function — **2.9–3.4%** of
|
||
words across the onboarded overlays + the resident, versus **0.000%** for the data blobs. Validated
|
||
against positive controls (`SC01/077/0.4.dec` 3.39%, resident `MAIN/FILE_010/1.1` 2.91%) and negative
|
||
controls (type-2 `0.00%`, type-0 `0.00%`).
|
||
|
||
## The finding
|
||
|
||
**Type-4 (location overlays) is complete.** All 138 type-4 payloads are onboarded and build
|
||
byte-identical. The 4 that were invisible for a month — `ov_SC07_{006,007,010,011}` — put graphics at
|
||
PAC entry 0 and the code overlay at entry 1 (`1.4.dec`); `new_overlay.sh` hardcoded `0.4.dec`. They are
|
||
now onboarded (byte-verified: `7ca772be`, `b3b95547`, `d7b5875d`, `9885af74`). **Fleet: 136 → 140.**
|
||
|
||
**Type-1 holds 39 additional, un-onboarded code modules.** These are resident-class code (the resident
|
||
`MAIN.CD/FILE_010/1.1` is the one already onboarded), the largest being `MAIN/FILE_027` (1318 w),
|
||
`FILE_036` (1229 w), `FILE_028` (1115 w). Full ranked list: `.run/disc_code_sweep.txt` (regenerate with
|
||
the tool). They are **NOT location overlays** — they do not load at the shared slot `0x80128158`; each
|
||
loads at its own address, the way the resident loads at `0x800CEDF8`. So — unlike the SC07 overlays —
|
||
**they cannot be onboarded mechanically:** a build binary needs its load address to byte-verify (P9), and
|
||
that address is only knowable by runtime RE (a PCSX-Redux RAM-dump proof, the Phase-3 method). Onboarding
|
||
them is a Gen2 RE task, deferred with this evidence — NOT a false "complete" while code sits unbuilt.
|
||
|
||
> **⚠️ 2026-08-06 (S44): the "only knowable by runtime RE" sentence above is REFUTED.** The load
|
||
> addresses are **static** for 46 of the 78 unclaimed payloads: the EXE's `loadDestPtrTable`
|
||
> (0x80072C70) + the boot loaders' literal `&cdFileLocTable[k]` operands + two index tables INSIDE the
|
||
> resident (`D_800D3764` → slot A 0x800CAE08 for MAIN/13…41; `D_800D384C` → slot B 0x800CCB1C for
|
||
> MAIN/42…47) + `src/resident/resident.c:641` (MAIN/12 → the standard overlay slot 0x80128158) + the
|
||
> SC07 pair's own headers (→ 0x801A00D8). Full routing table with provenance:
|
||
> **`docs/memory-map.md` §"Phase 30 S44"**. Independently corroborated by h_exact base voting (~500:1)
|
||
> and jal-alignment voting. The genuinely runtime-only remainder is the 28 SC0x script modules +
|
||
> MAIN/7, MAIN/9, SC02/9 — parked for L3 with evidence. Additional corrections from the same pass:
|
||
> the three biggest "modules" (MAIN/12, SC02/37, SC03/107) are **ordinary overlays stored uncompressed**
|
||
> (PAC type 1 = raw overlay, type 4 = LZSS overlay); the 78 ledger rows sum **3,406,325 B** (the
|
||
> bucket's 3,564,021 additionally counts PAC headers); `MAIN/7` is a raw file (`FILE_007`, not
|
||
> PAC-wrapped); `MAIN/0 ≡ MAIN/1` byte-identical; payload word0 is a global module id (resident=0x36).
|
||
|
||
## Consequence for the completion contract (roadmap §1)
|
||
|
||
The contract's binary count is **no longer "136"**. Two corrections:
|
||
1. **140 binaries onboarded now** (main + resident + 138 overlays) — the number `check-all` verifies.
|
||
2. **⚠️ SUPERSEDED 2026-08-06 by `make audit-disc` — the real backlog is 78 payloads / 3.56 MB, not 39.**
|
||
The "39" below came from `disc_code_sweep`, which reads only the RAW layer through a **4,096-word
|
||
window** and has no notion of a *claim*. The L1+L2 disc audit walks the disc image, classifies
|
||
**whole** payloads at **both** layers, derives `claimed-by` from `config/check.<bin>.sha`, and unions
|
||
two independent oracles: **78 unclaimed code payloads, 3,564,021 bytes**, across MAIN.CD (42),
|
||
SC03 (18), SC05 (7), SC04 (7), SC07 (2), SC02 (2). Verified against the old list: **all 39 are still
|
||
un-onboarded** (0 of 39 claimed), so the new number strictly contains the old one. The audit asserts
|
||
a **residue-0 partition** over all 416,021,760 disc bytes, so this figure is a floor with a proof
|
||
rather than a sample. Live list: `docs/disc-ledger.md`. The paragraph below is kept for provenance.
|
||
|
||
2. *(superseded)* **A documented backlog of 39 type-1 code modules** pending load-address RE before they can be
|
||
onboarded and counted. Game-code TRUE 100% (the contract's bar) is only honest once these are either
|
||
onboarded-and-matched or explicitly excluded with a reason. They are recorded here so the "100%"
|
||
claim cannot be made while they sit un-onboarded and unexamined (R34 — the byte-gate cannot see them).
|
||
|
||
**This is a re-baselining event, expected to LOWER the headline %** (the 4 SC07 overlays add ~2.45 MB of
|
||
mostly-unmatched code to the denominator; every "×134" family propagation is now "×138"). That is the
|
||
honest direction — the prior number was measured over an incomplete disc.
|
||
|
||
## S45 (2026-08-06): the module campaign landed — the residue IS the parked-for-L3 ledger
|
||
|
||
**43 of the 78 unclaimed payloads now build byte-identical** (P30 S44/S45): the 3 uncompressed
|
||
overlays (`ov_MAIN_012`, `ov_SC02_037`, `ov_SC03_107`) + the 38 MAIN modules (slot A
|
||
`md_MAIN_013…041` @0x800CAE08 · slot B `md_MAIN_042…047` @0x800CCB1C · boot trio `md_MAIN_001`
|
||
[≡MAIN/0, stored twice] / `md_MAIN_008` / `md_MAIN_011` @0x800CEDF8) + the SC07 pair
|
||
(`md_SC07_003/004` @0x801A00D8) — every address static-derived (§S44 loader table,
|
||
`docs/memory-map.md`) and byte-corroborated by a first-build byte-identity. Fleet = **183
|
||
binaries**, `make audit-disc` residue 0.
|
||
|
||
**The remaining UNCLAIMED = 34 payloads = the parked-for-L3 exclusion list** (the 100% claim
|
||
cites exactly this list, roadmap §1.1):
|
||
- the **28 SC0x script modules** (SC03/73–79, SC03/132–138, SC04/24–30, SC05/23–29 = 7 modules ×
|
||
4 per-disc builds) — bases loader-determined per-disc via the resourceIdMap/DESTPTR path;
|
||
- **SC02/9** (70,784 B), **MAIN/7** (raw file, not PAC), **MAIN/9**;
|
||
- **SC03/53, SC03/54, SC03/56** (6,616 / 8,220 / 3,680 B) — *added S45:* three SC-disc type-1
|
||
rows the S44 exploration never tiered; same per-disc runtime-routing class as SC02/9. Their
|
||
jal-vote bases are low-confidence; onboarding on a guess would be P9 theater.
|
||
|
||
Resolution path: the **L3 emulator tour** (P31 bucket T) logs every load (payload → RAM addr →
|
||
len), delivering the 34 bases + R34-verification of the static addresses + evidence for any
|
||
never-loaded payload's out-of-scope call.
|
||
|
||
## S45 addendum (2026-08-07): the L3 tour ran — 29 of the 34 onboarded; parked = 6
|
||
|
||
The debug-menu tour (`docs/memory-map.md` §S45; menu list `docs/debug-menu-list.txt`) delivered:
|
||
- **All 28 script modules captured live and onboarded byte-identical** (`md_SC03_073…079`,
|
||
`md_SC03_132…138`, `md_SC04_024…030`, `md_SC05_023…029` at the four byte-verified per-chapter
|
||
slots). The interior↔module routing law is in memory-map §S45.
|
||
- **MAIN/3 DISCOVERED and onboarded** (`md_MAIN_003` — the main-menu module, id 0x39, live
|
||
byte-proven at 0x800CEDF8). It had been mis-bucketed `classified-data` by BOTH oracles — the
|
||
low-jr module class evades the L1 heuristic AND L2's carve. The **module-id census** (word0 ∈
|
||
id-range + early prologue, run disc-wide) found **77 id-law code payloads, 72 claimed + 5
|
||
parked, zero further misses** — that census is the third oracle for this class.
|
||
- **SC03/55 verdict: DATA, confirmed** (id-like word0 0x42 but zero prologues and zero `jr $ra`
|
||
in 7,988 B; it is the data companion of modules 0x40/0x41/0x43).
|
||
- **Fleet: 183 → 212 binaries.** `make audit-disc`: **UNCLAIMED = 6, residue 0.**
|
||
|
||
**S45 part 3:** SC02/9 fell too — captured live at the 1ST-BOSS arena (0x801E4C60),
|
||
retro-verified by the Phase-3 `ram_castle.bin` dump (same address, 2026-06-14), onboarded as
|
||
`md_SC02_009`. **Fleet: 213. The parked ledger is now 5 payloads** (MAIN/7, MAIN/9,
|
||
SC03/53/54/56) — reclassified from "emulator targets" to **static-RE targets** (their loaders
|
||
are individual + condition-gated; see memory-map §S45 part 3 for the decoded leads).
|
||
|
||
**The prior 6-payload framing (kept for provenance):**
|
||
|
||
**The parked-for-L3 ledger is (superseded) 6 payloads**, each with byte-checked negative evidence from the
|
||
tour (never present in RAM across boot/title/attract/menus/load/opening/endings/game-over and ~15
|
||
scene loads): **MAIN/7, MAIN/9, SC02/9, SC03/53, SC03/54, SC03/56.** Next tier: the CD-read
|
||
tracer (log `cdFileLocTable` index per read during play), not further scene-guessing.
|
||
|
||
## P32 T2 (2026-09-05): the parked ledger is EMPTY — all five payloads onboarded, `make audit-disc` UNCLAIMED = 0
|
||
|
||
The five static-RE targets the S45 addendum left (MAIN/7, MAIN/9, SC03/53, SC03/54, SC03/56) are binaries:
|
||
|
||
| payload | binary | base | TEXT_LO | base evidence (memory-map §S45 p7) | first build |
|
||
|---|---|---|---|---|---|
|
||
| MAIN/7 (raw `FILE_007`, 9,600 B, id 0x3A, OPDEMO0) | `md_MAIN_007` | 0x800CEDF8 (boot slot) | 0x34 | STRONG: 9/9 self-calls + 14/16 pointers on its own function starts | `2ff702b6…` |
|
||
| MAIN/9 (`FILE_009.dir/0.1`, 2,544 B, id 0x2D, OPDEMO1) | `md_MAIN_009` | 0x800CD348 (inside slot B's region, +0x82C) | 0x3C | STRONG: 6/6 self-calls + 9/9 pointers on starts at exactly one base | `d270f695…` |
|
||
| SC03/53 (6,616 B, id 0x40) | `md_SC03_053` | 0x801EF468 (ov_SC03_001's DESTPTR) | 0x4 | STRONG: 52/75 pointers inside, 3 + its one self-call on starts | `c0848f30…` |
|
||
| SC03/54 (8,220 B, id 0x41) | `md_SC03_054` | 0x801EF468 | 0xF0 | STRONG: 106/115 pointers inside, 5 header fn-ptr entries on starts | `06bd73df…` |
|
||
| SC03/56 (3,680 B, id 0x43) | `md_SC03_056` | 0x801CBB50 (ov_SC03_002's DESTPTR) | 0x4 | 15/17 pointers inside; an outward call to a function only ov_SC03_002 (+2) has | `bc768a6b…` |
|
||
|
||
`make audit-disc` (2026-09-05, `.run/P32/t2b/close.log`): **UNCLAIMED code payloads: 0** — "0 UNCLAIMED of 220"
|
||
(`docs/disc-ledger.md`); `make audit-binaries` 218/218 citizens; R22 218/218 byte-identical.
|
||
|
||
**How the bases were derived — and what the first build does NOT prove.** `tools/payload_base_evidence.py`
|
||
(controls-gated: seven banked modules re-derive their byte-proven bases from their payloads alone, 7/7) scores a
|
||
bounded candidate list — the five §S44 slots, the 134 IDXTAB DESTPTRs, and a jal→function-start vote — on
|
||
self-calls and fn-ptr-table entries landing exactly on the module's own function starts (starts = prologues ∪ the
|
||
word after each `jr $ra`+delay; leaf functions have no prologue). The all-`INCLUDE_ASM` **first build is a NULL
|
||
oracle for FINE base errors**: MAIN/7 builds byte-identical at base+8, and only a gross error (an internal `jal`
|
||
leaving the window) fails — as a LINK error, not a hash (`.run/P32/t2b/control_{fine,full}.log`). So the §S44 line
|
||
"byte-identical on its FIRST build at the derived address" corroborated the address CLASS, never the address; every
|
||
base here is `static-derived STRONG` (G5) and is byte-PROVEN by the first C bank whose body calls an internal sibling —
|
||
20 such banks landed the same session (T2c: twin remaps + constant flips across all five modules, every build
|
||
byte-identical), which is that proof for md_MAIN_007 (func_800CF390 calls func_800CF3B0), md_SC03_053
|
||
(func_801EF56C calls func_801858CC) and the others whose remapped bodies address their own data.
|
||
|
||
**What this closes.** The 100% claim's explicit-exclusion list is empty: every code-bearing payload on the disc (220
|
||
of 220 classified code payloads) is an onboarded, byte-identical binary. What remains is per-function work inside
|
||
the binaries (the census), not scope.
|
||
|
||
## Reproduce
|
||
> **⚠️ S45: `tools/disc_code_sweep.py` is RETIRED (R33)** — superseded by `make audit-disc`
|
||
> (`tools/disc_audit.py`): whole-payload classification at BOTH the raw and LZSS layers, a
|
||
> residue-0 partition over the disc, and `claimed-by` derived from `config/check.<bin>.sha`.
|
||
> The commands below are kept for provenance of the 2026-07-15 findings; they no longer run.
|
||
```
|
||
tools/disc_code_sweep.py # (retired) the table above + the ranked hidden list
|
||
tools/disc_code_sweep.py --types 1 # (retired) just the type-1 code modules
|
||
```
|