User File #73827119493636426

Upload All User Files

#73827119493636426 - Sync Scripts - Find Syncing Savestates

sync-savestates.lua
Game: Unknown Game ( NES, see all files )
150 downloads
Uploaded 8/29/2021 7:24 PM by Zinfidel (see all 12)
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