Skip to content

[Request] Memory searching functionality for Lua scripts #4760

Description

@Davidebyzero

As far as I can tell, there's no built-in memory search function in BizHawk Lua. So you either have to use the RAM Search UI and manually copy that into a script, or implement a search loop in Lua.

Here is an example, which I am using to display the current Worms Armageddon game engine time (using the DOSBox-X core). It works, but takes about 9 seconds even when the search is successful. On the bright side, it only has to be done once per started game round, but that's still somewhat inconvenient, and surely there are other TASes for which even more searching would be needed.

The built-in function should allow the memory domain and address range to be specified, along with the size of the needle in bytes (8 bytes in my example), and alignment (4 bytes in my example). Its implementation could then perhaps optimize by specializing for commonly used combinations of needle size and alignment (so that it doesn't have to be slowed down by using variables for those), e.g. by using templated code.

addr = 0

tastudio.addcolumn("time", "Time", 60)
local cache = {}

local id
id = event.onframeend(function()
    local needle0 = 0x5755D0
    local needle1 = 0x800

    if memory.read_u32_le(addr, "Physical RAM") ~= needle0 then -- or memory.read_u32_le(addr+4, "Physical RAM") ~= needle1 then
        local data = memory.read_bytes_as_array(0, 0x03000000, "Physical RAM")

        addr = 0
        for i = 0, #data - 8, 4 do
            local w0 = data[i+1] + (data[i+2] << 8) + (data[i+3] << 16) + (data[i+4] << 24)
            if w0 == needle0 then
                local w1 = data[i+5] + (data[i+6] << 8) + (data[i+7] << 16) + (data[i+8] << 24)
                if w1 == needle1 then
                    addr = i
                    console.log(string.format("Found at: 0x%08X", addr))
                    break
                end
            end
        end
    end
    if addr == 0 then
        event.unregisterbyid(id)
    else
        local value = memory.read_u32_le(addr + 8, "Physical RAM")
        msg = string.format("%d.%02d", value // 50, (value % 50) * 2)
        cache[emu.framecount()] = msg
        gui.text(1, 27, msg)
    end
end)

tastudio.onqueryitemtext(function(frame, column)
    if column == "time" then
        return cache[frame] or "?"
    end
end)

Metadata

Metadata

Assignees

No one assigned

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions