re: who references a .prt decides whether it ships -- menu named, in-game embedded

Censused the whole 135 unresolved set instead of chasing the five.
Cross-tab over all 376 .prt names: referenced by tables.pak AND
resolves 241; neither 100; referenced but absent 35; resolves WITHOUT
being referenced by tables.pak -- ZERO.

So resolving implies a tables.pak reference, 0 counterexamples of 376.
tables.pak holds the menu screen configs and every part it names ships
as <lang3>\<name>.prt.  The 100 names that appear only inside the
GP_MAIN_GAME_*2D.pak bundles never ship as entries -- the in-flight HUD
is authored into the bundles, not loaded by name.  The five pgmsg_*.prt
were never a special case; the split is menu = named + shipped,
in-game = embedded.

It is not a prefix rule: 6 of the 135 pg* names do resolve (pgloading,
pgloading2, pgmsg_scr, pgpause, pgpause_ttrl, pgpbase), because
tables.pak names them.

The 35-name residual is one coherent family -- pgmenu_btn*/item*/pad,
pgfacewin*, pgtextwin, phinfo1-3, 02d, 02d_scr, psview_release: the
in-game pause menu and squadron-order overlay, named by a menu config
but drawn from the in-game bundles.  Consistent with the split, not
separately proved.

Artefact +44 lines / 0 deletions; the other six regenerate
byte-identical.
This commit is contained in:
Sylpheed RE agent
2026-08-27 14:13:41 +00:00
parent 94065d40ec
commit e4000d9cb5
4 changed files with 119 additions and 2 deletions

View File

@@ -827,6 +827,31 @@ unknown, what evidence exists, and what the first step would be. Move an item in
field; the stat keys in records not opened here (`MegaTons`, `BulletLimit`,
`CrewCount`, `HP_CLASS`); why the roster lists 59 of 131.
***(2026-08-27) WHO REFERENCES A `.prt` DECIDES WHETHER IT SHIPS — menu parts
are named and shipped, in-game parts are embedded. 0 counterexamples in 376.**
[structures/mission-script-manifest](structures/mission-script-manifest.md),
artefact `data/prt-parts.txt` (+44 lines, 0 deletions — purely additive).
Censused the whole 135 unresolved set instead of chasing the five. Cross-tab
over all 376 `.prt` names: **referenced by `tables.pak` AND resolves 241;
neither 100; referenced but absent 35; resolves WITHOUT being referenced by
`tables.pak` — ZERO.**
🔑 **Resolving implies a `tables.pak` reference, 0 counterexamples of 376.**
`tables.pak` holds the menu screen configs and every part it names ships as
`<lang3>\<name>.prt`. The **100** names that appear only inside the
`GP_MAIN_GAME_*2D.pak` bundles never ship as entries — the in-flight HUD is
authored into the bundles, not loaded by name. So the five `pgmsg_*.prt` were
never a special case; the real split is **menu = named + shipped, in-game =
embedded**.
**It is NOT a prefix rule** — 6 of the 135 `pg*` names DO resolve
(`pgloading`, `pgloading2`, `pgmsg_scr`, `pgpause`, `pgpause_ttrl`, `pgpbase`),
precisely because `tables.pak` names them.
🟡 The 35-name residual is one coherent family: `tables.pak`-referenced yet
absent — `pgmenu_btn*`/`pgmenu_item*`/`pgmenu_pad`, `pgfacewin*`, `pgtextwin`,
`phinfo1-3`, `02d`, `02d_scr`, `psview_release`: the **in-game pause menu and
squadron-order overlay**, named by a menu config but drawn from the in-game
bundles. Consistent with the split, not separately proved.
🟡 Still open: where an embedded part sits INSIDE a bundle.
* 🟡 **(2026-08-27) WHERE `.prt` SCREEN PARTS LIVE — and the five mission
banners are a real exception.**
[structures/mission-script-manifest](structures/mission-script-manifest.md),

View File

@@ -22,6 +22,50 @@
prbase.prt resolves under: ['eng\\', 'jpn\\', 'fra\\', 'deu\\', 'ita\\', 'esp\\']
palogo1.prt resolves under: ['eng\\', 'jpn\\']
## WHO REFERENCES a part decides whether it ships as an entry
cross-tab (referenced by tables.pak?, resolves as an entry?):
tables=True resolves=True 241
tables=False resolves=False 100
tables=True resolves=False 35
=> resolving IMPLIES referenced by tables.pak: 0 counterexamples of 376
the 35 referenced-but-absent parts:
02d.prt
02d_scr.prt
pgfacewin.prt
pgfacewin_base.prt
pgfacewin_dead.prt
pgfacewin_em.prt
pgfacewin_tr.prt
pgmenu_btn00.prt
pgmenu_btn00f.prt
pgmenu_btn01.prt
pgmenu_btn01f.prt
pgmenu_btn10.prt
pgmenu_btn10f.prt
pgmenu_btn11.prt
pgmenu_btn11f.prt
pgmenu_btn12.prt
pgmenu_btn12f.prt
pgmenu_btn20.prt
pgmenu_btn20f.prt
pgmenu_btn21.prt
pgmenu_btn21f.prt
pgmenu_btn22.prt
pgmenu_btn22f.prt
pgmenu_btn30.prt
pgmenu_btn30f.prt
pgmenu_item0.prt
pgmenu_item1.prt
pgmenu_item2.prt
pgmenu_item3.prt
pgmenu_pad.prt
pgtextwin.prt
phinfo1.prt
phinfo2.prt
phinfo3.prt
psview_release.prt
pg* parts: 135, of which 6 resolve: ['pgloading.prt', 'pgloading2.prt', 'pgmsg_scr.prt', 'pgpause.prt', 'pgpause_ttrl.prt', 'pgpbase.prt']
## `<stem>_sub.rat` sub-bundles inside RATC
distinct _sub.rat names: 11
pgmsg_end_sub.rat in 6 archives ['GP_MAIN_GAME_D2D.pak', 'GP_MAIN_GAME_E2D.pak']

