From 14d9ac48034b90c2d1f094f5ae21c0b78759f23f Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Sat, 5 Nov 2022 13:23:16 -0400 Subject: [PATCH 01/10] beginning of total rewrite --- hook.lua | 337 +++---------------------------------------------------- 1 file changed, 18 insertions(+), 319 deletions(-) diff --git a/hook.lua b/hook.lua index fbc368d..d199ac9 100644 --- a/hook.lua +++ b/hook.lua @@ -91,15 +91,21 @@ rcodes = { function format_response(code, message) emu.frameadvance() + -- Format response code and message into a valid response return tostring(code) .. '_' .. tostring(message) end +function bullshit() + console.log("test test test") +end local function handleRequest(data) -- Handle incoming requests for reading from -- and writing to memory with the BizHawk emulator + + domain, address, type, signage, size, endianness, value = data:match('^([%w%s]*)%/(%d+)%/([bif])([us])([1234])([lb])%/(-?%d*%.?%d*)$') @@ -111,330 +117,22 @@ local function handleRequest(data) -- Convert address to integer address = tonumber(address) - - -- local function format_response(code, message) - -- -- Format response code and message into a valid response - -- return tostring(code) .. '_' .. tostring(message) - -- end - - - -- [ READ ] - if value == "" then - - -- [ BYTE ] - if type == 'b' then - return format_response( - rcodes.BYTE, - memory.readbyte(address, domain) - ) - end - - - -- [ INTEGER ] - if type == 'i' then - - -- [ UNSIGNED ] - if signage == 'u' then - - -- [ 1 BYTE ] - if size == '1' then - return format_response( - rcodes.INTEGER, - memory.read_u8(address, domain) - ) - end - - -- [ LITTLE ENDIAN ] - if endianness == 'l' then - - -- [ 2 BYTE ] - if size == '2' then - return format_response( - rcodes.INTEGER, - memory.read_u16_le(address, domain) - ) - - -- [ 3 BYTE ] - elseif size == '3' then - return format_response( - rcodes.INTEGER, - memory.read_u24_le(address, domain) - ) - - -- [ 4 BYTE ] - elseif size == '4' then - return format_response( - rcodes.INTEGER, - memory.read_u32_le(address, domain) - ) - end - end - - -- [ BIG ENDIAN ] - if endianness == 'b' then - - -- [ 2 BYTE ] - if size == '2' then - return format_response( - rcodes.INTEGER, - memory.read_u16_be(address, domain) - ) - - -- [ 3 BYTE ] - elseif size == '3' then - return format_response( - rcodes.INTEGER, - memory.read_u24_be(address, domain) - ) - - -- [ 4 BYTE ] - elseif size == '4' then - return format_response( - rcodes.INTEGER, - memory.read_u32_be(address, domain) - ) - end - end - end - - -- [ SIGNED ] - if signage == 's' then - - -- [ 1 BYTE ] - if size == '1' then - return format_response( - rcodes.INTEGER, - memory.read_s8(address, domain) - ) - end - - -- [ LITTLE ENDIAN ] - if endianness == 'l' then - - -- [ 2 BYTE ] - if size == '2' then - return format_response( - rcodes.INTEGER, - memory.read_s16_le(address, domain) - ) - - -- [ 3 BYTE ] - elseif size == '3' then - return format_response( - rcodes.INTEGER, - memory.read_s24_le(address, domain) - ) - - -- [ 4 BYTE ] - elseif size == '4' then - return format_response( - rcodes.INTEGER, - memory.read_s32_le(address, domain) - ) - - end - end - - -- [ BIG ENDIAN ] - if endianness == 'b' then - - -- [ 2 BYTE ] - if size == '2' then - return format_response( - rcodes.INTEGER, - memory.read_s16_be(address, domain) - ) - - -- [ 3 BYTE ] - elseif size == '3' then - return format_response( - rcodes.INTEGER, - memory.read_s24_be(address, domain) - ) - - -- [ 4 BYTE ] - elseif size == '4' then - return format_response( - rcodes.INTEGER, - memory.read_s32_be(address, domain) - ) - - end - end - end - end - - -- [ FLOAT ] - if type == 'f' then - -- Whether the value is big endian or not - bigendian = endianness == 'b' - - return format_response( - rcodes.FLOAT, - memory.readfloat(address, bigendian, domain) - ) - end + -- [ INPUT ] + if domain == "" then - -- [ WRITE ] else - - -- Convert value to number - value = tonumber(value) - - - -- [ BYTE ] - if type == 'b' then - return format_response( - rcodes.WRITTEN, - memory.writebyte(address, value, domain) - ) - end - - - -- [ INTEGER ] - if type == 'i' then - - -- [ UNSIGNED ] - if signage == 'u' then - - -- [ 1 BYTE ] - if size == '1' then - return format_response( - rcodes.WRITTEN, - memory.write_u8(address, value, domain) - ) - end - - -- [ LITTLE ENDIAN ] - if endianness == 'l' then - - -- [ 2 BYTE ] - if size == '2' then - return format_response( - rcodes.WRITTEN, - memory.write_u16_le(address, value, domain) - ) - - -- [ 3 BYTE ] - elseif size == '3' then - return format_response( - rcodes.WRITTEN, - memory.write_u24_le(address, value, domain) - ) - - -- [ 4 BYTE ] - elseif size == '4' then - return format_response( - rcodes.WRITTEN, - memory.write_u32_le(address, value, domain) - ) - end - end - - -- [ BIG ENDIAN ] - if endianness == 'b' then - - -- [ 2 BYTE ] - if size == '2' then - return format_response( - rcodes.WRITTEN, - memory.write_u16_be(address, value, domain) - ) - - -- [ 3 BYTE ] - elseif size == '3' then - return format_response( - rcodes.WRITTEN, - memory.write_u24_be(address, value, domain) - ) - - -- [ 4 BYTE ] - elseif size == '4' then - return format_response( - rcodes.WRITTEN, - memory.write_u32_be(address, value, domain) - ) - end - end - end - - -- [ SIGNED ] - if signage == 's' then - - -- [ 1 BYTE ] - if size == '1' then - return format_response( - rcodes.WRITTEN, - memory.write_s8(address, value, domain) - ) - end - - -- [ LITTLE ENDIAN ] - if endianness == 'l' then - - -- [ 2 BYTE ] - if size == '2' then - return format_response( - rcodes.WRITTEN, - memory.write_s16_le(address, value, domain) - ) - - -- [ 3 BYTE ] - elseif size == '3' then - return format_response( - rcodes.WRITTEN, - memory.write_s24_le(address, value, domain) - ) - - -- [ 4 BYTE ] - elseif size == '4' then - return format_response( - rcodes.WRITTEN, - memory.write_s32_le(address, value, domain) - ) - end - end - - -- [ BIG ENDIAN ] - if endianness == 'b' then - - -- [ 2 BYTE ] - if size == '2' then - return format_response( - rcodes.WRITTEN, - memory.write_s16_be(address, value, domain) - ) - - -- [ 3 BYTE ] - elseif size == '3' then - return format_response( - rcodes.WRITTEN, - memory.write_s24_be(address, value, domain) - ) - - -- [ 4 BYTE ] - elseif size == '4' then - return format_response( - rcodes.WRITTEN, - memory.write_s32_be(address, value, domain) - ) - end - end + -- [ READ ] + if value == "" then + + -- [ BYTE ] + if type == 'b' then + return format_response( + rcodes.BYTE, + memory.readbyte(address, domain) + ) end end - - -- [ FLOAT ] - if type == 'f' then - - -- Whether the value is big endian or not - bigendian = endianness == 'b' - - return format_response( - rcodes.WRITTEN, - memory.writefloat(address, value, bigendian, domain) - ) - end end @@ -468,6 +166,7 @@ local function clientHandler(client) data = data .. chunk end + if not data then return end From 176c30857720f5aee59cf41209f0db48a0b9ff20 Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Mon, 7 Nov 2022 15:15:53 -0500 Subject: [PATCH 02/10] added .basic gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c9d217d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +### Manual ### +.vscode/** \ No newline at end of file From d0ee4380c593ef9a6e649d8d1397e739cae25c39 Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Mon, 7 Nov 2022 18:54:52 -0500 Subject: [PATCH 03/10] first implimentation of new api --- hook.lua | 67 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/hook.lua b/hook.lua index d199ac9..16ba730 100644 --- a/hook.lua +++ b/hook.lua @@ -88,50 +88,64 @@ rcodes = { ERROR = 4; -- Generic error } +function mysplit (inputstr, sep) + if sep == nil then + sep = "%s" + end + local t={} + for str in string.gmatch(inputstr, "([^"..sep.."]+)") do + table.insert(t, str) + end + return t +end function format_response(code, message) + -- -- console.log(" ") + -- -- console.log("format_response") emu.frameadvance() - + -- console.log("code:", code, "message:", message) -- Format response code and message into a valid response return tostring(code) .. '_' .. tostring(message) end -function bullshit() - console.log("test test test") -end - local function handleRequest(data) -- Handle incoming requests for reading from -- and writing to memory with the BizHawk emulator - + -- console.log(" ") + -- console.log("handleRequest:") + -- -- console.log(data) + + split_data = mysplit(data, '/') + -- console.log("split_data:") + -- console.log(split_data) - domain, address, type, signage, size, endianness, value - = data:match('^([%w%s]*)%/(%d+)%/([bif])([us])([1234])([lb])%/(-?%d*%.?%d*)$') + query_type = tonumber(split_data[1]) + domain = split_data[2] + address = tonumber(split_data[3]) -- Use default domain if none is provided if domain == "" then domain = nil end - - -- Convert address to integer - address = tonumber(address) + -- console.log("query_type:", query_type) + -- console.log("domain:", domain) + -- console.log("address:", address) -- [ INPUT ] - if domain == "" then - + if query_type == 0 then + -- console.log("input") else + -- console.log("read bytes") -- [ READ ] - if value == "" then + if query_type == 1 then -- [ BYTE ] - if type == 'b' then - return format_response( - rcodes.BYTE, - memory.readbyte(address, domain) - ) - end + return format_response( + rcodes.BYTE, + memory.readbyte(address, domain) + ) end end @@ -146,11 +160,15 @@ local function clientHandler(client) -- and processes the data with handleRequest local data = "" + -- -- console.log(" ") + -- -- console.log("handing client") while true do -- Read 1 byte at a time chunk, errmsg = client:receive(1) - + + emu.frameadvance() + -- Quit reading if an error has occured -- or no data was received if not chunk then @@ -174,6 +192,8 @@ local function clientHandler(client) -- and formulate a response response = handleRequest(data) + -- console.log("response", tostring(response)) + if not response then return end -- Make sure response is string @@ -181,9 +201,11 @@ local function clientHandler(client) client:send(tostring(response)) end +console.log("Adding server") copas.addserver(server, clientHandler) +console.log("Displaying socket info") -- Open up socket with a clear sign while emu.framecount() < 600 do @@ -191,6 +213,7 @@ while emu.framecount() < 600 do emu.frameadvance() end +console.log("Done starting socket") while true do -- Communicate with client @@ -200,5 +223,5 @@ while true do end -- Advance the game by a frame - -- emu.frameadvance() + emu.frameadvance() end \ No newline at end of file From d2207a5004aaaecddb3e03467fcbfa6eef56ca89 Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Tue, 8 Nov 2022 15:39:52 -0500 Subject: [PATCH 04/10] lots of extra prints, deep in debugging issue --- hook.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/hook.lua b/hook.lua index 16ba730..bd8566f 100644 --- a/hook.lua +++ b/hook.lua @@ -201,27 +201,30 @@ local function clientHandler(client) client:send(tostring(response)) end -console.log("Adding server") +-- console.log("Adding server") copas.addserver(server, clientHandler) -console.log("Displaying socket info") +-- console.log("Displaying socket info") -- Open up socket with a clear sign -while emu.framecount() < 600 do +while emu.framecount() < 120 do gui.text(20, 20, '.Opening socket at ' .. address .. ':' .. port) emu.frameadvance() end -console.log("Done starting socket") +-- console.log("Done starting socket") while true do -- Communicate with client local handled, errmsg = copas.step(0) + -- if errmsg then + -- console.log("errmsg", errmsg) + -- end if handled == nil then print(('Socket error: %s'):format(errmsg)) end -- Advance the game by a frame - emu.frameadvance() + emu.yield() end \ No newline at end of file From 004a0199a77d3404edb762f875364b915ef5eb4d Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Tue, 8 Nov 2022 15:47:55 -0500 Subject: [PATCH 05/10] got rid of all the commented print statements --- hook.lua | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/hook.lua b/hook.lua index bd8566f..5a325f9 100644 --- a/hook.lua +++ b/hook.lua @@ -100,11 +100,8 @@ function mysplit (inputstr, sep) end function format_response(code, message) - -- -- console.log(" ") - -- -- console.log("format_response") - emu.frameadvance() - -- console.log("code:", code, "message:", message) - -- Format response code and message into a valid response + -- -- emu.frameadvance() + -- Format response code and message into a valid response return tostring(code) .. '_' .. tostring(message) end @@ -112,14 +109,9 @@ local function handleRequest(data) -- Handle incoming requests for reading from -- and writing to memory with the BizHawk emulator - -- console.log(" ") - -- console.log("handleRequest:") - -- -- console.log(data) - + -- split_data = mysplit(data, '/') - -- console.log("split_data:") - -- console.log(split_data) - + query_type = tonumber(split_data[1]) domain = split_data[2] address = tonumber(split_data[3]) @@ -129,16 +121,12 @@ local function handleRequest(data) domain = nil end - -- console.log("query_type:", query_type) - -- console.log("domain:", domain) - -- console.log("address:", address) - + -- [ INPUT ] if query_type == 0 then - -- console.log("input") + console.log("no input function") else - -- console.log("read bytes") - -- [ READ ] + -- [ READ ] if query_type == 1 then -- [ BYTE ] @@ -160,9 +148,7 @@ local function clientHandler(client) -- and processes the data with handleRequest local data = "" - -- -- console.log(" ") - -- -- console.log("handing client") - + -- -- while true do -- Read 1 byte at a time chunk, errmsg = client:receive(1) @@ -192,8 +178,6 @@ local function clientHandler(client) -- and formulate a response response = handleRequest(data) - -- console.log("response", tostring(response)) - if not response then return end -- Make sure response is string @@ -201,19 +185,14 @@ local function clientHandler(client) client:send(tostring(response)) end --- console.log("Adding server") - copas.addserver(server, clientHandler) --- console.log("Displaying socket info") - -- Open up socket with a clear sign while emu.framecount() < 120 do gui.text(20, 20, '.Opening socket at ' .. address .. ':' .. port) emu.frameadvance() end --- console.log("Done starting socket") while true do -- Communicate with client From 8e8b15083a9c1497e528b3dbb4dcf9a4b7c0d1ff Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Tue, 8 Nov 2022 15:51:12 -0500 Subject: [PATCH 06/10] fixed the error caused by bad frameadvance() --- hook.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/hook.lua b/hook.lua index 5a325f9..3e2e7a2 100644 --- a/hook.lua +++ b/hook.lua @@ -153,8 +153,6 @@ local function clientHandler(client) -- Read 1 byte at a time chunk, errmsg = client:receive(1) - emu.frameadvance() - -- Quit reading if an error has occured -- or no data was received if not chunk then From 7189423e93f626caa711c0416e33f484d7889238 Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Tue, 8 Nov 2022 16:52:48 -0500 Subject: [PATCH 07/10] simplified string matching --- hook.lua | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/hook.lua b/hook.lua index 3e2e7a2..ba15247 100644 --- a/hook.lua +++ b/hook.lua @@ -88,33 +88,20 @@ rcodes = { ERROR = 4; -- Generic error } -function mysplit (inputstr, sep) - if sep == nil then - sep = "%s" - end - local t={} - for str in string.gmatch(inputstr, "([^"..sep.."]+)") do - table.insert(t, str) - end - return t -end function format_response(code, message) - -- -- emu.frameadvance() - -- Format response code and message into a valid response + -- emu.frameadvance() + -- Format response code and message into a valid response return tostring(code) .. '_' .. tostring(message) end local function handleRequest(data) -- Handle incoming requests for reading from -- and writing to memory with the BizHawk emulator - - -- - split_data = mysplit(data, '/') + query_type, domain, address = string.match(data, "(%d)%/(.+)%/(.+)%/") - query_type = tonumber(split_data[1]) - domain = split_data[2] - address = tonumber(split_data[3]) + query_type = tonumber(query_type) + address = tonumber(address) -- Use default domain if none is provided if domain == "" then From 2fac05718a0c8dc5653f2dc0c7ef98c6cf8326ff Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Tue, 8 Nov 2022 17:49:34 -0500 Subject: [PATCH 08/10] finally fixed error spam when updating --- hook.lua | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/hook.lua b/hook.lua index ba15247..efe1fc9 100644 --- a/hook.lua +++ b/hook.lua @@ -90,7 +90,7 @@ rcodes = { function format_response(code, message) - -- emu.frameadvance() + emu.frameadvance() -- Format response code and message into a valid response return tostring(code) .. '_' .. tostring(message) end @@ -98,10 +98,10 @@ end local function handleRequest(data) -- Handle incoming requests for reading from -- and writing to memory with the BizHawk emulator - query_type, domain, address = string.match(data, "(%d)%/(.+)%/(.+)%/") + query_type, domain, mem_address = string.match(data, "(%d)%/(.+)%/(.+)%/") query_type = tonumber(query_type) - address = tonumber(address) + mem_address = tonumber(mem_address) -- Use default domain if none is provided if domain == "" then @@ -112,16 +112,14 @@ local function handleRequest(data) -- [ INPUT ] if query_type == 0 then console.log("no input function") - else - -- [ READ ] - if query_type == 1 then - - -- [ BYTE ] - return format_response( - rcodes.BYTE, - memory.readbyte(address, domain) - ) - end + end + -- [ READ ] + if query_type == 1 then + -- [ BYTE ] + return format_response( + rcodes.BYTE, + memory.readbyte(mem_address, domain) + ) end @@ -178,6 +176,9 @@ while emu.framecount() < 120 do emu.frameadvance() end +-- I spent days trying to track down the origin of a mysterious error in copas +-- I've given up and just overriden its error handler as it kills performance +copas.setErrorHandler("", "") while true do -- Communicate with client @@ -190,5 +191,5 @@ while true do end -- Advance the game by a frame - emu.yield() + -- emu.yield() end \ No newline at end of file From cb912fa22e4e1cfd793e67815c6918648524abe8 Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Tue, 8 Nov 2022 17:51:54 -0500 Subject: [PATCH 09/10] removed some extra commented out code --- hook.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hook.lua b/hook.lua index efe1fc9..71998ff 100644 --- a/hook.lua +++ b/hook.lua @@ -183,9 +183,7 @@ copas.setErrorHandler("", "") while true do -- Communicate with client local handled, errmsg = copas.step(0) - -- if errmsg then - -- console.log("errmsg", errmsg) - -- end + if handled == nil then print(('Socket error: %s'):format(errmsg)) end From 83ec02ba11e5debb4d2270dcf5f4c1e823118250 Mon Sep 17 00:00:00 2001 From: huttsMichael Date: Wed, 9 Nov 2022 22:03:18 -0500 Subject: [PATCH 10/10] basic implimentation of passing inputs working --- hook.lua | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/hook.lua b/hook.lua index 71998ff..1bdf4ae 100644 --- a/hook.lua +++ b/hook.lua @@ -78,10 +78,17 @@ copas = require("copas") server = socket.bind(address, port) +-- Query types +qtype = { + INPUT = 0; + READ = 1; + WRITE = 2; + CLIENT = 3 +} -- Response codes rcodes = { - WRITTEN = 0; -- Successfully wrote to memory + INPUT = 0; -- Successfully wrote to memory BYTE = 1; -- Successfully read byte INTEGER = 2; -- Successfully read integer FLOAT = 3; -- Successfully read float @@ -98,10 +105,20 @@ end local function handleRequest(data) -- Handle incoming requests for reading from -- and writing to memory with the BizHawk emulator - query_type, domain, mem_address = string.match(data, "(%d)%/(.+)%/(.+)%/") - + form = tonumber(string.match(data, "(%d)%/.+")) + if form == qtype["INPUT"] then + -- TODO: make a proper lua table + query_type, button_name, button_state = string.match(data, "(%d)%/(.+)%/(.+)%/") + button_table = {} + button_table[button_name] = button_state + -- console.log("Sending Input:") + -- console.log(button_table) + elseif form == qtype["READ"] then + query_type, domain, mem_address = string.match(data, "(%d)%/(.+)%/(.+)%/") + mem_address = tonumber(mem_address) + end + query_type = tonumber(query_type) - mem_address = tonumber(mem_address) -- Use default domain if none is provided if domain == "" then @@ -110,11 +127,14 @@ local function handleRequest(data) -- [ INPUT ] - if query_type == 0 then - console.log("no input function") + if form == qtype["INPUT"] then + return format_response( + rcodes.INPUT, + joypad.set(button_table) + ) end -- [ READ ] - if query_type == 1 then + if form == qtype["READ"] then -- [ BYTE ] return format_response( rcodes.BYTE, @@ -168,18 +188,26 @@ local function clientHandler(client) client:send(tostring(response)) end +console.log("Adding server") + copas.addserver(server, clientHandler) +console.log("Added server") + -- Open up socket with a clear sign while emu.framecount() < 120 do gui.text(20, 20, '.Opening socket at ' .. address .. ':' .. port) emu.frameadvance() end +console.log("Done showing intro") + -- I spent days trying to track down the origin of a mysterious error in copas -- I've given up and just overriden its error handler as it kills performance copas.setErrorHandler("", "") +console.log("Disabled COPAS error handler") + while true do -- Communicate with client local handled, errmsg = copas.step(0)