#!/usr/bin/env python3 """Is the C68K harness's decode pixel-exact against the reference decoder? python3 tools/bench/c68k/verify_c68k.py --nframes N This is the licence for every cycle number the harness prints. The harness rebuilds px68k's memory model from scratch -- byte-swapped RAM, GVRAM word writes that discard the high byte, a hand-rolled 24-bit map -- and any of that being subtly wrong would still produce plausible-looking cycle counts. It could not produce a pixel-exact 80-frame temporal recursion. Unlike tools/bench/verify_decode.py this compares palette INDICES, not rendered RGB: the harness dumps the low byte of each GVRAM word directly, so there is no palette round-trip to model and no snapshot geometry to unpick. """ import argparse, sys sys.path.insert(0, "tools/encoder") import numpy as np from dlx import DLX ap = argparse.ArgumentParser() ap.add_argument("container") ap.add_argument("--dump", default="tmp/c68k_screen.bin") ap.add_argument("--nframes", type=int, default=None) a = ap.parse_args() d = DLX(a.container) NF = a.nframes if a.nframes is not None else d.nframes if NF > d.nframes: sys.exit(f"--nframes {NF} exceeds the container's {d.nframes}") canvas = np.zeros((d.H, d.W), np.uint8) for f in range(NF): d.paint(canvas, f) got = np.fromfile(a.dump, np.uint8) if got.size != d.H * d.W: sys.exit(f"FAIL 1. dump is {got.size} B, expected {d.H*d.W}") got = got.reshape(d.H, d.W) if not np.array_equal(got, canvas): bad = got != canvas by, bx = np.where(bad) blocks = sorted(set(zip((by // 4).tolist(), (bx // 4).tolist()))) sys.exit(f"FAIL 2. frame {NF-1} not pixel-exact under C68K: {bad.sum()} px in " f"{len(blocks)} blocks differ; first block " f"(by={blocks[0][0]}, bx={blocks[0][1]})") print(f"OK {NF} frames decoded on px68k's C68K core, final frame pixel-exact " f"against tools/encoder/dlx.py") print(f" {d.W}x{d.H}, {d.nb} blocks/frame, k1={d.k1} k4={d.k4}; the memory " f"model (byte-swapped RAM, high-byte-discarding GVRAM) is therefore right")