Order of work as the checklist sets it: census first, then magic scan validated by running the decompressor, then nesting, then the band.
Reproduce with
python3 tools/packscan2.py _work/iso --depth 3 → notes/packscan.txt
and python3 tools/band.py _work/iso --per-file → notes/band.txt.
python3 tools/census.py _work/iso → notes/census.txt.
First-longword histogram, 221 files:
| magic | count | what |
|---|---|---|
ATN! |
96 | Imploder |
\0\0\3\xf3 |
24 | AmigaDOS hunk |
FORM |
20 | IFF |
PaCK |
9 | not one of the eight known crunchers |
\xe3\x10 |
8 | Workbench icon |
CrM! |
2 | CrunchMania |
#--- |
5 | text (the .Man scripts) |
cd0: |
3 | the three launcher scripts |
| everything else | 54 | raw data, one file each |
P3, written before any magic was read:
After three Core Design discs the only surviving same-label regularity is the cruncher. The Speris Legacy — the other Team 17 disc — uses the Imploder (
IMP!), 35 of 47 files, 52.8 %. Prediction: Superfrog packs with the Imploder.
Correct, and by a wider margin than Speris. 96 of 221 files begin ATN!,
and the Imploder's decruncher — transcribed from The Speris Legacy's own
shipped routine, tools/speris_imp.py, reused unmodified — decodes every one of
them with ok=True, meaning the in-place pointer landed exactly on zero.
ATN! rather than Speris's IMP! is the same packer: the two magics are the
Imploder's data-file and executable forms and the same 350-byte routine reads
both. The tail layout is identical — 38 bytes carrying the initial literal run,
the initial bit buffer, eight offset bases, twelve bit widths and a checksum —
and every file on this disc carries the Imploder's default tables.
So "the cruncher follows the label" goes from 3-of-3 inside Core Design to two independent labels, with Team 17 at 2 of 2 across two studios (Superfrog is Team 17's own; Super Stardust is Bloodhouse) and three years.
158 validated Imploder streams. Validation is not structural: every one was decoded, and a hit only counts if the output length equals the declared length.
| depth | streams | packed | unpacked | factor |
|---|---|---|---|---|
| 1 | 137 | 3,285,886 | 11,988,480 | 3.65× |
| 2 | 21 | 207,228 | 782,656 | 3.78× |
P13 is wrong. The prediction was depth 0 — no stream inside a stream. There are 21 second-level streams, all of them inside the output of a first-level stream, and they are not incidental: they are the intro and the particle engine's payloads.
96 files begin with a stream; 137 streams exist at the first level; so 41 streams sit at non-zero offsets inside files, which is the concatenation form.
The checklist names three and this disc has all three.
A file that is a stream. 96 of them. SFData/L1BM is ATN!, 63,744 bytes
on disc, 134,400 out, and nothing else.
A file that is a concatenation of streams with raw gaps between them.
SuperFrog/SFIntro, 751,852 bytes, holds 27 streams. SFData/S3BO holds 6,
SABO 4, SuperFrogCD 6.
A file that is a stream whose output is a concatenation.
SFData/INTROF is one stream at offset 0; decompress it and the 268,956-byte
result contains 15 more streams. SFData/PARTF is the same shape with 6.
This is the form that a single-level unpack misses entirely, and it is where 21
of the 158 streams live.
The gaps are not padding. 32 raw runs totalling 1,080,250 bytes sit
between and around the streams — 6.2 % of the resident corpus. They are not
alignment: the largest single gap is 209,504 bytes and it is the code hunk of
the packed engine inside PARTF. Counted rather than assumed, as Gunship's 241
single-zero-byte gaps were.
Nine files in /SuperStardust/CRM begin PaCK, which is none of the eight
crunchers the set has catalogued. The header was deduced from the files, not
from a format description, and it validates on all nine:
+0 char[4] 'PaCK'
+4 UWORD 0 (zero on all nine)
+6 ULONG unpacked size
+10 ULONG packed size
+14 ... packed bytes, exactly `packed` of them
14 + packed == filesize on 9 of 9. And the disc supplies its own control:
four of the nine have a same-named sibling in RAW/, and the declared unpacked
size equals that sibling's byte count exactly in all four cases.
| file | on disc | declared unpacked | RAW/ sibling |
match |
|---|---|---|---|---|
Cargo.bob |
1,626 | 2,868 | 2,868 | yes |
Enemy02.bob |
2,700 | 3,570 | 3,570 | yes |
NEMESIS.bob |
950 | 2,208 | 2,208 | yes |
tausta1.frames(64x488) |
9,458 | 11,712 | 11,712 | yes |
TOKENpuff |
526 | 1,176 | — | |
TOKENpuffM |
216 | 392 | — | |
megablast0.bob |
534 | 852 | — | |
megablast1.bob |
402 | 708 | — | |
megablast2.bob |
208 | 480 | — |
9 files, 16,620 bytes on disc, 23,966 declared, 1.44×.
The codec is not decoded — the header is proven, the stream is not. That is
open question 3, and the honest statement is that PaCK is a ninth container
here, and a candidate ninth cruncher only once someone reads the stream.
The CRM/ and AGACRM/ directory names mean crunched, and RAW/ and
AGARAW/ are the same assets unpacked: the demo ships both forms of four
assets side by side.
Two files in /SuperStardust/AGACRM begin CrM!. The CrunchMania header
documented on the Gloom disc parses both exactly:
leeway unpacked packed 14+packed filesize
MAPMONITOR 0 61,440 18,020 18,034 18,034 ✓
MAPMONITORSCREENS 0 102,400 16,480 16,494 16,494 ✓
34,528 bytes on disc declaring 163,840 out, 4.75×.
And the inherited decoder returns a wrong negative. cd32-gloom-doc's
crm.py implements CrM2 and its CrM! branch is the literal line
raise NotImplementedError("CrM! stream: no file on the disc uses it")— a correct statement about Gloom and a false one here. Run it on this disc and
it reports 0 decrunched, 2 failed. That is the fourth time an inherited
tool with an assumption inside has produced a clean negative on the wrong disc
(after akiko.py on Universe and containers.py and audiotracks.py on
Gunship), and the checklist's rule — verify the assumption inside the tool
before writing the negative — is what caught it. The two streams remain
undecoded: open question 2.
Note what would have happened without the rule: the inherited containers.py
and unpackall.py decode only RNC method 1, and this disc has no RNC at
all, so those two report zero streams on a disc with 158. They were not used.
packscan2.py is codec-agnostic and was written for this disc.
Three figures, every one stated against a named denominator.
| Files | On disc | Resident | Used | Expansion | Slack | |
|---|---|---|---|---|---|---|
| Superfrog | 122 | 4,102,748 | 13,336,690 | 12,853,499 | 3.25× | 3.62 % |
| Super Stardust (demo) | 64 | 3,221,772 | ≥3,358,430 | 3,218,518 | ≥1.04× | 0.10 % |
| Arcade Pool (demo) | 14 | 601,518 | 645,598 | 645,582 | 1.07× | 0.002 % |
| system | 21 | 200,527 | 200,527 | 200,518 | 1.00× | 0.004 % |
| whole disc | 221 | 8,126,565 | 17,404,587 | 16,918,117 | 2.14× | 2.80 % |
Depth of unpacking: 2. Fully exhausted — a third pass finds nothing. Super Stardust's resident figure is a lower bound because the two CrM! and nine PaCK streams are declared and not decoded; adding their declared sizes gives ≥3,358,430. Superfrog's figure has no such caveat: every container in its tree decoded.
P5 predicted the band would hold, by route (a) "the disc barely compresses" or (c) "the expansion factor is at the bottom of the scale". Both are wrong. Superfrog expands 3.25×, the second-highest factor in the set after Dragonstone's 3.78×, and well above the 1.58× that the arithmetic said was the break-even.
What saves the on-disc reading is route (b), the one the prediction ranked last: 49.5 % of this disc is not Superfrog. Strip the two demos and the system files and the game is 4.10 MB on disc, comfortably inside the 2.25–13.3 band.
The resident reading does not survive:
Superfrog resident 13,336,690
Marvin, previous maximum 13,251,697
excess +84,993 bytes = +0.64 %
So the resident band's ceiling is broken, by 0.64 %, and the on-disc band's is not. The two readings now return different verdicts about the same disc.
That is the honest way to state it, and it matters more than picking the louder half. The checklist already says the band is coherent only as an on-disc measurement, because Banshee and Dragonstone are 6 % apart on disc and 80 % apart unpacked. Superfrog is the first disc where following that rule changes the answer rather than merely tidying it: on-disc says "inside", resident says "new maximum", and both are correctly computed. Keep them separate, quote the denominator, and do not average them.
A caveat that belongs with the number rather than in a footnote: "resident"
means bytes after every container is expanded, which is a property of the
corpus, not of peak RAM. SFIntro alone accounts for 3,290,454 resident bytes
and the game plainly does not hold all of them at once. The figure is
comparable across discs because it is defined the same way for all of them; it
is not a memory-footprint claim.
Resident minus used, where "used" is bytes up to the last non-zero byte of each resident piece. The checklist asks for the number, for the per-file view, and for no third hypothesis. All three:
Whole disc 2.80 %. Superfrog alone 3.62 %. That puts it between Banshee (3.9 %) and Universe (0.5 %) and makes it the sixth point on the scale, which now runs Gunship 0.004 %, Fire & Ice 0.3 %, Universe 0.5 %, Superfrog 3.6 %, Banshee 3.9 %, Dragonstone 9.1 %.
Per file, the slack is not spread evenly — it is concentrated, as it was on Universe:
| file | resident | used | slack | % |
|---|---|---|---|---|
SFData/LWMS |
26,880 | 10,222 | 16,658 | 61.97 % |
SFData/L4MS |
26,880 | 13,426 | 13,454 | 50.05 % |
SFData/LBMA |
53,588 | 31,988 | 21,600 | 40.31 % |
SFData/S2BO |
204,800 | 167,034 | 37,766 | 18.44 % |
SFData/LWMA1 |
53,588 | 47,149 | 6,439 | 12.02 % |
SFData/L3MS |
26,880 | 23,664 | 3,216 | 11.96 % |
SFData/S1BO |
204,800 | 182,011 | 22,789 | 11.13 % |
SFIntro |
3,290,454 | 3,095,105 | 195,349 | 5.94 % |
SFData/S3BO |
1,229,178 | 1,171,408 | 57,770 | 4.70 % |
And the reason the per-file view is worth taking is visible in it directly:
every MS file unpacks to exactly 26,880 bytes and every MA file to exactly
53,588, regardless of content. Seven and twenty-four files respectively, all
landing on the same two numbers to the byte. These are fixed-size buffers, and
the slack is the unused tail of a fixed allocation — which is the checklist's
"expect fixed sizes, packed or not" observation showing up as the dominant term
in the slack figure rather than as a side note.
No third hypothesis is offered. The number is 3.62 % for the game, it is concentrated in fixed-size level buffers, and that is the finding.
SFData/INTROC unpacks to 101,528 bytes. SFIntro has a raw gap at offset
650,256 that is 101,596 bytes. Align them and the second contains the first
starting 56 bytes in, with 99.9576 % of 101,528 bytes identical — 43 bytes
differ.
So roughly 101 KB of intro payload exists twice on the disc, once as a standalone packed file and once inside the intro executable, in two builds that differ in 43 bytes. Byte-identical duplication is zero on this disc (01); near-identical duplication inside containers is not, and it is only visible after unpacking.