Thread: Development: Lua? In MY emulator?
View Single Post
  #2    
Old February 8th, 2013 (01:44 PM). Edited February 8th, 2013 by knizz.
knizz's Avatar
knizz knizz is offline
Team Kalos
 
Join Date: Aug 2007
Posts: 192
UPDATE: The building process for linux users should be fully automated now.

Here's a test-file you can use with my emulator. Put it in the top folder of the project and name it… "pokemon.lua" maybe. Launch the emulator with 'vbam -l firered.gba' in the top folder, press F11, type 'require "pokemon"'. Resume emulation with Ctrl+D. You should see lots of debug output now. (PROFIT!)
Code:
-- Usage:
--  require "pokemon"
--  Ctrl+D

require "bkpt"
bit = require "bit"
stack = require "stack"
stack.over = {}

mute_c3 = false

function pwrite(x)
    io.write(string.format("%-80s", x))
    printtrace()
end

function c3_init_enter()
    print("\n======== RESET C3 ========\n")
    mute_c3 = true
end

function c3_init_leave()
    mute_c3 = false
end

function c3watch_trigger(self, a, b, c)
    if mute_c3 then return end
    local space = ""
    for i=1,self.id do space = space.."            " end
    if a == 0 then
        pwrite(space..string.format("#%02x ", self.id) .. ref(c))
    elseif a == 4 then
        pwrite(space..string.format("#%02x ", self.id) .. (c==1 and "ON" or "OFF"))
    end
end

function dp01watch_trigger(self, a, b, c)
    local space = ""
    for i=1,self.id do space = space.."       " end
    pwrite("DP01 ==== "..space..ref(c))
end

in_script = false
function script_enter() in_script = true  end
function script_leave() in_script = false end
function script_env_trigger(self, a, b, c)
    -- a = offset
    -- b = old value
    -- c = new value
    if a >= 0x74 then
        return
    end
    if a == 0x5C and c ~= 0x0815F9B4 then
        print("!!!!!!!!!!!!!!!!!!!!!!!!!!!")
        print(string.format("New script command table @ %08x", c))
    end
    if not in_script then
        print(string.format("untracked change 0x%08x+%02x %x->%x", self.start, a, b, c))
        printtrace()
    end
end
function script_desc()
    local p = gba.reg(4)
    return string.format("scriptenv %08x @ %08x ", p, gba.mem32(p+8))
end
function script_cmd()
    print(script_desc().."cmd: "..ref(gba.reg(1)))
end
function script_env_init()
    in_script = true
    pwrite(string.format("scriptenv %08x @ reset", gba.reg(4)))
end
function script_status_normal()
    in_script = true
    pwrite(string.format("scriptenv %08x @ %08x LAUNCH", gba.reg(0), gba.reg(1)))
end
function oamt_spawn_from_uns_2()
    pwrite(string.format("OAMt from UNS 2 %08x", gba.reg(0)))
end
function oamt_spawn_from_uns_1()
    pwrite(string.format("OAMt from UNS 1 %08x", gba.reg(0)))
end

-- -- -- -- -- -- -- --

function watch_array(start, count, size, trigger)
    for i=0,count do
        local nw = {}
        nw.id = i
        nw.start = start + size*i
        nw.stop =  start + size*(i+1)
        nw.trigger = trigger
        table.insert(watch, nw)
    end
    gba.oldapi("bpw", string.format("0x%08x", start), string.format("%d", count*size))
end

function watch_simple(pos, size, msg)
    function pp(self, a, b, c)
        pwrite(string.format("%s: %08x+%x: ", msg, self.start, a)..ref(b).." -> "..ref(c))
    end
    local nw = {}
    nw.start = pos
    nw.stop = pos + size
    nw.trigger = pp
    table.insert(watch, nw)
    gba.oldapi("bpw", string.format("0x%08x", pos), string.format("%d", size))
end

function regmodpoint(addr, reg, value)
    function modder()
        gba.reg(reg, value)
    end
    table.insert(bkpts.inactive, addr)
    bkpts.callback[addr] = modder
end

-- -- -- -- -- -- -- --

function install()
    bkpts:add(0x080773BC, c3_init_enter)
    bkpts:add(0x0807740C, c3_init_leave)
    bkpts:add(0x08069804, script_enter)
    bkpts:add(0x0806986E, script_cmd)
    bkpts:add(0x0806987C, script_leave)
    bkpts:add(0x080697AC, script_env_init)
    bkpts:add(0x080697E2, script_leave)
    bkpts:add(0x080697E8, script_status_normal)
    bkpts:add(0x080697F0, script_leave)
    bkpts:add(0x08006F8C, oamt_spawn_from_uns_1)
    bkpts:add(0x08006FE0, oamt_spawn_from_uns_2)

    watch_array(0x03005090, 16, 0x28, c3watch_trigger)
    watch_array(0x03000eb0,  2, 0x78, script_env_trigger)
    watch_array(0x03004FE0, 4, 4, dp01watch_trigger)
    watch_simple(0x03005020, 4, "map loader")
    -- watch_simple(0x030030F0, 8)
    -- watch_simple(0x02023D74, 4)
    -- watch_simple(0x03004F84, 4)

    add_tracepoint(0x08035AC0, "                               ------------AC0", 1)
    -- add_tracepoint(0x0800D8B0, "load dp01 buffer", 1)
    -- add_tracepoint(0x08014068, "", 0)
    -- add_tracepoint(0x08012408, "c1_battle_dp01_bx_r0", 0)

    bkpts:enable()

    -- You probably don't have this file.
    -- loadnames("firered.map")
end

-- -- -- -- -- -- -- --

names = {}

function ref(addr)
    local addr = bit.band(addr, bit.bnot(1))
    return names[addr] or string.format("%08x", addr)
end

function loadnames(fname)
    for line in io.lines(fname) do
        k, v = string.match(line, ":(%x+)       (.+)")
        if k ~= nil then
            names[tonumber(k, 16)+0x08000000] = v
        end
    end
end

-- -- -- -- -- -- -- --

function introskipper()
    gba.mem32(0x080EC5D0, 0x0800C301)
    gba.mem32(0x0800C4C4, 0x08056645)
    gba.mem32(0x080EC5D0, 0x0800C301)
    gba.mem32(0x0800C4C4, 0x08056645) -- Player Name: Kamon
    gba.mem32(0x08054A68, 0x68204C3C)
    gba.mem32(0x08054A6C, 0xE0014900)
    gba.mem32(0x08054A70, 0x081C5797)
    gba.mem16(0x08054A7E, 0x4E34)
    gba.mem16(0x08054B3A, 0x0000)
    gba.mem16(0x08054B3C, 0x0000)
end

-- -- -- -- -- -- -- --

install()
introskipper()
I can't really explain all of it right now. I hope you can figure it out from the lua-files.
__________________
Firered IDA 6.5 DB: https://www.dropbox.com/s/hvvmxxoo1dkmdzc/firered.idb
VBA-M with lua scripting support
Reply With Quote