Nothing here changes what a tool computes; it changes where tools look. - tools/re-capture: 33 censuses globbed /work/sylph_extract, a path that has existed nowhere since /work became a clone, so they matched nothing and printed empty results. They now resolve the disc through a new disc.py from $SYLPHEED_DISC and exit loudly without it (the #44 fix, generalised). Nine scripts that imported siblings from the retired Reborn checkout or an old session scratchpad now import from their own directory. unitgroup.py only needs the variable when --pak is not given. - sylpheed-xex: the loader only ever uses the XEX2 retail key. The dead devkit key and a doc comment claiming a devkit fallback that does not exist are gone; Project Sylpheed is a retail XEX2, so no XEX1 key either. - sylpheed-viewer: real_font_rasterizes looked for /tmp/sylph_extract and so always skipped. It reads $SYLPHEED_DISC now, and passes against the disc. - Comments and docs that named xenia-rs, the Reborn repository or /work/*.pe as places to look now name sylpheed.db, Canary's ppc_context.h and the flat .pe; docs/re/README.md no longer says the native Canary build does not run. Historical records keep their original paths: findings that were measured against /work/xenia-rs/sylpheed.db still say so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
91 lines
3.8 KiB
Python
91 lines
3.8 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
|
|
from disc import disc_root
|
|
|
|
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(disc_root() + '/**/GP_MAIN_GAME_E2D.pak', recursive=True)[0]
|
|
E = dict(pak_entries(p2))
|
|
H = set()
|
|
for pk in sorted(glob.glob(disc_root() + '/**/*.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## the objective / tutorial MARKER records")
|
|
seen = set()
|
|
for h, b in pak_entries(p2):
|
|
if b[:4] != b'IDXD': continue
|
|
for r in U.parse(b):
|
|
sq = r['squadron']
|
|
if not (sq.startswith('ObjectiveMarker_') or sq.startswith('TutorialMarker_')): continue
|
|
if sq in seen: continue
|
|
seen.add(sq)
|
|
n = U.named(r)
|
|
print(" %-30s %s" % (sq, " ".join("%s=%s" % (k, v) for k, v in sorted(n.items()))))
|
|
|
|
print("\n## ResourceTable -- 29 pairs, one per stage, with a single override")
|
|
for pk in sorted(glob.glob(disc_root() + '/**/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()
|