Files
goldeneye-pc-port/tools_pc/d125_check.py
T
James Dansereau 00fdd94c8d 2-4 player split-screen (#99): D416-D419, D422, D428, D448, D450
Virtual seats, per-seat camera and input routing, aim modes, hot-plugged
controllers reopening via a coalesced rescan (D450, dolent's PR #122,
merged as the original commit). Rule-2
sign-off for D417.

Refs: #99 D416 D417 D418 D419 D422 D428 D448 D450 #122
2026-10-06 18:35:40 -04:00

56 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""D125 diagnostic: does the propDefs blob in the *emitted* pccg sidecar
(after RZ round-trip) byte-match tools_pc/d88_propdefs.convert_stream()?
Tests the M-14 claim that the RAM propDefs is "zeros/garbage after record 0".
If this script says MATCH, the corruption is downstream of the sidecar
(runtime rebase / bank alloc / sizepropdef walk); if MISMATCH, it is in
d88_emit.py's emit/placement or the RZ recompress.
"""
import csv, struct, zlib, sys
from d88_propdefs import convert_stream, PROPDEF_PC_BYTES
REGION = "ntsc-final"
rom = open(f"data/ge007.{REGION}.z64", "rb").read()
fl = {}
for r in csv.reader(open("scripts/filelist.u.csv")):
if len(r) >= 3 and r[2]:
b = r[2].rsplit("/", 1)[-1]
b = b[:-4] if b.endswith(".bin") else b
fl[b] = (int(r[0]), int(r[1]))
man = {}
for r in csv.reader(open(f"data/pccg-{REGION}/manifest.csv")):
if r and (r[0].startswith("Usetup") or r[0].startswith("Ump_setup")):
man[r[0]] = (int(r[1]), int(r[2]))
sidebin = open(f"data/pccg-{REGION}/pccg.bin", "rb").read()
be = lambda b, o: struct.unpack_from(">I", b, o)[0]
targets = sys.argv[1:] or sorted(man)
for nm in targets:
a, s = fl[nm]
dec_n64 = zlib.decompress(rom[a:a + s][2:], -15)
pd_n64, intro_n64 = be(dec_n64, 12), be(dec_n64, 8)
want, n64len, pclen = convert_stream(dec_n64, pd_n64, intro_n64)
off, size = man[nm]
dec_pc = zlib.decompress(sidebin[off:off + size][2:], -15)
# PC header: 8-byte slots, low 4 = LE offset
pd_pc = struct.unpack_from("<I", dec_pc, 8 * 3)[0] # propDefs = field 3
intro_pc = struct.unpack_from("<I", dec_pc, 8 * 2)[0] # intro = field 2
got = dec_pc[pd_pc:pd_pc + len(want)]
if got == want:
print(f"MATCH {nm:18} pd@{pd_pc:#x} len={len(want)}")
else:
# first differing byte + which record it lands in
d = next((i for i in range(min(len(got), len(want))) if got[i] != want[i]), None)
rec, o = 0, 0
while o < (d or 0):
t = want[o + 3]
o += PROPDEF_PC_BYTES.get(t, 4)
rec += 1
print(f"MISMATCH {nm:18} pd@{pd_pc:#x} want={len(want)} got={len(got)} "
f"first diff @+{d} (~record {rec}, off {o:#x}); "
f"gotlen_vs_intro: {intro_pc - pd_pc} vs pclen {pclen}")