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,47 @@
|
||||
-- Real frame, 256-colour, with the ACTUAL display gate from MAME's source:
|
||||
-- CRTC R20 bit 11 = "G-VRAM set to buffer" -> graphics layer invisible.
|
||||
-- CRTC R20 bits 9-8 = colour setup: 0x0100 = 256-colour, low byte per word.
|
||||
-- The IPL leaves R20 = 0x0B16 (buffered + 65536c), which is why every earlier
|
||||
-- attempt rendered black no matter what the video controller said.
|
||||
M=manager.machine; SP=M.devices[":maincpu"].spaces["program"]; SUB=nil
|
||||
|
||||
local CRTC20 = 0xE80000 + 20*2
|
||||
local GVRAM, GPAL = 0xC00000, 0xE82000
|
||||
|
||||
local f=io.open("frame.bin","rb"); local d=f:read("a"); f:close()
|
||||
local function B(i) return string.byte(d,i) end
|
||||
local W,H = B(5)*256+B(6), B(7)*256+B(8)
|
||||
local PAL0, PIX0 = 9, 9+256*3
|
||||
|
||||
-- GGGGGRRRRRBBBBBI, confirmed from x68k_v.cpp
|
||||
local function pack(r,g,b) return ((g>>3)<<11)|((r>>3)<<6)|((b>>3)<<1)|1 end
|
||||
|
||||
local function T() local t=M.time; return t.seconds+t.attoseconds/1e18 end
|
||||
local st,tp="wait",nil
|
||||
|
||||
SUB = emu.add_machine_frame_notifier(function()
|
||||
local t=T()
|
||||
if st=="wait" then
|
||||
if t<3.0 then return end
|
||||
local old = SP:read_u16(CRTC20)
|
||||
local new = (old & ~0x0B00) | 0x0100 -- clear buffer bit, select 256c
|
||||
SP:write_u16(CRTC20, new)
|
||||
SP:write_u16(0xE82400, 0x0001) -- video ctrl: 256 colours
|
||||
SP:write_u16(0xE82600, 0x001F) -- graphics + pages on, text off
|
||||
SP:write_u8(0xE8E001, 15) -- monitor contrast: IPL leaves it at 14
|
||||
for c=0,255 do
|
||||
local o=PAL0+c*3
|
||||
SP:write_u16(GPAL+c*2, pack(B(o),B(o+1),B(o+2)))
|
||||
end
|
||||
for y=0,H-1 do
|
||||
local row,base = PIX0+y*W, GVRAM+y*1024
|
||||
for x=0,W-1 do SP:write_u16(base+x*2, B(row+x)) end
|
||||
end
|
||||
print(string.format("[SHOW3] R20 %04X->%04X E82400=%04X E82600=%04X gv=%04X t=%.3f",
|
||||
old, SP:read_u16(CRTC20), SP:read_u16(0xE82400), SP:read_u16(0xE82600),
|
||||
SP:read_u16(GVRAM), t))
|
||||
st,tp="painted",t
|
||||
elseif st=="painted" and t>tp+0.30 then
|
||||
M.video:snapshot(); print("[SHOW3] snapshot"); st="done"; M:exit()
|
||||
end
|
||||
end)
|
||||
Reference in New Issue
Block a user