A path that names its own archive is a free name->key fact, since a pak TOC holds only hashes. Swept them disc-wide and aimed the result at the 2D / GP_READY_ROOM blocker. Seven fields carry a game: value - BackGroundPackage 18, StageResourcePackage 23, TBL_3D 6, LodEnumTable 7, MotionEnumTable 7, one PATH, one anonymous - giving 63 distinct paths in two forms: 42 file-form (41 present on the extracted ISO, the single miss being the bare directory game:\hidden\Resource3D\, which is not a file) and 21 archive+entry (20 of 20 resolve inside the archive they name; the 21st is sound.pak+ with an empty entry). The blocker test is a measured zero. The six 2D paks and GP_READY_ROOM hold 1817 distinct keys between them and NONE is named by a + path. The dictionary's total reach is 20 of 16630 keys, 0.12%, and every one lands in DefTables or GP_HANGAR_ARSENAL - archives that are already partly named. The route is exhausted rather than unlucky: these paths exist only in the seven fields above, and none of those fields ever addresses a 2D or ready-room asset. The blocker keeps its earlier structural reason (six identical 711-key TOCs, 0 of 711 shared with any other archive). The full dictionary is recorded: 6 x <lang>\GP_HANGAR_ARSENAL_3D.tbl in GP_HANGAR_ARSENAL.pak, and EnumGameModel_* plus EnumLODSet_* for S24, S26, S27, S28, S29, Tutorial and test in DefTables.pak. Left unexplained: both DefTables families are seven names with S25 absent and no story stage present at all. All fifteen artefacts byte-identical.
331 lines
17 KiB
Markdown
331 lines
17 KiB
Markdown
# ✅ Which archives the disc can name — and the two it cannot
|
||
|
||
The previous pass found that **0 of 419** in-game HUD config paths hash to a pak
|
||
entry ([hud-config](hud-config.md)). Chasing more prefixes would have been the
|
||
same mistake twice, so this censuses the whole disc instead: harvest **every**
|
||
plausible asset-name string from **every** archive, hash each under the 16 known
|
||
path prefixes, and ask per archive **what fraction of its TOC that explains**.
|
||
|
||
`idxd-container.md` and `idxd-tag-hash.md` own the hash (`name_hash` = a
|
||
checksum byte over a 24-bit modular value, case-insensitive, distinct from
|
||
`tag_hash`); neither says which archives are *reachable* by it. Artefact
|
||
`../data/archive-naming.txt`, regenerator `tools/re-capture/archive_naming.py`
|
||
(**6 027** candidate names × 16 prefixes).
|
||
|
||
## The result is bimodal
|
||
|
||
| archive | entries | named | |
|
||
|---|---:|---:|---|
|
||
| `GP_TITLE`, `GP_PAUSE_MENU`, `GP_STAGE_CLEAR`, `GP_CHALLENGE`, `GP_MOVIE_THEATER`, `GP_GAMEOVER`, `GP_BUNK`, `GP_SYSTEM`, `GP_TUTORIAL`, `MiscBin`, `fonts` | 2–151 | **all** | **100 %** |
|
||
| `tables.pak` | 79 | 78 | 98.7 % |
|
||
| `GP_DIALOG` | 140 | 139 | 99.3 % |
|
||
| `deu/eng/esp/fra/ita/jpn.pak` | 117 | 115 | 98.3 % |
|
||
| `GP_SAVE_LOAD` / `GP_LEADERBOARD` / `GP_OPTIONS` / `GP_MISSION_LOG` | 24–108 | | 91–94 % |
|
||
| `GP_MAIN_GAME_{D,E,F,I,J,S}` | 1 119 | 751 | 67.1 % |
|
||
| `GP_DEBRIEFING_PILOTLOG` | 234 | 78 | 33.3 % |
|
||
| `GP_HANGAR_ARSENAL` | 1 538 | 347 | 22.6 % |
|
||
| `DefTables` | 1 465 | 130 | 8.9 % |
|
||
| `GP_MISSION_SELECT` | 88 | 22 | 25.0 % |
|
||
| **`GP_READY_ROOM`** | **1 106** | **6** | **0.5 %** |
|
||
| **`GP_MAIN_GAME_{D,E,F,I,J,S}2D`** | **711** each | **0** | **0.0 %** |
|
||
| `sound.pak` | 9 519 | 1 | 0.0 % (a separate format — [sound-pak-contents](sound-pak-contents.md)) |
|
||
|
||
🔑 **The six 2D paks are at exactly 0.0 %, all six, 711 entries each** — while
|
||
eleven menu paks are at 100 % by the same method in the same run. That is the
|
||
control that makes it a finding rather than a failed guess: the method works, and
|
||
these archives are outside it.
|
||
|
||
🔑 **`GP_READY_ROOM` is a second such archive** — 1 106 entries, **6** named.
|
||
Not previously noted anywhere in `docs/re/`; it is the largest UI pak on the
|
||
disc and its names are as unreachable as the 2D paks'.
|
||
|
||
## ✅ The sweep now says WHICH entry, not just how many (2026-08-27)
|
||
|
||
The percentages above were the whole output for a long time, and that hid
|
||
something: the sweep had **already named** the 24 `StageParameter_S<NN>.tbl`
|
||
objects that a later iteration "discovered" — they were in the 6 027-candidate
|
||
set from the start. Nobody could tell, because the artefact only reported
|
||
`GP_MAIN_GAME_E … 751 named, 67.1 %`.
|
||
|
||
`archive_naming.py` now also emits, per archive, the **resolved name families**
|
||
(digits collapsed to `#`) with counts — **6 573 named entries, 1 631 families
|
||
across the disc**. That turns the statistic into a content index; the
|
||
`GP_MAIN_GAME_E` head is
|
||
|
||
```
|
||
x28 EnumUnit_S#.tbl x28 StageResource_S#.tbl
|
||
x28 FormationSet_S#.tbl x28 UnitGroup_S#.tbl
|
||
x28 Route_S#.tbl x22 AIParams_S#.tbl
|
||
x22 StageParameter_S#.tbl x22 UnitMessageSet_S#.tbl …212 families
|
||
```
|
||
|
||
**Method lesson, paid for twice now:** a coverage percentage is not a name table.
|
||
If a sweep can name a thing, make it *say* the name, or the next reader will
|
||
redo the work.
|
||
|
||
⚠️ Determinism: the resolved map is built by iterating the candidate set, so it
|
||
is now iterated **sorted** — a plain `set` gave a different winner for collided
|
||
hashes on each run and the artefact failed its own byte-identical check.
|
||
|
||
## ✅ What the `GP_MAIN_GAME_*` unnamed block is — 333 of 337 already owned (2026-08-27)
|
||
|
||
Every language copy carries the **identical** 337 unnamed IDXD hashes (6/6). By
|
||
record-name shape (53 shapes), classified against the corpus:
|
||
|
||
| | objects | owner |
|
||
|---|---:|---|
|
||
| weapon datasheets (`Shell+Weapon` ± `ShellWake`/missile params) | **131** | `weapon-datasheet-static.md` |
|
||
| unit datasheets (`…Maneuver…StructureCount` + turrets/bridges) | **114** | `unit-datasheet-static.md` |
|
||
| unit `Faces` tables | 64 | `unit-datasheet-static.md` |
|
||
| unit message sets (`Generic+Message_000…`) + `MessageSet_test` | 10 | `preset-message-rules.md` |
|
||
| chatter rule tables (`ATTACK_SUCCEEDED…`) | 8 | `preset-message-rules.md` |
|
||
| `EnumUnit` ×2, `EnumWeapon`, formations, placement/route-test, asteroid groups | 5 | `stage-mission-tables.md` etc. |
|
||
| **unclassified** | **4** | → [`player-tuning-tables.md`](player-tuning-tables.md) |
|
||
|
||
🔑 **The 114 unit datasheets are exactly the corpus's 114 units** (43 `Craft` +
|
||
71 `Vessel`). These objects were never undiscovered data — they are the tables
|
||
the corpus has always worked with, reached **by record shape because they have
|
||
no names**. Naming them adds nothing; only the 4 unclassified ones were new.
|
||
|
||
⚠️ **The `Enumerate` object in each `GP_MAIN_GAME_*` is EMPTY** — zero fields,
|
||
declaring nothing. It is a shipped placeholder, and it is why route 2 named
|
||
1 283 entries in `DefTables` and **0** here.
|
||
|
||
## ✅✅ ROUTE 2 — the `Enumerate` declaration tables close `DefTables` (2026-08-27)
|
||
|
||
The string harvest could never name `DefTables`, because **those names are not
|
||
spelled out as `something.tbl` anywhere on the disc**. They are declared instead.
|
||
|
||
🔑 **An IDXD object whose single record is named `Enumerate` is a DECLARATION
|
||
TABLE: its FIELD NAMES are the names of other objects, and each one resolves as
|
||
`name_hash("<field name>.tbl")`.** `EnumLODSet_test.tbl` declares 676 names,
|
||
`EnumGameModel_test.tbl` 360 — and the disc holds **144** such objects (138 in
|
||
`DefTables`, one in each of the six `GP_MAIN_GAME_*`), declaring **1 298**
|
||
distinct names between them.
|
||
|
||
| | |
|
||
|---|---:|
|
||
| entries `DefTables` named by the string harvest (route 1) | 130 |
|
||
| **entries named by the declaration tables (route 2)** | **+1 283** |
|
||
| still unnamed | **12** |
|
||
| **`DefTables` IDXD coverage** | **1 413 / 1 425 = 99.2 %** |
|
||
|
||
`130 + 1283 + 12 = 1425` — the arithmetic closes, with **no overlap** between
|
||
the two routes.
|
||
|
||
✅ **Zero partials, and the suffix is exact.** Every one of the 1 036
|
||
`_test`-declared names resolves, and it resolves **only** as `<name>.tbl` with
|
||
**no** path prefix — of the 5 suffixes × 6 prefixes tried, `('', '.tbl')` scored
|
||
1 036 and every other combination scored 0.
|
||
|
||
**What the residual is**, in full: 8 declaration tables that nothing declares (the
|
||
other 130 are named by route 1, from the stage tables that reference them), plus
|
||
**4** ordinary tables — two `Generic+Level_0` LOD sets whose `Model` fields read
|
||
`rou_e004` and `rou_e013`, and two motion sets. **15 declared names have no pak
|
||
entry** (`GameModel_eff_e0033`, `…e0058`–`e0060`, `rou_e106_wep_02`, and their
|
||
`LOD_Effect_*` twins) — declarations for content that did not ship.
|
||
|
||
### 🔴 The XPR2 manifests are NOT the naming source — refuted
|
||
|
||
The obvious guess was the 40 XPR2 manifests, which name meshes
|
||
(`<XBGMesh Name = "rou_e104_brg_01_d" DataFile = "machines\rou_e104\objects\…xbg"/>`).
|
||
Their **82** `Name=` values and 82 `DataFile`/`Source` paths, hashed bare and
|
||
under `.tbl` / `.xbg` / `.xpr` / `.prt` / `game:\`, resolve **0** `DefTables`
|
||
entries.
|
||
|
||
They are not unrelated, though: **40 of the 82 manifest names appear as the
|
||
`Model` field VALUE inside the LOD/motion tables** (1 272 distinct `Model`
|
||
values in `DefTables`). Manifest and table share the *model* namespace; the pak
|
||
key is a different namespace, and only the declaration tables bridge it.
|
||
|
||
⚠️ First attempt used `Name="` and found **0 values** — the manifests write
|
||
`Name = "…"` with spaces. A regex miss looks exactly like a null result.
|
||
|
||
### ⚠️ Bonus, not this item: the `GP_MAIN_GAME_*` residual is already-owned data
|
||
|
||
With `DefTables` closed, the largest remaining unnamed block is the identical
|
||
**337 IDXD in each of the six `GP_MAIN_GAME_*`**, in 53 record-name shapes whose
|
||
top entries are `Shell+Weapon` (90), `Faces+Generic` (64),
|
||
`Effect+Explosion+Generic+Maneuver+Mass+SE+Shield+StructureCount` (44) and a
|
||
chatter table (`ATTACK_IS_AVOIDED …`, 8) — i.e. **weapon, unit and chatter
|
||
tables**, all families the corpus already documents. Characterising them
|
||
properly is still open.
|
||
|
||
## ✅ WHY each archive is low-coverage — two different reasons (2026-08-27)
|
||
|
||
Splitting every **unnamed** entry by its magic turns the percentage table into an
|
||
explanation. The three "low-coverage" UI archives are not missing data at all:
|
||
|
||
| archive | IDXD | named | **unnamed IDXD** | unnamed T8aD/RATC | unnamed LSTA |
|
||
|---|---:|---:|---:|---:|---:|
|
||
| `GP_HANGAR_ARSENAL` | 180 | **180** | **0** | 1 149 | 42 |
|
||
| `GP_MISSION_SELECT` | 0 | 0 | **0** | 64 | 2 |
|
||
| `GP_DEBRIEFING_PILOTLOG` | 0 | 0 | **0** | 148 | 8 |
|
||
| `DefTables` | 1 425 | 130 | **1 295** | 0 | 0 |
|
||
| `GP_MAIN_GAME_{D…S}` | 1 004 | 667 | 337 | 0 | 0 |
|
||
|
||
🔑 **`GP_HANGAR_ARSENAL`'s "22.6 %" is misleading: every one of its 180 data
|
||
tables is named.** Its 1 191 unnamed entries are **sprites and bundles**, and
|
||
`GP_MISSION_SELECT` / `GP_DEBRIEFING_PILOTLOG` contain **no IDXD objects at
|
||
all**. Those three are the *same* phenomenon as the 🔴 blocked 2D and
|
||
`GP_READY_ROOM` archives — unreachable **artwork** names — not a data gap.
|
||
|
||
🔑 **`DefTables` is the only genuine data gap on the disc**: 1 295 unnamed IDXD
|
||
objects, in **17 record-name shapes**, and two families cover almost all of them:
|
||
|
||
```
|
||
Generic + Level_0 … Level_3 807 LOD sets (cf. EnumLODSet_*.tbl)
|
||
Default + EnumMotions + Generic + 463 motion sets (cf. EnumGameModel_*.tbl)
|
||
ReferenceFrames (+ Motion_break /
|
||
Motion_dead / Motion_down)
|
||
```
|
||
|
||
`stage-definition-table.md` and `stage-mission-tables.md` own the *names*
|
||
`EnumLODSet_*.tbl` / `EnumGameModel_*.tbl`; **the record shapes above are not in
|
||
`docs/re/` anywhere** — `Level_0`, `EnumMotions` and `ReferenceFrames` appear in
|
||
no document. So what `DefTables` withholds is **one LOD table and one motion
|
||
table per model**, keyed by model names the disc does not spell out.
|
||
|
||
⚠️ The 40 `<?xml` entries in `DefTables` are **already identified** —
|
||
`isl-condition-builtins.md` calls them XPR2 resource manifests
|
||
(`<RDF Version="XPR2">`, `<XBGMesh …/>`, `<Texture …/>`) and corrects an earlier
|
||
"the config reader is XML" claim. Not new here.
|
||
|
||
**Control:** `GP_TITLE` and the other 100 % archives have no unnamed entry of any
|
||
kind, and `GP_MAIN_GAME_E` splits 667 named / 337 unnamed IDXD with zero unnamed
|
||
artwork — the two failure modes are cleanly separated, not a gradient.
|
||
|
||
## What that means for the 419
|
||
|
||
The in-game HUD's asset paths are not "missing". **Nothing in the 2D paks is
|
||
reachable by name from the disc's own strings**, whatever the extension. So the
|
||
2D and READY_ROOM TOC keys are hashes of names that are **not written anywhere
|
||
we can read** — built by the tool chain, or from a string the executable
|
||
composes, or from a name list held outside these archives.
|
||
|
||
## 🧪 Also refuted here — 13 name transformations
|
||
|
||
Before the census, the 419 config values were re-hashed under 13 rewrites:
|
||
as-is, forward slashes, basename, basename without extension, without extension,
|
||
uppercased, `.rat` substituted, `2d\`/`eng\`/`hud\`/`GP_MAIN_GAME_2D\` prefixed,
|
||
and first-directory stripped. **Every one scored 0, both against the E2D pak's
|
||
711 entries and against all 16 630 entries on the disc.**
|
||
|
||
## 🔴 BLOCKED — three routes to those names, all closed
|
||
|
||
Followed up the next iteration. Every avenue the container can reach is now
|
||
tried, each with a positive control in the same run:
|
||
|
||
**1. A different hash family.** The corpus knows three
|
||
([idxd-tag-hash](idxd-tag-hash.md)): `name_hash` (pak TOC), `tag_hash` (IDXD
|
||
keys) and `ixud_hash`. Scoring all 5 977 harvested names × 6 prefixes:
|
||
|
||
| archive | `name_hash` | `tag_hash` | `ixud_hash` |
|
||
|---|---:|---:|---:|
|
||
| `GP_TITLE` (control) | **8 / 16** | 0 | 0 |
|
||
| `GP_PAUSE_MENU` (control) | **6 / 11** | 0 | 0 |
|
||
| `GP_MAIN_GAME_E2D` | **0 / 711** | 0 | 0 |
|
||
| `GP_READY_ROOM` | 6 / 1 106 | 0 | 0 |
|
||
|
||
`tag_hash` and `ixud_hash` explain **nothing anywhere**, including the paks
|
||
`name_hash` does explain — so they are not the TOC function, and the two
|
||
unnameable archives are not simply keyed by a different one.
|
||
|
||
**2. The executable.** `sylpheed.db`'s `strings` table holds **7 140** rows, of
|
||
which exactly **two** look like asset paths — `Data\gmicon002_2.t32` and
|
||
`Data\gmicon006_2.t32`, in a `Data\` directory nothing else on the disc uses.
|
||
**Neither resolves in any archive.** So the binary is not the name source
|
||
either; it holds two strays and no table.
|
||
|
||
**3. Name transformations** of the config paths — 13 of them, all 0 (above).
|
||
|
||
🔴 **This is where the container runs out.** The 2D and `GP_READY_ROOM` TOC keys
|
||
hash names that are on neither the disc nor the executable in readable form. The
|
||
remaining lever is a *dictionary attack* using `name_hash`'s shape — the top byte
|
||
is the character-sum checksum, so candidates are cheap to reject — but that needs
|
||
a plausible name corpus, and this disc does not contain one. **Noted as blocked
|
||
rather than improvised around.**
|
||
|
||
⚠️ The port does not need these names: the sprites and bundles are readable by
|
||
*content* (T8aD, RATC), and the config records already say which asset each HUD
|
||
element uses. Only the archive-key ↔ name mapping is missing.
|
||
|
||
## ✅ Two structural facts that tighten the blocker (2026-08-28)
|
||
|
||
Re-opened to retry the prefix idea after `StageMessageSet_S02.tbl` turned out to
|
||
be a wrong-prefix problem (it resolves under `message\`, not `stage\`). **That
|
||
retry was already done here** — the 13 rewrites above include `2d\`, `eng\`,
|
||
`hud\` and `GP_MAIN_GAME_2D\`, all 0. What the re-open did produce is two
|
||
measurements the earlier passes did not make:
|
||
|
||
**1. The six 2D archives share ONE key set — 711 keys, identical in all six.**
|
||
Intersection = union = **711**; `4 266` entries, `711` distinct keys. So the
|
||
entry *names are language-independent*: the language lives in the **pak file
|
||
name**, not in the entry path. That refutes any `<lang>\` prefix hypothesis
|
||
**structurally**, not just by a zero score — if the names carried a language
|
||
directory the six key sets would differ.
|
||
|
||
**2. The 2D key space is disjoint from the rest of the disc.** **0 of the 711**
|
||
appear in any non-2D archive (disc-wide, 2 010 of the 16 630 distinct keys are
|
||
shared between archives, so sharing is common — this set simply does not do it).
|
||
There is no named neighbour to borrow a convention from.
|
||
|
||
⚠️ **And the six named `GP_READY_ROOM` entries are all fonts** —
|
||
`deu\GOTHICB.TTF`, `eng\`, `esp\`, `fra\`, `ita\` likewise, and
|
||
`jpn\HGRGE00.TTF`. The
|
||
count "6 named" was recorded above without saying *what* they are; they are
|
||
localisation fonts whose names come from elsewhere on the disc, **not a sample of
|
||
the archive's own artwork vocabulary**. So they cannot seed the dictionary attack
|
||
— the lever below still has no corpus.
|
||
|
||
## 🟡 Not settled
|
||
|
||
* What names the 2D and `GP_READY_ROOM` TOCs actually hash. The one lever left is
|
||
the hash's own shape — the top byte is the character-sum checksum, so any
|
||
candidate is cheap to reject — but that needs a name corpus this disc does not
|
||
contain.
|
||
* Why `DefTables` (8.9 %) and `GP_HANGAR_ARSENAL` (22.6 %) sit in the middle;
|
||
probably just that most of their entries are tables referenced by records this
|
||
harvest does not treat as filenames. Not chased.
|
||
|
||
## ❌ The `archive.pak+entry` dictionary does not touch the 2D blocker — 0 of 1 817
|
||
|
||
`StageResource` turned up a path form that names an archive *and* an entry
|
||
inside it ([[stage-definition-table]]). Since a pak TOC holds only hashes, any
|
||
such path is a **free name→key fact**, so it is worth asking whether the disc
|
||
carries enough of them to crack the two blocked archives.
|
||
|
||
Swept disc-wide, **7 fields** carry a `game:` value — `BackGroundPackage` (18),
|
||
`StageResourcePackage` (23), `TBL_3D` (6), `LodEnumTable` (7),
|
||
`MotionEnumTable` (7), plus one `PATH` and one anonymous. That is **63 distinct
|
||
paths in two forms**:
|
||
|
||
* **file form, 42** — 41 exist on the extracted ISO; the one miss is the bare
|
||
directory `game:\hidden\Resource3D\`, which is not a file.
|
||
* **`archive+entry` form, 21** — **20 of 20** resolve inside the archive they
|
||
name (the 21st is `sound.pak+` with an empty entry).
|
||
|
||
🔑 **The whole dictionary is 20 keys**, and here it is in full:
|
||
|
||
| archive | entry |
|
||
|---|---|
|
||
| `GP_HANGAR_ARSENAL.pak` | `deu\`, `eng\`, `esp\`, `fra\`, `ita\`, `jpn\` + `GP_HANGAR_ARSENAL_3D.tbl` |
|
||
| `DefTables.pak` | `EnumGameModel_{S24,S26,S27,S28,S29,Tutorial,test}.tbl` |
|
||
| `DefTables.pak` | `EnumLODSet_{S24,S26,S27,S28,S29,Tutorial,test}.tbl` |
|
||
|
||
❌ **The blocker test is a measured zero.** The six 2D paks and `GP_READY_ROOM`
|
||
hold **1 817** distinct keys between them; **0** are named by any `+` path. The
|
||
dictionary's total reach is **20 of 16 630 keys (0.12 %)**, and every one lands
|
||
in `DefTables` or `GP_HANGAR_ARSENAL` — archives that are already partly named.
|
||
|
||
**The route is exhausted, not merely unlucky**: these paths exist only in the
|
||
seven fields above, and none of those fields ever addresses a 2D or ready-room
|
||
asset. The blocker stands on its earlier structural reason (six identical 711-key
|
||
TOCs, 0 of 711 shared with any other archive).
|
||
|
||
❔ **One asymmetry left unexplained**: both `DefTables` families list
|
||
`S24, S26, S27, S28, S29, Tutorial, test` — **seven each, with S25 absent** and
|
||
no story stage present at all. Whether the other stages' `EnumLODSet` tables are
|
||
referenced by a bare name elsewhere, or simply not referenced by path, is not
|
||
settled here.
|