Files
vt1200/bad-apple/tools/load_mame.lua
T

152 lines
4.3 KiB
Lua

-- load_mame.lua -- debugger entry for the Bad Apple payload.
--
-- Loads the payload at bit 0x018C0000 and the movie at bit 0x00080000, then
-- enters the payload at the OS idle loop. This is the development path; the
-- real delivery path is tools/load.sh (rdebug + LANCE).
--
-- Env:
-- BA_MODE=one|play (one is the only mode implemented here)
-- BA_MOVIE movie file (default bad-apple/data/test_movie.bin)
-- BA_PAYLOAD raw payload (default bad-apple/player/build/player.bin)
-- BA_ENV player.env with ENTRY_PTR (default .../player.env)
-- BA_AT load frame (default 2500)
-- BA_END inspection/exit frame (default 2600)
local function hex(v, w)
return string.format("%0" .. (w or 8) .. "X", v)
end
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
local prog = cpu.spaces['program']
if not dbg then
print("BA ERROR: debugger not enabled; pass -debug")
machine:exit()
return
end
local ORIGIN = 0x018C0000
local MOVIE = 0x00080000
local MARK = 0x01810000
local ENTRY_PC = 0x3F579970
local AT = tonumber(os.getenv("BA_AT") or "2500")
local STOP_AT = tonumber(os.getenv("BA_END") or "2600")
local MOVIE_PATH = os.getenv("BA_MOVIE") or "bad-apple/data/test_movie.bin"
local PAYLOAD_PATH = os.getenv("BA_PAYLOAD") or "bad-apple/player/build/player.bin"
local ENV_PATH = os.getenv("BA_ENV") or "bad-apple/player/build/player.env"
local function read_all(path)
local f, err = io.open(path, "rb")
if not f then
print("BA ERROR: cannot open " .. path .. ": " .. tostring(err))
machine:exit()
return nil
end
local data = f:read("*a")
f:close()
return data
end
local function entry_from_env()
local explicit = os.getenv("BA_ENTRY")
if explicit then
return tonumber(explicit)
end
local f = io.open(ENV_PATH, "r")
if not f then
return ORIGIN
end
for line in f:lines() do
local value = line:match("ENTRY_PTR=0x(%x+)")
if value then
f:close()
return tonumber(value, 16)
end
end
f:close()
return ORIGIN
end
local payload = read_all(PAYLOAD_PATH)
local movie = read_all(MOVIE_PATH)
if not payload or not movie then
return
end
local entry = entry_from_env()
print(string.format("BA: payload %d bytes, movie %d bytes, entry %s",
#payload, #movie, hex(entry)))
local function write_bytes(data, base)
local i
for i = 0, #data - 1 do
prog:write_u8(base + i * 8, data:byte(i + 1))
end
end
local function verify(data, base)
local i
for i = 0, #data - 1 do
if prog:read_u8(base + i * 8) ~= data:byte(i + 1) then
return false, i
end
end
return true, 0
end
local loaded = false
local entered = false
local done = false
local frames = 0
local function load_and_enter()
write_bytes(payload, ORIGIN)
write_bytes(movie, MOVIE)
local ok, bad = verify(payload, ORIGIN)
if not ok then
print("BA ERROR: payload readback mismatch at byte " .. bad)
machine:exit()
return
end
ok, bad = verify(movie, MOVIE)
if not ok then
print("BA ERROR: movie readback mismatch at byte " .. bad)
machine:exit()
return
end
print("BA: loaded; breakpoint at " .. hex(ENTRY_PC))
dbg:command("bpset " .. hex(ENTRY_PC) .. ",,{ pc = " .. hex(entry) .. " ; g }")
end
emu.register_frame_done(function()
frames = frames + 1
if frames == AT and not loaded then
loaded = true
load_and_enter()
end
if loaded and not entered and prog:read_u16(MARK) == 0x0000
and prog:read_u16(MARK + 0x10 * 8) == 0x0001 then
entered = true
done = true
print(string.format("BA: STATUS=painted at frame %d; FRAME=%d",
frames, prog:read_u16(MARK)))
end
if loaded and not done and frames > AT + 30 then
local err = prog:read_u32(MARK)
if err ~= 0 then
print(string.format("BA ERROR: marker %s at frame %d",
hex(err), frames))
machine:exit()
end
end
if frames >= STOP_AT then
print(string.format("BA: end at frame %d (loaded=%s done=%s)",
frames, tostring(loaded), tostring(done)))
machine:exit()
end
end, "vt1200-badapple-loader")
dbg.visible_cpu = cpu
dbg.execution_state = 'run'