mesen-binary-monitor/commands.lua

900 lines
28 KiB
Lua
Raw Normal View History

2021-11-04 03:55:06 +01:00
local _p = print
2021-11-03 17:53:25 +01:00
local function print(data)
_p(data .. "")
end
return function(server)
2021-11-05 03:16:20 +01:00
local me = {
open = false,
}
2021-11-03 17:53:25 +01:00
local function responseCheckpointInfo(requestId, checkpt, hit)
local r = {}
r[#r+1] = server.uint32ToLittleEndian(checkpt.num)
r[#r+1] = server.boolToLittleEndian(hit)
r[#r+1] = server.uint16ToLittleEndian(checkpt.start)
r[#r+1] = server.uint16ToLittleEndian(checkpt.finish)
r[#r+1] = server.boolToLittleEndian(checkpt.stop)
r[#r+1] = server.boolToLittleEndian(checkpt.enabled)
r[#r+1] = server.uint8ToLittleEndian(checkpt.op)
r[#r+1] = server.boolToLittleEndian(checkpt.temp)
r[#r+1] = server.uint32ToLittleEndian(checkpt.hitCount)
r[#r+1] = server.uint32ToLittleEndian(checkpt.ignoreCount)
r[#r+1] = server.boolToLittleEndian(checkpt.condition ~= nil)
r[#r+1] = server.uint32ToLittleEndian(checkpt.memspace)
server.response(server.responseType.CHECKPOINT_INFO, server.errorType.OK, requestId, table.concat(r))
end
local regMeta = {
a = { name = "A", id = 0, size = 1 },
x = { name = "X", id = 1, size = 1 },
y = { name = "Y", id = 2, size = 1 },
pc = { name = "PC", id = 3, size = 2 },
sp = { name = "SP", id = 4, size = 1 },
status = { name = "FL", id = 5, size = 1 },
}
local function responseRegisterInfo(requestId)
if requestId == nil then
error("request id was nil", 2)
end
local r = {}
local regs = emu.getState().cpu
local count = 0
for name, meta in pairs(regMeta) do
count = count + 1
end
r[#r+1] = server.uint16ToLittleEndian(count)
local itemSize = 3
for name, meta in pairs(regMeta) do
r[#r+1] = server.uint8ToLittleEndian(itemSize)
r[#r+1] = server.uint8ToLittleEndian(meta.id)
r[#r+1] = server.uint16ToLittleEndian(regs[name])
end
server.response(server.responseType.REGISTER_INFO, server.errorType.OK, requestId, table.concat(r))
end
local function responseStopped()
local pc = emu.getState().cpu.pc
server.response(server.responseType.STOPPED, server.errorType.OK, server.EVENT_ID, server.uint16ToLittleEndian(pc))
end
local function responseResumed()
local pc = emu.getState().cpu.pc
server.response(server.responseType.RESUMED, server.errorType.OK, server.EVENT_ID, server.uint16ToLittleEndian(pc))
end
function me.monitorOpened()
2021-11-05 03:16:20 +01:00
if me.open then
return
end
me.open = true
2021-11-03 17:53:25 +01:00
print("Monitor opened")
2021-11-05 04:19:12 +01:00
local pc = emu.getState().cpu.pc
print(string.format("PC: %04x", pc))
2021-11-03 17:53:25 +01:00
responseRegisterInfo(server.EVENT_ID)
responseStopped(server.EVENT_ID)
end
function me.monitorClosed()
2021-11-05 03:16:20 +01:00
if not me.open then
return
end
me.open = false
2021-11-03 17:53:25 +01:00
print("Monitor closed")
responseResumed(server.EVENT_ID)
end
local dumps = {}
local function processDump(command)
if command.length < 3 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local saveRoms = server.readBool(command.body, 1)
local saveDisks = server.readBool(command.body, 2)
local filenameLength = server.readUint8(command.body, 3)
if command.length < 3 + filenameLength then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local filename = command.body:sub(4, 4 + filenameLength - 1)
print("Dumping "..filename)
local dereg
local callback = function()
dumps[filename] = emu.saveSavestate()
server.response(server.responseType.DUMP, server.errorType.OK, command.requestId, nil)
print("Dumped "..filename)
emu.removeEventCallback(dereg, emu.eventType.startFrame)
end
dereg = emu.addEventCallback(callback, emu.eventType.startFrame)
end
local function processUndump(command)
if command.length < 1 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local filenameLength = server.readUint8(command.body, 1)
if command.length < 1 + filenameLength then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local filename = command.body:sub(2, 2 + filenameLength - 1)
local dump = dumps[filename]
if dump == nil then
server.errorResponse(server.errorType.CMD_FAILURE, command.requestId)
return
end
local dereg
local callback = function()
emu.loadSavestate(dump)
local pc = emu.getState().cpu.pc
server.response(server.responseType.UNDUMP, server.errorType.OK, command.requestId, server.uint16ToLittleEndian(pc))
emu.removeEventCallback(dereg, emu.eventType.startFrame)
end
dereg = emu.addEventCallback(callback, emu.eventType.startFrame)
end
2021-11-03 17:53:25 +01:00
local function processAdvanceInstructions(command)
if command.length < 3 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local stepOverSubroutines = server.readBool(command.body, 1)
local count = server.readUint16(command.body, 2)
server.stepping = true
if stepOverSubroutines then
-- FIXME
emu.execute(count, emu.executeCountType.cpuInstructions)
else
emu.execute(count, emu.executeCountType.cpuInstructions)
end
server.running = true
server.response(server.responseType.ADVANCE_INSTRUCTIONS, server.errorType.OK, command.requestId, nil)
me.monitorClosed()
end
2021-11-05 10:42:26 +01:00
-- FIXME This should take instruction level into account
local function processExecuteUntilReturn(command)
-- FIXME
server.stepping = true
emu.execute(1, emu.executeCountType.cpuInstructions)
server.running = true
server.response(server.responseType.EXECUTE_UNTIL_RETURN, server.errorType.OK, command.requestId, nil)
me.monitorClosed()
end
2021-11-03 17:53:25 +01:00
local function processPing(command)
server.response(server.responseType.PING, server.errorType.OK, command.requestId, nil)
end
local memspaces = {
MAIN = 0,
INVALID = -1,
}
local function getRequestedMemspace(requestedMemspace)
if requestedMemspace == 0 then
return memspaces.MAIN
else
return memspaces.INVALID
end
end
local banks = {
default = 0,
cpu = 1,
ppu = 2,
palette = 3,
oam = 4,
secondaryOam = 5
}
local function validateBanknum(memspace, banknum)
return memspace == memspaces.MAIN and banknum >= banks.default and banknum <= banks.secondaryOam
end
2021-11-04 00:24:50 +01:00
local function ignoreRegister(meta)
return false
end
local function processRegistersAvailable(command)
if command.length < 1 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local requestedMemspace = server.readUint8(command.body, 1)
local memspace = getRequestedMemspace(requestedMemspace)
if memspace == memspaces.INVALID then
server.errorResponse(server.errorType.INVALID_MEMSPACE, command.requestId)
return
end
local responseRegCount = 0;
for name, meta in pairs(regMeta) do
if not ignoreRegister(meta) then
responseRegCount = responseRegCount + 1
end
end
local r = {}
r[#r+1] = server.uint16ToLittleEndian(responseRegCount)
for name, meta in pairs(regMeta) do
if not ignoreRegister(meta) then
local itemSize = meta.name:len() + 3
r[#r+1] = server.uint8ToLittleEndian(itemSize)
r[#r+1] = server.uint8ToLittleEndian(meta.id)
r[#r+1] = server.uint8ToLittleEndian(meta.size * 8)
r[#r+1] = server.writeString(meta.name);
end
end
server.response(server.responseType.REGISTERS_AVAILABLE, server.errorType.OK, command.requestId, table.concat(r));
end
2021-11-04 00:48:47 +01:00
local function processBanksAvailable(command)
local responseBankCount = 0;
for name, id in pairs(banks) do
responseBankCount = responseBankCount + 1
end
local r = {}
r[#r+1] = server.uint16ToLittleEndian(responseBankCount)
for name, id in pairs(banks) do
local itemSize = name:len() + 3
r[#r+1] = server.uint8ToLittleEndian(itemSize)
r[#r+1] = server.uint16ToLittleEndian(id)
r[#r+1] = server.writeString(name);
end
server.response(server.responseType.BANKS_AVAILABLE, server.errorType.OK, command.requestId, table.concat(r));
end
2021-11-04 03:55:06 +01:00
local function processDisplayGet(command)
print("Taking screenshot")
2021-11-04 03:55:06 +01:00
if command.apiVersion < 0x02 then
print("API Version error")
2021-11-04 03:55:06 +01:00
server.errorResponse(server.errorType.INVALID_API_VERSION, command.requestId)
return
end
local infoLength = 13;
local shot = emu.takeScreenshot()
print("Screenshot taken")
2021-11-04 03:55:06 +01:00
local r = {}
-- Length of fields before display buffer
r[#r+1] = server.uint32ToLittleEndian(infoLength)
2021-11-04 00:48:47 +01:00
2021-11-04 03:55:06 +01:00
-- Full width of buffer
r[#r+1] = server.uint16ToLittleEndian(256)
-- Full height of buffer
r[#r+1] = server.uint16ToLittleEndian(240)
-- X offset of the inner part of the screen
r[#r+1] = server.uint16ToLittleEndian(0)
-- Y offset of the inner part of the screen
r[#r+1] = server.uint16ToLittleEndian(0)
-- Width of the inner part of the screen
r[#r+1] = server.uint16ToLittleEndian(256)
-- Height of the inner part of the screen
r[#r+1] = server.uint16ToLittleEndian(240)
-- Bits per pixel of image
r[#r+1] = server.uint8ToLittleEndian(24)
-- Length of display buffer
r[#r+1] = server.uint32ToLittleEndian(shot:len())
-- Buffer Data in requested format
r[#r+1] = shot
server.response(server.responseType.DISPLAY_GET, server.errorType.OK, command.requestId, table.concat(r));
end
local function processExit(command)
2021-11-04 00:48:47 +01:00
server.response(server.responseType.EXIT, server.errorType.OK, command.requestId, nil)
me.monitorClosed()
2021-11-04 03:55:06 +01:00
server.running = true
2021-11-04 00:48:47 +01:00
end
local function processReset(command)
server.running = true
emu.reset()
server.response(server.responseType.RESET, server.errorType.OK, command.requestId, nil)
me.monitorClosed()
end
local function processMemorySet(command)
local newSidefx = server.readBool(command.body, 1)
local startAddress = server.readUint16(command.body, 2)
local endAddress = server.readUint16(command.body, 4)
if startAddress > endAddress then
server.errorResponse(server.errorType.INVALID_PARAMETER, command.requestId)
return
end
local length = endAddress - startAddress + 1
if command.length < length + 8 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local requestedMemspace = server.readUint8(command.body, 6)
local memspace = getRequestedMemspace(requestedMemspace)
if memspace == memspaces.INVALID then
server.errorResponse(server.errorType.INVALID_MEMSPACE, command.requestId)
return
end
local requestedBanknum = server.readUint16(command.body, 7)
if not validateBanknum(memspace, requestedBanknum) then
server.errorResponse(server.errorType.INVALID_PARAMETER, command.requestId)
return
end
local banknum = requestedBanknum
if banknum == banks.default then
banknum = banks.cpu
end
if not newSidefx and ( banknum == banks.cpu or banknum == banks.ppu ) then
banknum = banknum + 0x100
end
banknum = banknum - 1
for i = 0,length - 1,1 do
local val = command.body:byte(8 + i + 1)
print(val)
emu.write(startAddress + i, val, banknum)
end
server.response(server.responseType.MEM_SET, server.errorType.OK, command.requestId, nil)
end
2021-11-04 00:24:50 +01:00
local function processExit(command)
server.running = true
server.response(server.responseType.EXIT, server.errorType.OK, command.requestId, nil)
me.monitorClosed()
end
local function processReset(command)
server.running = true
emu.reset()
server.response(server.responseType.RESET, server.errorType.OK, command.requestId, nil)
me.monitorClosed()
end
2021-11-03 17:53:25 +01:00
local function processMemorySet(command)
local newSidefx = server.readBool(command.body, 1)
local startAddress = server.readUint16(command.body, 2)
local endAddress = server.readUint16(command.body, 4)
if startAddress > endAddress then
server.errorResponse(server.errorType.INVALID_PARAMETER, command.requestId)
return
end
local length = endAddress - startAddress + 1
if command.length < length + 8 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local requestedMemspace = server.readUint8(command.body, 6)
local memspace = getRequestedMemspace(requestedMemspace)
if memspace == memspaces.INVALID then
server.errorResponse(server.errorType.INVALID_MEMSPACE, command.requestId)
return
end
2021-11-04 00:24:50 +01:00
local requestedBanknum = server.readUint16(command.body, 7)
2021-11-03 17:53:25 +01:00
if not validateBanknum(memspace, requestedBanknum) then
server.errorResponse(server.errorType.INVALID_PARAMETER, command.requestId)
return
end
local banknum = requestedBanknum
if banknum == banks.default then
banknum = banks.cpu
end
if not newSidefx and ( banknum == banks.cpu or banknum == banks.ppu ) then
banknum = banknum + 0x100
end
banknum = banknum - 1
for i = 0,length - 1,1 do
local val = command.body:byte(8 + i + 1)
print(val)
emu.write(startAddress + i, val, banknum)
end
server.response(server.responseType.MEM_SET, server.errorType.OK, command.requestId, nil)
end
local function processMemoryGet(command)
if command.length < 8 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local newSidefx = server.readBool(command.body, 1)
local startAddress = server.readUint16(command.body, 2)
local endAddress = server.readUint16(command.body, 4)
if startAddress > endAddress then
server.errorResponse(server.errorType.INVALID_PARAMETER, command.requestId)
return
end
local requestedMemspace = server.readUint8(command.body, 6)
local memspace = getRequestedMemspace(requestedMemspace)
if memspace == memspaces.INVALID then
server.errorResponse(server.errorType.INVALID_MEMSPACE, command.requestId)
return
end
local length = endAddress - startAddress + 1
local requestedBanknum = server.readUint16(command.body, 7)
if not validateBanknum(memspace, requestedBanknum) then
server.errorResponse(server.errorType.INVALID_PARAMETER, command.requestId)
return
end
local banknum = requestedBanknum
local r = {}
r[#r+1] = server.uint16ToLittleEndian(length)
if banknum == banks.default then
banknum = banks.cpu
end
if not newSidefx and ( banknum == banks.cpu or banknum == banks.ppu ) then
banknum = banknum + 0x100
end
banknum = banknum - 1
local remainingByte = length % 2 ~= 0
for addr=startAddress,endAddress-1,2 do
r[#r+1] = server.uint16ToLittleEndian(emu.readWord(addr, banknum))
end
if remainingByte then
r[#r+1] = server.uint8ToLittleEndian(emu.read(addr, banknum))
end
server.response(server.responseType.MEM_GET, server.errorType.OK, command.requestId, table.concat(r))
end
nextTrap = 1
traps = {}
local operation = {
READ = 0x01,
WRITE = 0x02,
EXEC = 0x04,
}
local trapHandle
local function addCheckpoint(start, finish, stop, enabled, op, temp)
local num = nextTrap
nextTrap = nextTrap+1
local trap = {
start = start,
finish = finish,
stop = stop,
enabled = enabled,
op = op,
temp = temp,
hitCount = 0,
ignoreCount = 0,
condition = nil,
memspace = 0,
num = num,
}
traps[#traps+1] = trap
if trap.op & operation.EXEC ~= 0 then
trap.execRegistration = emu.addMemoryCallback(function()
if trap.enabled then
trapHandle(trap)
end
end, emu.memCallbackType.cpuExec, trap.start, trap.finish)
end
if trap.op & operation.READ ~= 0 then
trap.readRegistration = emu.addMemoryCallback(function()
if trap.enabled then
trapHandle(trap)
end
end, emu.memCallbackType.cpuRead, trap.start, trap.finish)
end
if trap.op & operation.WRITE ~= 0 then
trap.writeRegistration = emu.addMemoryCallback(function()
if trap.enabled then
trapHandle(trap)
end
end, emu.memCallbackType.cpuRead, trap.start, trap.finish)
end
return trap
end
local function removeCheckpoint(num)
local trap
for i=#traps,1,-1 do
trap = traps[i]
if trap.num == num then
table.remove(traps, i)
break
end
trap = nil
end
if trap == nil then
return false
end
if trap.execRegistration ~= nil then
emu.removeMemoryCallback(trap.execRegistration, emu.memCallbackType.cpuExec, trap.start, trap.finish)
end
if trap.readRegistration ~= nil then
emu.removeMemoryCallback(trap.readRegistration, emu.memCallbackType.cpuRead, trap.start, trap.finish)
end
if trap.writeRegistration ~= nil then
emu.removeMemoryCallback(trap.writeRegistration, emu.memCallbackType.cpuWrite, trap.start, trap.finish)
end
return true
end
local function toggleCheckpoint(enable, num)
for i=#traps,1,-1 do
trap = traps[i]
if trap.num == num then
break
end
trap = nil
end
if trap == nil then
return false
end
trap.enabled = enable
return true
end
local function processCheckpointGet(command)
if command.length < 4 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local num = server.readUint32(command.body, 1)
for i=#traps,1,-1 do
trap = traps[i]
if trap.num == num then
break
end
trap = nil
end
if not trap then
server.errorResponse(server.errorType.OBJECT_MISSING, command.requestId)
return
end
responseCheckpointInfo(command.requestId, trap, false)
end
local function processCheckpointSet(command)
if command.length < 8 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
-- Ignore the memspace - byte 9
local checkpt = addCheckpoint(
server.readUint16(command.body, 1),
server.readUint16(command.body, 3),
server.readBool(command.body, 5),
server.readBool(command.body, 6),
server.readUint8(command.body, 7),
server.readBool(command.body, 8)
)
responseCheckpointInfo(command.requestId, checkpt, 0)
end
local function processCheckpointDelete(command)
if command.length < 4 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local brkNum = server.readUint32(command.body, 1)
local success = removeCheckpoint(brkNum)
if not success then
server.errorResponse(server.errorType.OBJECT_MISSING, command.requestId)
return
end
server.response(server.responseType.CHECKPOINT_DELETE, server.errorType.OK, command.requestId, nil)
end
local function processCheckpointList(command)
for i = 1,#traps,1 do
responseCheckpointInfo(command.requestId, traps[i], false)
end
local r = server.uint32ToLittleEndian(#traps)
server.response(server.responseType.CHECKPOINT_LIST, server.errorType.OK, command.requestId, r)
end
local function processCheckpointToggle(command)
if command.length < 5 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local num = server.readUint32(command.body, 1)
local enable = server.readBool(command.body, 5)
if not toggleCheckpoint(enable, num) then
server.errorResponse(server.errorType.OBJECT_MISSING, command.requestId)
return
end
server.response(server.responseType.CHECKPOINT_TOGGLE, server.errorType.OK, command.requestId, nil)
end
local function validateRegister(memspace, regId)
return memspace == memspaces.MAIN and regId >= regMeta.a.id and regId <= regMeta.status.id
end
local function processRegistersGet(command)
if command.length < 1 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local requestedMemspace = server.readUint8(command.body, 1)
local memspace = getRequestedMemspace(requestedMemspace)
if memspace == memspaces.INVALID then
server.errorResponse(server.errorType.INVALID_MEMSPACE, command.requestId)
return
end
responseRegisterInfo(command.requestId, memspace)
end
local function processRegistersSet(command)
local headerSize = 3
local count = server.readUint16(command.body, 2)
if command.length < headerSize + count * (3 + 1) then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
local requestedMemspace = server.readUint8(command.body, 1)
local memspace = getRequestedMemspace(requestedMemspace)
if memspace == memspaces.INVALID then
server.errorResponse(server.errorType.INVALID_MEMSPACE, command.requestId)
return
end
local bodyCursor = headerSize + 1
local state = emu.getState()
for i=1,count do
local itemSize = server.readUint8(command.body, bodyCursor + 0)
local regId = server.readUint8(command.body, bodyCursor + 1)
local regVal = server.readUint16(command.body, bodyCursor + 2)
if itemSize < 3 then
server.errorResponse(server.errorType.CMD_INVALID_LENGTH, command.requestId)
return
end
if not validateRegister(memspace, regId) then
server.errorResponse(server.errorType.OBJECT_MISSING, command.requestId)
return
end
for name, meta in pairs(regMeta) do
if meta.id == regId then
state.cpu[name] = regVal
break
end
end
bodyCursor = bodyCursor + itemSize + 1
end
emu.setState(state)
responseRegisterInfo(command.requestId, memspace)
end
function me.processCommand(apiVersion, bodyLength, remainingHeader, body)
local command = {}
command.apiVersion = apiVersion
if command.apiVersion < 0x01 or command.apiVersion > 0x02 then
server.errorResponse(server.errorType.INVALID_API_VERSION, command.requestId)
end
command.length = bodyLength
command.requestId = server.readUint32(remainingHeader, 1)
command.type = server.readUint8(remainingHeader, 5)
command.body = body
local prettyType = ""
for k, v in pairs(server.commandType) do
if v == command.type then
prettyType = k
break
end
end
print(string.format("Command start: %02x (%s)", command.type, prettyType))
2021-11-03 17:53:25 +01:00
local ct = command.type
if ct == server.commandType.MEM_GET then
processMemoryGet(command)
elseif ct == server.commandType.MEM_SET then
processMemorySet(command)
elseif ct == server.commandType.CHECKPOINT_GET then
processCheckpointGet(command)
elseif ct == server.commandType.CHECKPOINT_SET then
processCheckpointSet(command)
elseif ct == server.commandType.CHECKPOINT_DELETE then
processCheckpointDelete(command)
elseif ct == server.commandType.CHECKPOINT_LIST then
processCheckpointList(command)
elseif ct == server.commandType.CHECKPOINT_TOGGLE then
processCheckpointToggle(command)
elseif ct == server.commandType.REGISTERS_GET then
processRegistersGet(command)
elseif ct == server.commandType.REGISTERS_SET then
processRegistersSet(command)
--[[
elseif ct == server.commandType.DUMP then
processDump(command)
elseif ct == server.commandType.UNDUMP then
processUndump(command)
]]
2021-11-03 17:53:25 +01:00
elseif ct == server.commandType.ADVANCE_INSTRUCTIONS then
processAdvanceInstructions(command)
2021-11-05 10:42:26 +01:00
elseif ct == server.commandType.EXECUTE_UNTIL_RETURN then
processExecuteUntilReturn(command)
2021-11-03 17:53:25 +01:00
elseif ct == server.commandType.PING then
processPing(command)
2021-11-04 00:24:50 +01:00
elseif ct == server.commandType.REGISTERS_AVAILABLE then
processRegistersAvailable(command)
2021-11-04 00:48:47 +01:00
elseif ct == server.commandType.BANKS_AVAILABLE then
processBanksAvailable(command)
2021-11-04 03:55:06 +01:00
elseif ct == server.commandType.DISPLAY_GET then
processDisplayGet(command)
2021-11-03 17:53:25 +01:00
elseif ct == server.commandType.EXIT then
processExit(command)
elseif ct == server.commandType.RESET then
processReset(command)
else
server.errorResponse(server.errorType.CMD_INVALID_TYPE, command.requestId)
2021-11-05 10:21:34 +01:00
print(string.format("unknown command: %02x, skipping command length %d", command.type, command.length))
2021-11-03 17:53:25 +01:00
end
print(string.format("Command finished: %02x", command.type))
end
function trapHandle(trap)
2021-11-03 18:21:17 +01:00
if server.conn == nil then
2021-11-03 17:53:25 +01:00
return
end
2021-11-04 03:55:06 +01:00
responseCheckpointInfo(server.EVENT_ID, trap, true)
2021-11-03 17:53:25 +01:00
if trap.stop then
me.monitorOpened()
2021-11-04 03:55:06 +01:00
else
2021-11-03 17:53:25 +01:00
return
end
if server.running then
server.running = false
server.deregisterFrameCallback()
print("Break called by trap")
emu.breakExecution()
end
2021-11-03 17:53:25 +01:00
end
return me
end