-- CRTC high-speed-clear timing probe.
--
-- Discriminator 1 (unambiguous): write a pattern into GVRAM, reserve the
-- clear, then read GVRAM back IMMEDIATELY. Stock MAME performs the whole
-- clear synchronously inside the register write, so the pattern is already
-- gone. Real hardware (and the patched build) only RESERVES the clear, so the
-- pattern must still be intact until the next vertical display start.
--
-- Discriminator 2: the busy bit (operation port $E80480 bit 1) sampled once
-- per frame. Patched: 0 until VDISP, then set for exactly one frame.
local cpu = manager.machine.devices[":maincpu"]
local mem = cpu.spaces["program"]
local frame = 0

local OPPORT = 0xE80480   -- CRTC operation port
local R21    = 0xE8002A   -- clear page select
local GVRAM  = 0xC00000

local PAT = { 0x1234, 0x5678, 0x9ABC, 0xDEF0 }
local probeAt = 240
local done = false
local log = {}

local function writePattern()
    for i = 0, 3 do
        mem:write_u16(GVRAM + i * 2, PAT[i + 1])
    end
    -- a couple of rows in as well, so we are not only sampling row 0
    mem:write_u16(GVRAM + 512 * 2 * 4, 0x4321)
end

local function readPattern()
    local v = {}
    for i = 0, 3 do
        v[#v + 1] = string.format("%04X", mem:read_u16(GVRAM + i * 2))
    end
    v[#v + 1] = string.format("%04X", mem:read_u16(GVRAM + 512 * 2 * 4))
    return table.concat(v, " ")
end

local function busy()
    return (mem:read_u16(OPPORT) & 0x02) ~= 0 and 1 or 0
end

emu.register_frame_done(function()
    frame = frame + 1

    if frame == probeAt then
        writePattern()
        io.write("CRTCPROBE pattern_written  gvram=" .. readPattern() .. "\n")
        io.write(string.format("CRTCPROBE busy_before=%d r21_before=%04X\n",
                               busy(), mem:read_u16(R21)))
        mem:write_u16(R21, 0x000F)          -- select all four clear pages
        mem:write_u16(OPPORT, 0x0002)       -- reserve the high-speed clear
        -- IMMEDIATELY after the write, in the same emulated instant:
        io.write("CRTCPROBE after_write      gvram=" .. readPattern() ..
                 string.format("  busy=%d\n", busy()))
        log[#log + 1] = string.format("f+0 busy=%d gv=%s", busy(), readPattern())
    elseif frame > probeAt and frame <= probeAt + 6 then
        log[#log + 1] = string.format("f+%d busy=%d gv=%s",
                                      frame - probeAt, busy(), readPattern())
    elseif frame == probeAt + 7 and not done then
        done = true
        for _, l in ipairs(log) do
            io.write("CRTCPROBE " .. l .. "\n")
        end
        io.write("CRTCPROBE end\n")
        io.flush()
        manager.machine:exit()
    end
end)
