Checked first: no docs/re file mentions ArmsStatus, RangeFinder, Radar, Sight, Wing, NamePlate or ResourceTable. Only HudResource had been opened; the other fifteen records had not. The six IDXD entries of GP_MAIN_GAME_E2D.pak: two carry the 16-record HUD config, two the 13-record ObjectiveMarker_*/TutorialMarker_* set, one Face (52 portrait sprites), one ResourceTable. Between them they name 419 distinct asset paths -- the whole flight HUD -- with new subdirectory prefixes throughout (ArmsSt, ActvArm, RangeF, Marker, Manuva, Map, Speed, Radar, Sight, Wing, Hitmark, Lockon, Info). The decisive control uses the config's own exact path strings, so no guessing is left in the loop: 419 distinct .prt/.t32/.tbl values, ZERO resolve as a pak entry under 10 prefixes, and the four config filenames resolve to nothing either. The .t32 sprites certainly exist -- 574 T8aD in that pak. So the 2D pak is not addressed by name_hash of the name its config uses. This supersedes the earlier framing: the 28 'dangling' .prt names were never a missing-asset story; they are 28 of a set where none of the 419 resolves. ResourceTable is 58 positional fields = 29 pairs, alternating HudResource.tbl / HudMarkerResource.tbl, identical in all six language paks, with exactly one override at pair index 25 -- HudResource_S26.tbl. Reading: indexed by stage number minus 1, so index 25 is S26, the one stage with its own HUD config. Arithmetic exact, indexing unproven, not adopted. New structure doc, artefact and regenerator; the other seven regenerate byte-identical.
78 lines
3.3 KiB
Python
78 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""The in-game HUD configuration in the `GP_MAIN_GAME_*2D.pak` IDXD entries.
|
|
|
|
Regenerates docs/re/data/hud-config.txt.
|
|
"""
|
|
import sys, os, glob, collections
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
sys.path.insert(0, HERE)
|
|
import unitgroup as U
|
|
from unit_substructures import pak_entries
|
|
|
|
PRE = ['', '2d\\', 'ui\\', 'hud\\'] + [l + '\\' for l in ('eng', 'jpn', 'fra', 'deu', 'ita', 'esp')]
|
|
DEFAULT = ('HudResource.tbl', 'HudMarkerResource.tbl')
|
|
|
|
def main():
|
|
p2 = glob.glob('/work/sylph_extract/**/GP_MAIN_GAME_E2D.pak', recursive=True)[0]
|
|
E = dict(pak_entries(p2))
|
|
H = set()
|
|
for pk in sorted(glob.glob('/work/sylph_extract/**/*.pak', recursive=True)):
|
|
for h, b in pak_entries(pk):
|
|
H.add(h)
|
|
|
|
print("# The in-game HUD configuration (GP_MAIN_GAME_*2D.pak, IDXD entries)")
|
|
print("# Regenerate: python3 tools/re-capture/hud_config.py")
|
|
print("# See docs/re/structures/hud-config.md")
|
|
|
|
print("\n## the six IDXD entries of GP_MAIN_GAME_E2D.pak")
|
|
for h, b in sorted(pak_entries(p2)):
|
|
if b[:4] != b'IDXD': continue
|
|
recs = U.parse(b)
|
|
print(" %08x %2d records: %s" % (h, len(recs), ", ".join(r['squadron'] for r in recs)))
|
|
|
|
print("\n## every config record, field by field")
|
|
seen = set()
|
|
for h, b in sorted(pak_entries(p2)):
|
|
if b[:4] != b'IDXD': continue
|
|
for r in U.parse(b):
|
|
if r['squadron'] in seen: continue
|
|
seen.add(r['squadron'])
|
|
n = U.named(r)
|
|
pos = [v for t, nm, v in r['fields'] if nm is None]
|
|
print("\n== %s : %d fields (%d named, %d positional)"
|
|
% (r['squadron'], len(r['fields']), len(n), len(pos)))
|
|
for k, v in sorted(n.items()):
|
|
print(" %-28s %s" % (k, v))
|
|
for i, v in enumerate(pos):
|
|
print(" [%2d] %s" % (i, v))
|
|
|
|
vals = set()
|
|
for h, b in pak_entries(p2):
|
|
if b[:4] != b'IDXD': continue
|
|
for r in U.parse(b):
|
|
for t, nm, v in r['fields']:
|
|
if v.endswith('.prt') or v.endswith('.t32') or v.endswith('.tbl'):
|
|
vals.add(v)
|
|
ok = [v for v in vals if any(U.name_hash(q + v) in H for q in PRE)]
|
|
print("\n## CONTROL do the config's own path values resolve as pak entries?")
|
|
print(" distinct .prt/.t32/.tbl values: %d ; resolving under %d prefixes: %d"
|
|
% (len(vals), len(PRE), len(ok)))
|
|
print(" the config FILENAMES themselves:")
|
|
for n in list(DEFAULT) + ['HudResource_S26.tbl', 'HudMarkerResource_S26.tbl']:
|
|
print(" %-30s %s" % (n, 'resolves' if any(U.name_hash(q + n) in H for q in PRE) else 'no hit'))
|
|
|
|
print("\n## ResourceTable -- 29 pairs, one per stage, with a single override")
|
|
for pk in sorted(glob.glob('/work/sylph_extract/**/GP_MAIN_GAME_*2D.pak', recursive=True)):
|
|
for h, b in pak_entries(pk):
|
|
if b[:4] != b'IDXD': continue
|
|
for r in U.parse(b):
|
|
if r['squadron'] != 'ResourceTable': continue
|
|
vv = [v for t, nm, v in r['fields']]
|
|
odd = [(i, v) for i, v in enumerate(vv) if v not in DEFAULT]
|
|
print(" %-26s %2d fields = %d pairs ; non-default at %s"
|
|
% (os.path.basename(pk), len(vv), len(vv) // 2, odd))
|
|
|
|
if __name__ == "__main__":
|
|
main()
|