Files
vt1200/bad-apple/tools/check_vram.py
T

74 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Compare a MAME VRAM dump with the logical frame the movie should show."""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
import numpy as np
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from pipeline.movie import read_movie
from pipeline.tilepack import apply_record
VRAM_STRIDE = 256
def vram_to_logical(data: bytes, width: int = 640, height: int = 512,
scale: int = 2) -> np.ndarray:
"""Unpack a 1-bpp VRAM dump and majority-downsample scale×scale blocks."""
screen_w = width * scale
screen_h = height * scale
need = VRAM_STRIDE * screen_h
if len(data) < need:
raise ValueError("VRAM dump is %d bytes, need at least %d"
% (len(data), need))
rows = np.frombuffer(data[:need], dtype=np.uint8).reshape(screen_h,
VRAM_STRIDE)
bits = np.unpackbits(rows, axis=1, bitorder="little")[:, :screen_w]
blocks = bits.astype(np.uint16).reshape(height, scale, width, scale)
# The driver's palette: bit 1 = white, bit 0 = black.
return blocks.mean(axis=(1, 3)) < 0.5
def expected_frame(movie_path: str, frame: int) -> np.ndarray:
header, records = read_movie(movie_path)
if frame < 0 or frame >= len(records):
raise ValueError("frame %d outside 0..%d" % (frame, len(records) - 1))
canvas = np.zeros((header.height, header.width), dtype=bool)
for record in records[:frame + 1]:
apply_record(canvas, record, tile=header.tile)
return canvas
def main(argv=None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--vram", required=True)
parser.add_argument("--movie", required=True)
parser.add_argument("--frame", type=int, default=0)
parser.add_argument("--scale", type=int, default=2)
args = parser.parse_args(argv)
data = Path(args.vram).read_bytes()
header, _ = read_movie(args.movie)
actual = vram_to_logical(data, header.width, header.height, args.scale)
expected = expected_frame(args.movie, args.frame)
if np.array_equal(actual, expected):
print("EXACT frame %d" % args.frame)
return 0
bad = int(np.count_nonzero(actual != expected))
ys, xs = np.where(actual != expected)
print("MISMATCH frame %d: %d logical pixels differ" % (args.frame, bad))
for y, x in list(zip(ys, xs))[:16]:
print(" (%d,%d) expected=%d actual=%d"
% (x, y, expected[y, x], actual[y, x]))
return 1
if __name__ == "__main__":
raise SystemExit(main())