modemwars/extracted/provenance.py
2026-08-23 02:09:40 -05:00

39 lines
1.5 KiB
Python

#!/usr/bin/env python3
# provenance.py - map each 256-byte RAM page of a VICE snapshot to the disk sector / file page it came from.
import hashlib, glob, os, sys
ram = open(sys.argv[1], "rb").read()
secs = {}
for f in sorted(glob.glob("sectors/t??s??.bin")):
name = os.path.basename(f)[:-4]
secs.setdefault(hashlib.md5(open(f,"rb").read()).hexdigest(), []).append(name)
load = open("files/load.prg","rb").read()[2:]
for p in range(len(load)//256):
secs.setdefault(hashlib.md5(load[p*256:(p+1)*256]).hexdigest(), []).append(f"load.prg@{0x9800+p*256:04X}")
zeroHash = hashlib.md5(bytes(256)).hexdigest()
prev = None
rows = []
for p in range(256):
page = ram[p*256:(p+1)*256]
h = hashlib.md5(page).hexdigest()
if h == zeroHash:
src = "zero"
else:
src = ",".join(secs.get(h, ["?"]))
rows.append((p, src))
# compress runs
out = []
startP = 0
for i in range(1, 257):
cur = rows[i][1] if i < 256 else None
runSrc = rows[startP][1]
def kind(s):
if s in ("zero", "?"): return s
if s.startswith("load.prg"): return "load"
return "sector"
if i == 256 or kind(cur) != kind(runSrc) or kind(runSrc) in ("sector","load") and cur != runSrc and not (kind(runSrc)=="sector" and cur != "?" ):
out.append((startP, i-1, [r[1] for r in rows[startP:i]]))
startP = i
for s, e, srcs in out:
uniq = srcs if len(srcs) <= 6 else srcs[:3] + ["..."] + srcs[-2:]
print(f"${s:02X}00-${e:02X}FF: " + " ".join(uniq))