Get a real Dragon's Lair frame onto the emulated X68000
First pixels on an actual X68000 screen. Everything up to now was Python-side or a headless -video none run, which cannot snapshot at all. The blocker was not the video controller. The IPL leaves CRTC R20 = 0x0B16, and bit 11 is "G-VRAM set to buffer", which makes MAME's draw_gfx() return early. GVRAM writes still land and read back correctly while the layer is invisible, so six attempts at $E82400/$E82500/$E82600 all rendered black with every register holding the value I intended. Two more facts, both confirmed against MAME 0.277 source rather than assumed: - $E8E001 monitor contrast is left at 14 by the IPL, scaling all output to 93.3%. The player must set it to 15. Contrast 0 blanks the screen, which is a free fade-to-black for scene transitions. - The palette word is GGGGGRRRRRBBBBBI with a shared LSB, expanded as pal6bit((field<<1)|I). With contrast at 15 the render is pixel-exact, not merely close, which also confirms the 1024-byte GVRAM line stride. That exactness gives a new quality ceiling: the 15-bit+I palette alone costs 38.88 dB against the 24-bit palettised source, the same order as the scsi profile's own codec error. scsi is close to display-transparent on hardware, which bounds how much further it is worth raising. Unblocks next step 2, the 68000 decoder skeleton, which now has a known-good reference image to diff against. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Frame -> flat (RGB888 palette + index plane) blob for the MAME Lua loader.
|
||||
|
||||
Packing into the X68000 palette word is done Lua-side on purpose: the exact
|
||||
channel order is a hardware fact we intend to CONFIRM BY EYE, not assume, so it
|
||||
has to be cheap to change without regenerating the blob.
|
||||
"""
|
||||
import sys, struct, glob
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
src, out = sys.argv[1], sys.argv[2]
|
||||
f = sorted(glob.glob(f"{src}/*.png"))[int(sys.argv[3]) if len(sys.argv) > 3 else 0]
|
||||
im = Image.open(f).convert("RGB")
|
||||
W, H = im.size
|
||||
|
||||
q = im.quantize(colors=256, method=Image.MEDIANCUT, dither=Image.NONE)
|
||||
pal = np.array(q.getpalette()[:256*3], dtype=np.uint8).reshape(256, 3)
|
||||
idx = np.asarray(q, dtype=np.uint8)
|
||||
|
||||
with open(out, "wb") as fh:
|
||||
fh.write(b"DLXR")
|
||||
fh.write(struct.pack(">HH", W, H))
|
||||
fh.write(pal.tobytes())
|
||||
fh.write(idx.tobytes())
|
||||
|
||||
# reference PNG of exactly what the X68000 should display
|
||||
Image.fromarray(pal[idx]).save(out.replace(".bin", "_ref.png"))
|
||||
print(f"src={f} {W}x{H} colors={len(np.unique(idx))} -> {out}")
|
||||
Reference in New Issue
Block a user