#!/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()