Disc coverage
How much of the game's own bytes the project can account for, measured against the disc rather than against the project's own notes. This is where the two byte-denominated figures on the landing page come from.
Why this exists alongside the port catalog
The port catalog tracks three status columns — dumped, documented, ported — over the set of addresses this project cites. That is the right instrument for steering work, and it answers "what is left on the list". It cannot answer "how much of the game is left", because its denominator is the citation graph: a subsystem nobody has cited is invisible to it, and the page can read as near-complete while that subsystem sits outside the measurement entirely.
The distinction is not academic. Against the citation graph the dump corpus reads as effectively closed — zero cited-but-not-dumped addresses. Against the executable's own bytes, roughly a sixth of SCUS_942.54's code is not inside any dumped function at all.
The two halves measure different things
This is the one thing to carry away before quoting a figure from this page.
| Kind | What a percentage means | |
|---|---|---|
| Code | byte-exact | a byte is inside a dumped function, or it is not |
| Data | format recognition | an entry's format class is known; its bytes are not individually accounted for |
The data figure is an upper bound. Knowing an entry is a VAB stream is not the same as consuming every byte inside it, and no parser in the tree reports consumed-versus-unconsumed bytes yet. Closing that gap — having each parser return its consumed extent — is what would put the data half on the same footing as the code half.
How code coverage is computed
Every Ghidra dump header carries an entry address and a byte length, so the dumped functions are real intervals over an image's address space. The tool merges them, subtracts them from the image's extent, and is left with the genuinely un-dumped remainder.
That remainder is then split into code and data, because a PS-X EXE's text segment carries its read-only data inside the same span, and counting string tables and jump tables as "un-decompiled code" would understate coverage badly. Each gap is classified statistically over its whole length: the share of words decoding to a plausible MIPS I opcode, and the density of 0x80xxxxxx words that betrays a pointer table.
The classifier is checked against a control. A region known to be code profiles at about 94% plausible opcodes and near-zero pointer density; the large gaps reported as code match that signature, while the head of the segment (87% printable ASCII, 48% plausible) does not.
Dumps that report 0 instructions and carry only decompiled C are excluded — such a dump is not evidence that its bytes are understood.
Why overlay rows can read "not meaningful"
SCUS_942.54 is the only image with an unambiguous answer: one load image, one fixed base, no aliasing.
Overlays are different. Several are loaded at the same base address, so a dump whose entry lands in that band cannot be attributed to one image by address alone — the same address belongs to the battle overlay, the menu overlay and the field overlay at different moments. Attributing by address counts a dump once for every image whose span contains it.
Rather than publish a number that quietly double-counts, each overlay row carries the share of its extents that could not be placed. Above 50% the coverage figure is replaced by not meaningful, and such rows are excluded from the ratchet baseline: a figure that moves with attribution rather than with real coverage would produce failures nobody can act on. That is also why the landing page's decompilation bar quotes the executable alone.
Where the bytes can settle it, they do. A companion sweep disassembles each extracted overlay at its recovered base and asks which images actually hold a dump's bytes at the address it prints; the per-extent verdict is committed and the gate applies it. An extent the bytes place in another image leaves the row entirely instead of inflating it, an extent whose bytes live nowhere at the printed address is credited to nobody, and only what the disassembly window cannot sign stays ambiguous. Most of what used to be counted against the two measured overlays belonged to images the gate does not measure at all.
One shape does not yield to that. Where one measured span lies wholly inside another, every extent in the inner one falls in both by construction, so most of what it loses is loss to the outer image and the same residue is a much larger share of what remains. That is structural rather than a corpus gap: no amount of dumping moves it, and forcing a figure would mean asserting the residue belongs to the inner image when nothing in the bytes says so.
The ambiguity share counts distinct extents, not dump files — one extent can back dozens of dumps, and weighting by how often the same bytes happened to be dumped measures the corpus rather than the image. That is also the key the committed verdict file uses, so the report and the artifact read directly against each other.
Gate behaviour
Both inputs — the Ghidra dump corpus and the extracted disc tree — are gitignored, so a clone without disc data has nothing to measure. The tool exits 0 and reports SKIPPED in that case, following the same skip-and-pass convention as the rest of the repo's disc-gated tests. CI therefore passes without disc data, and the ratchet only has teeth on a machine that has the disc.
Coverage may only go up, within a tolerance of half a percentage point, checked against a committed baseline. If a dump is legitimately removed, the baseline is refreshed explicitly and the commit message has to say why — a baseline moving down is a claim that needs a reason.
A useful side effect: the report lists the largest un-dumped code runs in the executable by size. That is a dump worklist derived from the bytes rather than from what anyone happened to cite — the one worklist the citation graph structurally cannot produce.
Tool: scripts/ci/disc-coverage.py. The landing-page figures are refreshed by scripts/ci/update-progress-metrics.py and committed, because the site is built where the disc is not.