User File #638453505817884095

Upload All User Files

#638453505817884095 - BizHawk script - Log replay file intput frame, emulator-cycle frame, and polling-for-input (TAStudio-like but works with both Gambatte & GBHawk cores) info

movie-frame-list.lua
40 downloads
Uploaded 3/6/2024 7:36 PM by Deadcode (see all 13)
Works with both Gambatte and GBHawk cores (by reimplementing lag-frame detection in the latter using a bus-read hook).
Tested with the following BizHawk versions:
  • 2.3.2 (GBHawk)
  • 2.5.2 (GBHawk)
  • 2.9.1 (GBHawk and Gambatte)
function isVersionOrLater(major, minor, patch)
    local major0, minor0, patch0 = client.getversion():match("(%d+)%.(%d+)%.(%d+)")
    major0 = tonumber(major0)
    if major0 ~= major then
        return major0 > major
    end
    minor0 = tonumber(minor0)
    if minor0 ~= minor then
        return minor0 > minor
    end
    return tonumber(patch0) >= patch
end

function formatInput(input)
    local formattedString = ""
    for key, value in pairs(input) do
        if value then
            if formattedString ~= "" then
                formattedString = formattedString .. ", "
            end
            formattedString = formattedString .. key
        end
    end
    return formattedString
end

function my_joypad_getwithmovie()
    return movie.getinput(emu.framecount() - 1)
end

function inputHookSimple()
    didntReadInput = false
end

function inputHookFancy()
    readTime = emu.totalexecutedcycles() / 70224 - emu.framecount()
    if readInputFirst == nil then
        readInputFirst = readTime
    end
    readInputLast = readTime
end

logfile = nil
movieCore = nil
didntReadInput = true
readInputFirst = nil
readInputLast = nil
joypad_getwithmovie = isVersionOrLater(2,9,1) and joypad.getwithmovie or my_joypad_getwithmovie
event_on_bus_read = isVersionOrLater(2,9,0) and event.on_bus_read or event.onmemoryread

function logFrame()
    local emuFrame = emu.framecount()
    local emuCycle = emu.totalexecutedcycles()
    local isLagged = emu.islagged()
    if movieCore == "Gambatte" then
        emuFrame = emuFrame - 5
        emuCycle = emuCycle * 2 - 53476
    else
        isLagged = didntReadInput
        didntReadInput = true
    end
    local lagIndicator
    if useFancyIndicator then
        lagIndicator = readInputFirst~=nil and string.format("[%8.5f..%8.5f]", readInputFirst, readInputLast) or "                    "
    else
        lagIndicator = isLagged and " " or "!"
    end
    logfile:write(string.format("%6d, %12.6f: %s %s\n",
        emuFrame,
        emuCycle / 70224,
        lagIndicator,
        formatInput(joypad_getwithmovie()))
        )
    readInputFirst = nil
    logfile:flush()
end

local lastFrame
local lastMovie = nil
local finished
local busHookID = nil
while true do
    if movie.isloaded() and movie.mode() ~= "FINISHED" then
        if emu.framecount() == 0 and (finished or lastFrame ~= 0 or movie.filename() ~= lastMovie) then
            if logfile ~= nil then
                logfile:close()
            end
            if busHookID ~= nil then
                event.unregisterbyid(busHookID)
                busHookID = nil
            end
            lastMovie = movie.filename()
            logfile = io.open(lastMovie .. ".frame-list.txt", "w")
            movieCore = movie.getheader()["Core"]
            useFancyIndicator = movieCore ~= "Gambatte"
            if useFancyIndicator then
                busHookID = event_on_bus_read(useFancyIndicator and inputHookFancy or inputHookSimple, 0xFF00)
            end
            finished = false
        elseif logfile ~= nil and emu.framecount() ~= lastFrame then
            logFrame()
        end
        lastFrame = emu.framecount()
    elseif logfile ~= nil then
        if movie.isloaded() and emu.framecount() ~= lastFrame and not finished then
            logFrame()
            finished = true
        end
        if not movie.isloaded() or finished then
            logfile:close()
            logfile = nil
            if busHookID ~= nil then
                event.unregisterbyid(busHookID)
                busHookID = nil
            end
        end
    end
    emu.yield()
end