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

17 KiB
Raw Blame History

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). 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)

🔑 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

🔑 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, …e0058e0060, 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/ anywhereLevel_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 identifiedisl-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): 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 fontsdeu\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, 2120 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, testseven 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.