See Zinfidel/SyncScripts.html for usage.
This script looks for desyncs and asks for syncing savestates.
package.path = package.path .. ';luasocket/lua/?.lua;luasocket/lua/socket/?.lua'
package.cpath = package.cpath .. ';luasocket/?.dll;luasocket/mime/?.dll;luasocket/socket/?.dll'
local socket = require 'socket'
local tab = {} -- entire parsed file broken into lines
local gap_minimum = 10 -- Set the minimum number of frames between savestates. This can help prevent thrashing in bad sections.
function ParseFile()
print("Parsing file...")
local logfile = io.open("log.txt", "r")
local char
repeat
char = logfile:read("*l")
table.insert(tab, char)
until char == nil
logfile:close()
print("File parsed! Line count: "..#tab.."\n")
end
-- Customize this function to retrieve your sync data and format it the same way as it appears in log.txt. An example of how
-- to do this for N64 Star Wars Episode 1: Racer, matching the example in sync-collect.lua, is the default implementation. this
-- value will get compared, as a string, to the corresponding line in log.txt to verify sync.
function GetData()
Racedata = 0x118F90
Statedata = mainmemory.read_u24_be(Racedata+0x84+0x1)
SyncData = {}
MatrixStart = Statedata + 0x1C
for i=0, 15, 1 do
table.insert(SyncData, string.format("%.5f",mainmemory.readfloat(MatrixStart + 4*i, true)))
end
return table.concat(SyncData, ",")
end
-- Pause the client and establish a tcp connection to the server.
client.pause()
local tcp = assert(socket.connect("127.0.0.1", 45678), "Socket client failed to establish tcp connection with server. Script aborted.")
console.write("Connection to server established!\n")
tcp:settimeout(2)
emu.yield()
ParseFile()
local onExitEvent = event.onexit(
function()
console.log("\nScript exiting. Sending quit command to server." );
tcp:send("quit\n")
end
, "OnExit" );
local last_ss = 0
while true do
local frame = emu.framecount()
local original = tab[frame+1]
local yours = GetData()
gui.pixelText(0, 40, string.format( "%s - original\n%s - yours", original, yours))
-- mismatch
if (yours ~= original) and ((frame - last_ss) > gap_minimum) then
last_ss = frame
client.pause()
-- screen and console alarm
gui.pixelText(0, 40, string.format( "%s - original\n%s - yours\ndesync at frame %d", original, yours, frame), "red")
print(string.format( "desync at frame %d\n%s\n%s\n", frame, yours, original))
emu.yield()
local response = ""
tcp:send(frame .. ".State\n")
console.write("Sent packet asking for frame " .. tostring(frame) .. " ...")
emu.yield()
while true do
local line, err, partial = tcp:receive()
if not err then
response = line
console.log("\nReceived message that savestate " .. tostring(frame) .. " is available. Loading ...")
emu.yield()
savestate.load(response)
client.unpause()
break
elseif err == "timeout" then
response = response .. partial
console.write('.')
elseif err == "closed" then
console.log("\nConnection with server closed. Exiting now.")
break
else
console.log("\nUnknown communication error.")
end
emu.yield()
end
end
-- so far so good
emu.frameadvance()
end