Files
Sylpheed/docs/re/structures/archive-naming.md
Sylpheed RE agent b3d1ce7dec re: the archive.pak+entry dictionary is 20 keys and misses the 2D blocker entirely
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.
2026-08-28 06:43:52 +00:00

331 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ✅ 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` | 2151 | **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` | 24108 | | 9194 % |
| `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.