mirror of
https://github.com/Abdess/retrobios.git
synced 2026-06-26 21:02:47 +00:00
expand bios collection, retrobat at 93% coverage
This commit is contained in:
parent
851a14e49a
commit
e6ea0484a8
3946 changed files with 8119839 additions and 2930936 deletions
291
bios/Arcade/MAME/plugins/gdbstub/init.lua
Normal file
291
bios/Arcade/MAME/plugins/gdbstub/init.lua
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
-- license:BSD-3-Clause
|
||||
-- copyright-holders: Carl
|
||||
local exports = {
|
||||
name = "gdbstub",
|
||||
version = "0.0.1",
|
||||
description = "GDB stub plugin",
|
||||
license = "BSD-3-Clause",
|
||||
author = { name = "Carl" } }
|
||||
|
||||
local gdbstub = exports
|
||||
|
||||
-- percpu mapping of mame registers to gdb register order
|
||||
local regmaps = {
|
||||
i386 = {
|
||||
togdb = {
|
||||
EAX = 1, ECX = 2, EDX = 3, EBX = 4, ESP = 5, EBP = 6, ESI = 7, EDI = 8, EIP = 9, EFLAGS = 10, CS = 11, SS = 12,
|
||||
DS = 13, ES = 14, FS = 15, GS = 16 },
|
||||
fromgdb = {
|
||||
"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "EIP", "EFLAGS", "CS", "SS", "DS", "ES", "FS", "GS" },
|
||||
regsize = 4,
|
||||
addrsize = 4,
|
||||
pcreg = "EIP"
|
||||
}
|
||||
}
|
||||
regmaps.i486 = regmaps.i386
|
||||
regmaps.pentium = regmaps.i386
|
||||
|
||||
local reset_subscription, stop_subscription
|
||||
|
||||
function gdbstub.startplugin()
|
||||
local debugger
|
||||
local debug
|
||||
local cpu
|
||||
local breaks
|
||||
local watches
|
||||
local consolelog
|
||||
local consolelast
|
||||
local running
|
||||
|
||||
reset_subscription = emu.add_machine_reset_notifier(function ()
|
||||
debugger = manager.machine.debugger
|
||||
if not debugger then
|
||||
print("gdbstub: debugger not enabled")
|
||||
return
|
||||
end
|
||||
cpu = manager.machine.devices[":maincpu"]
|
||||
if not cpu then
|
||||
print("gdbstub: maincpu not found")
|
||||
end
|
||||
if not regmaps[cpu.shortname] then
|
||||
print("gdbstub: no register map for cpu " .. cpu.shortname)
|
||||
cpu = nil
|
||||
end
|
||||
consolelog = debugger.consolelog
|
||||
consolelast = 0
|
||||
breaks = {byaddr = {}, byidx = {}}
|
||||
watches = {byaddr = {}, byidx = {}}
|
||||
running = false
|
||||
end)
|
||||
|
||||
stop_subscription = emu.add_machine_stop_notifier(function ()
|
||||
consolelog = nil
|
||||
cpu = nil
|
||||
debug = nil
|
||||
end)
|
||||
|
||||
local socket = emu.file("", 7)
|
||||
local connected = false
|
||||
socket:open("socket.127.0.0.1:2159")
|
||||
|
||||
emu.register_periodic(function ()
|
||||
if not cpu then
|
||||
return
|
||||
end
|
||||
|
||||
if running and debugger.execution_state == "stop" then
|
||||
socket:write("$S05#B8")
|
||||
running = false
|
||||
return
|
||||
elseif debugger.execution_state == "run" then
|
||||
running = true
|
||||
end
|
||||
|
||||
local function chksum(str)
|
||||
local sum = 0
|
||||
str:gsub(".", function(s) sum = sum + s:byte() end)
|
||||
return string.format("%.2x", sum & 0xff)
|
||||
end
|
||||
|
||||
local function makebestr(val, len)
|
||||
local str = ""
|
||||
for count = 0, len - 1 do
|
||||
str = str .. string.format("%.2x", (val >> (count * 8)) & 0xff)
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
local last = consolelast
|
||||
local msg = consolelog[#consolelog]
|
||||
consolelast = #consolelog
|
||||
if #consolelog > last and msg:find("Stopped at", 1, true) then
|
||||
local point = tonumber(msg:match("Stopped at breakpoint ([0-9]+)"))
|
||||
local map = regmaps[cpu.shortname]
|
||||
running = false
|
||||
if not point then
|
||||
point = tonumber(msg:match("Stopped at watchpoint ([0-9]+"))
|
||||
if not point then
|
||||
return -- ??
|
||||
end
|
||||
local wp = watches.byidx[point]
|
||||
if wp then
|
||||
local reply = "T05" .. wp.type .. ":" .. makebestr(wp.addr, map.addrsize)
|
||||
socket:write("$" .. reply .. "#" .. chksum(reply))
|
||||
else
|
||||
socket:write("$S05#B8")
|
||||
end
|
||||
return
|
||||
else
|
||||
local bp = breaks.byidx[point]
|
||||
if bp then
|
||||
local reply = "T05hwbreak:" .. makebestr(cpu.state[map.pcreg].value, map.regsize)
|
||||
socket:write("$" .. reply .. "#" .. chksum(reply))
|
||||
else
|
||||
socket:write("$S05#B8")
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if running and debugger.execution_state == "stop" then
|
||||
socket:write("$S05#B8")
|
||||
running = false
|
||||
return
|
||||
elseif debugger.execution_state == "run" then
|
||||
running = true
|
||||
end
|
||||
|
||||
local data = ""
|
||||
|
||||
repeat
|
||||
local read = socket:read(100)
|
||||
data = data .. read
|
||||
until #read == 0
|
||||
if #data == 0 then
|
||||
return
|
||||
end
|
||||
if data == "\x03" then
|
||||
debugger.execution_state = "stop"
|
||||
socket:write("$S05#B8")
|
||||
running = false
|
||||
return
|
||||
end
|
||||
local packet, checksum = data:match("%$([^#]+)#(%x%x)")
|
||||
if packet then
|
||||
packet:gsub("}(.)", function(s) return string.char(string.byte(s) ~ 0x20) end)
|
||||
local cmd = packet:sub(1, 1)
|
||||
local map = regmaps[cpu.shortname]
|
||||
if cmd == "g" then
|
||||
local regs = {}
|
||||
for reg, idx in pairs(map.togdb) do
|
||||
regs[idx] = makebestr(cpu.state[reg].value, map.regsize)
|
||||
end
|
||||
local data = table.concat(regs)
|
||||
socket:write("+$" .. data .. "#" .. chksum(data))
|
||||
elseif cmd == "G" then
|
||||
local count = 0
|
||||
packet:sub(2):gsub(string.rep("%x", map.regsize * 2), function(s)
|
||||
count = count + 1
|
||||
cpu.state[map.fromgdb[count]].value = tonumber(s,16)
|
||||
end)
|
||||
socket:write("+$OK#9a")
|
||||
elseif cmd == "m" then
|
||||
local addr, len = packet:match("m(%x+),(%x+)")
|
||||
if addr and len then
|
||||
addr = tonumber(addr, 16)
|
||||
len = tonumber(len, 16)
|
||||
local data = ""
|
||||
local space = cpu.spaces["program"]
|
||||
for count = 1, len do
|
||||
data = data .. string.format("%.2x", space:readv_u8(addr))
|
||||
addr = addr + 1
|
||||
end
|
||||
socket:write("+$" .. data .. "#" .. chksum(data))
|
||||
else
|
||||
socket:write("+$E00#a5") -- fix error
|
||||
end
|
||||
elseif cmd == "M" then
|
||||
local count = 0
|
||||
local addr, len, data = packet:match("M(%x+),(%x+),(%x+)")
|
||||
if addr and len and data then
|
||||
addr = tonumber(addr, 16)
|
||||
local space = cpu.spaces["program"]
|
||||
data:gsub("%x%x", function(s) space:writev_u8(addr + count, tonumber(s, 16)) count = count + 1 end)
|
||||
socket:write("+$OK#9a")
|
||||
else
|
||||
socket:write("+$E00#a5")
|
||||
end
|
||||
elseif cmd == "s" then
|
||||
if #packet == 1 then
|
||||
cpu.debug:step()
|
||||
socket:write("+$OK#9a")
|
||||
socket:write("$S05#B8")
|
||||
running = false
|
||||
else
|
||||
socket:write("+$E00#a5")
|
||||
end
|
||||
elseif cmd == "c" then
|
||||
if #packet == 1 then
|
||||
cpu.debug:go()
|
||||
socket:write("+$OK#9a")
|
||||
else
|
||||
socket:write("+$E00#a5")
|
||||
end
|
||||
elseif cmd == "Z" then
|
||||
local btype, addr, kind = packet:match("Z([0-4]),(%x+),(.*)")
|
||||
addr = tonumber(addr, 16)
|
||||
if btype == "0" then
|
||||
socket:write("") -- is machine dependant
|
||||
elseif btype == "1" then
|
||||
if breaks.byaddr[addr] then
|
||||
socket:write("+$E00#a5")
|
||||
return
|
||||
end
|
||||
local idx = cpu.debug:bpset(addr)
|
||||
breaks.byaddr[addr] = idx
|
||||
breaks.byidx[idx] = addr
|
||||
socket:write("+$OK#9a")
|
||||
elseif btype == "2" then
|
||||
if watches.byaddr[addr] then
|
||||
socket:write("+$E00#a5")
|
||||
return
|
||||
end
|
||||
local idx = cpu.debug:wpset(cpu.spaces["program"], "w", addr, 1)
|
||||
watches.byaddr[addr] = idx
|
||||
watches.byidx[idx] = {addr = addr, type = "watch"}
|
||||
socket:write("+$OK#9a")
|
||||
elseif btype == "3" then
|
||||
if watches.byaddr[addr] then
|
||||
socket:write("+$E00#a5")
|
||||
return
|
||||
end
|
||||
local idx = cpu.debug:wpset(cpu.spaces["program"], "r", addr, 1)
|
||||
watches.byaddr[addr] = idx
|
||||
watches.byidx[idx] = {addr = addr, type = "rwatch"}
|
||||
socket:write("+$OK#9a")
|
||||
elseif btype == "4" then
|
||||
if watches.byaddr[addr] then
|
||||
socket:write("+$E00#a5")
|
||||
return
|
||||
end
|
||||
local idx = cpu.debug:wpset(cpu.spaces["program"], "rw", addr, 1)
|
||||
watches.byaddr[addr] = idx
|
||||
watches.byidx[idx] = {addr = addr, type = "awatch"}
|
||||
socket:write("+$OK#9a")
|
||||
end
|
||||
elseif cmd == "z" then
|
||||
local btype, addr, kind = packet:match("z([0-4]),(%x+),(.*)")
|
||||
addr = tonumber(addr, 16)
|
||||
if btype == "0" then
|
||||
socket:write("") -- is machine dependent
|
||||
elseif btype == "1" then
|
||||
if not breaks.byaddr[addr] then
|
||||
socket:write("+$E00#a5")
|
||||
return
|
||||
end
|
||||
local idx = breaks.byaddr[addr]
|
||||
cpu.debug:bpclr(idx)
|
||||
breaks.byaddr[addr] = nil
|
||||
breaks.byidx[idx] = nil
|
||||
socket:write("+$OK#9a")
|
||||
elseif btype == "2" or btype == "3" or btype == "4" then
|
||||
if not watches.byaddr[addr] then
|
||||
socket:write("+$E00#a5")
|
||||
return
|
||||
end
|
||||
local idx = watches.byaddr[addr]
|
||||
cpu.debug:wpclr(idx)
|
||||
watches.byaddr[addr] = nil
|
||||
watches.byidx[idx] = nil
|
||||
socket:write("+$OK#9a")
|
||||
end
|
||||
elseif cmd == "?" then
|
||||
socket:write("+$S05#B8")
|
||||
else
|
||||
socket:write("+$#00")
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return exports
|
||||
Loading…
Add table
Add a link
Reference in a new issue