Files
psxrecomp/tools/verify_audit_schema.py
Matthew Stanley 60801820fd cleanup: genericize hardcoded dev-machine paths in tracked docs/tools
Replace absolute F:/C: paths with repo-relative (../TombaRecomp, bios/, beetle-psx/)
or placeholders (<desktop>/<psxref>/<nesrecomp>/<psxrecomp-v4>) across accuracy docs,
WIDESCREEN/SHADOW/RECURSION_BUG/config_schema/ISSUES/README, and tools/*.py|.ps1.
Removed a personal C:\Users\Matthew\Desktop path (ISSUES.md). Left CLAUDE.md/PLAN.md
sibling-project + version-history paths intact (intentional layout documentation).
2026-07-06 11:51:36 -07:00

69 lines
2.5 KiB
Python

"""B0 schema verification: parse both audit configs and check shape.
Confirms tools/* can rely on a stable layout. If this passes, B1 can
proceed to consume the configs.
"""
import sys
from pathlib import Path
try:
import tomllib # Python 3.11+
except ImportError:
import tomli as tomllib
ROOT = Path(__file__).parent.parent
def hex_int(s, field):
if not isinstance(s, str): raise ValueError(f"{field}: expected hex string, got {type(s).__name__}")
return int(s, 16)
def validate(path, expect_remaps):
print(f"\n=== {path} ===")
with open(path, "rb") as f:
cfg = tomllib.load(f)
# Program info: accept [program] (BIOS / non-game) or [game] (game convention).
p = cfg.get("program") or cfg.get("game")
if p is None:
raise KeyError("config has neither [program] nor [game] block")
rom_field = p.get("rom") or p.get("exe") # [program].rom or [game].exe
if rom_field is None:
raise KeyError("program/game block missing rom/exe path")
print(f" program.name = {p['name']!r}")
print(f" program.rom = {rom_field!r}")
print(f" program.load_address = {p['load_address']} = 0x{hex_int(p['load_address'], 'load_address'):08X}")
print(f" program.text_size = {p['text_size']} = 0x{hex_int(p['text_size'], 'text_size'):08X}")
# [audit] block
a = cfg["audit"]
fs = a.get("function_starts")
print(f" audit.function_starts = {fs!r}")
regions = a["regions"]
print(f" audit.regions = {len(regions)} region(s)")
for r in regions:
lo = hex_int(r["rom_start"], "rom_start")
hi = hex_int(r["rom_end"], "rom_end")
va = hex_int(r["vaddr_base"], "vaddr_base")
print(f" - {r['name']:8s} rom 0x{lo:05X}..0x{hi:05X} vaddr base 0x{va:08X} ({hi-lo} bytes)")
norm = a["normalize"]
mask = hex_int(norm["kseg_mask"], "kseg_mask")
print(f" audit.normalize.kseg_mask = 0x{mask:08X}")
remaps = norm.get("remap", [])
print(f" audit.normalize.remap = {len(remaps)} remap(s)")
assert len(remaps) == expect_remaps, f"expected {expect_remaps} remaps, got {len(remaps)}"
for rm in remaps:
flo = hex_int(rm["from_lo"], "from_lo")
fhi = hex_int(rm["from_hi"], "from_hi")
tlo = hex_int(rm["to_lo"], "to_lo")
print(f" - 0x{flo:08X}..0x{fhi:08X} -> +0x{tlo:X} ({rm.get('description','')})")
return cfg
bios = validate(ROOT / "bios" / "SCPH1001.toml", expect_remaps=2)
tomba = validate(Path("../TombaRecomp/game.toml"), expect_remaps=0)
print("\nOK: both configs parse and validate.")