View File

@@ -126,7 +126,37 @@ but the control kills the generalisation: **only 4 of 376 `.prt` stems have a
`_sub.rat`. So `_sub.rat` is not the container convention; it is something these
four happen to have.
**Still not settled**: where the five mission-banner parts actually are. What is
### ✅ Who REFERENCES a part decides whether it ships as an entry
Censused the whole 135, not the five. The cross-tab over all **376** names:
| referenced by `tables.pak` | resolves as an entry | count |
|---|---|---:|
| yes | yes | **241** |
| no | no | **100** |
| yes | no | 35 |
| **no** | **yes** | **0** |
**Resolving implies being referenced by `tables.pak` — 0 counterexamples in
376.** `tables.pak` holds the menu screen configs; every part it names ships as
`<lang3>\<name>.prt`. The **100** names that appear only inside the
`GP_MAIN_GAME_*2D.pak` bundles never ship as entries at all — they are the
in-flight HUD, authored into the bundles rather than loaded by name.
🔑 So the five `pgmsg_*.prt` are not a special case of their own: they belong to
the 135, and the real split is **menu parts (named, shipped) vs in-game parts
(embedded)**. It is not a prefix rule — 6 of the 135 `pg*` names *do* resolve
(`pgloading`, `pgloading2`, `pgmsg_scr`, `pgpause`, `pgpause_ttrl`, `pgpbase`),
because `tables.pak` names them.
🟡 **The 35-name residual is one coherent family**: referenced by `tables.pak`
yet absent — `pgmenu_btn*` / `pgmenu_item*` / `pgmenu_pad`, `pgfacewin*`,
`pgtextwin`, `phinfo1-3`, `02d`, `02d_scr`, `psview_release`. That is the
**in-game pause menu and squadron-order overlay**: named by a menu config but
drawn from the in-game bundles. Consistent with the split above; not separately
proved.
**Still not settled**: where the embedded parts sit *inside* a bundle. What is
now settled is that they are **not** pak entries while 241 of their siblings are,
and that `pgmsg_update` is the odd one out even among them.

View File

@@ -18,13 +18,14 @@ PRE = ['', 'Stage\\', 'stage\\', 'message\\', 'language\\', '2d\\', 'ui\\', 'prt
def main():
H = collections.defaultdict(set)
names = set()
ref = collections.defaultdict(set)
rat = collections.defaultdict(set)
for pk in sorted(glob.glob('/work/sylph_extract/**/*.pak', recursive=True)):
base = os.path.basename(pk)
for h, b in pak_entries(pk):
H[h].add(base)
for m in re.finditer(rb'[A-Za-z0-9_]{3,40}\.prt', b):
names.add(m.group(0).decode())
names.add(m.group(0).decode()); ref[m.group(0).decode()].add(base)
if b[:4] == b'RATC':
for m in re.finditer(rb'[A-Za-z0-9_]{3,40}_sub\.rat', b):
rat[m.group(0).decode()].add(base)
@@ -50,6 +51,23 @@ def main():
ok = [p or '<bare>' for p in PRE if U.name_hash(p + n) in H]
print(" %-20s resolves under: %s" % (n, ok if ok else 'NOTHING'))
res = {n: any(U.name_hash(p + n) in H for p in PRE) for n in names}
tab = lambda n: 'tables.pak' in ref[n]
ct = collections.Counter((tab(n), res[n]) for n in names)
print("\n## WHO REFERENCES a part decides whether it ships as an entry")
print(" cross-tab (referenced by tables.pak?, resolves as an entry?):")
for k in sorted(ct, key=lambda x: -ct[x]):
print(" tables=%-5s resolves=%-5s %3d" % (k[0], k[1], ct[k]))
print(" => resolving IMPLIES referenced by tables.pak: %d counterexamples of %d"
% (ct[(False, True)], len(names)))
bad = sorted(n for n in names if tab(n) and not res[n])
print(" the %d referenced-but-absent parts:" % len(bad))
for n in bad:
print(" %s" % n)
pg = [n for n in names if n.startswith('pg')]
print(" pg* parts: %d, of which %d resolve: %s"
% (len(pg), sum(1 for n in pg if res[n]), sorted(n for n in pg if res[n])))
print("\n## `<stem>_sub.rat` sub-bundles inside RATC")
print(" distinct _sub.rat names: %d" % len(rat))
for k in sorted(rat):