User File #17415080449457385

Upload All User Files

#17415080449457385 - GBA Kingdom Hearts: Chain of Memories -- Object listing script

KH_mem.lua
638 downloads
Uploaded 9/15/2014 6:35 AM by FatRatKnight (see all 245)
The script attempts to identify whether combat has taken place, and if so, attempts to list out every object within it.
That's all it does. The strings are extracted from the game itself, and the script doesn't really do anything else. It's a proof of concept that I am able to get access to what's going on in there.
As a bonus, the script has some commented out piece of code. Remove the comment markers, then run the script. I haven't looked too hard at this generated list, but there might be some interesting things to look at. It's all in hexadecimal, and the six massive numbers would be memory pointers, not actual data in and of itself.
local R1u= memory.readbyte
local R2s= memory.readwordsigned
local R4s= memory.readdwordsigned

--*****************************************************************************
local function GetString(addr)
--*****************************************************************************
    local str= ""
    local v= R1u(addr)
    local c= 0
    while v ~= 0 do
        str= str .. string.char(v)
        c= c+1
        v= R1u(addr + c)
    end
    return str
end

--*****************************************************************************
local function ObjCount()
--*****************************************************************************
    local addr= 0x02000000
    local count
    local PrizeCard= 0
    local Handler= 0
    for i= 1, 10000 do
        addr= R4s(addr+0x10) -- Get next pointer
        if addr == 0 then  count= i; break end

        if (R4s(addr) <= -0x24) and (R4s(addr+0x20) == 0x09EE7650) then
            PrizeCard= PrizeCard+1
        end
--09EE77A4  Heartless Card
--09EDAED0  task_pause
        if (R4s(addr) <= -0x24) then
            Handler= Handler+1
            gui.text(50,Handler*8,string.format("%8X",addr))
        end
    end

    gui.text(2, 2,count or "Too many")
    gui.text(2,10,PrizeCard)
    gui.text(2,18,Handler)
end
--gui.register(ObjCount)


--*****************************************************************************
local function LocateCombatAddr()
--*****************************************************************************
    local addr= R4s(0x02039B84)

--This is the limits of my error checking. Make sure I'm looking correctly!
    if addr == 0                     then return false end -- No combat
    if R4s(addr-0x20) ~= -0x200      then return false end -- Wrong size
    if R4s(addr-0x08) ~=  0x081213DC then return false end -- ptr not in use

    return addr
end

--*****************************************************************************
local function ListTasks(addr,ScrX,clr,nul)
--*****************************************************************************
local PANIC= 0  -- Failsafe to kill script in case something horrible happens
    local count= 0
    while addr ~= 0 do
        local obj= R4s(addr) -- Getting pointer to... More pointers

        if R4s(obj) == 0 then  gui.text(ScrX,count*6,"null",nul)
        else gui.text(ScrX,count*6,GetString(R4s(R4s(obj))),clr)
        end
        count= count+1

        addr= R4s(addr+8) -- Getting pointer to next

PANIC= PANIC+1; if PANIC >= 1200 then error("FRK did something wrong!") end
    end  --Object count typically less than 20; 1200 should be a safe limit.
end

--*****************************************************************************
local function CombatScan()
--*****************************************************************************
    local addr= LocateCombatAddr()
    if not addr then return end

    local count= 0

    ListTasks(R4s(addr+0x34),  0,0x00FFFFFF,0xFF2000FF)
    ListTasks(R4s(addr+0x48),100,0xFFFF00FF,0xFF2000FF)

    return true
end
gui.register(CombatScan)



--[[
--This generates a card list. Uncomment this block to see it.
--It'll show up in the Output Console. Copy/paste that to Notepad!

--*****************************************************************************
local function GetString_word(addr,len)
--*****************************************************************************
    local str= ""
    for i= 0, len-1 do
        local v= R1u(addr + 2*i)
        if v == 0 then break end
        str= str .. string.char(v)
    end
    str= str .. string.rep(" ",len-#str)
    return str
end

print("=============")
for i= 0, 949 do
    local addr= 0x08F70AB0 + i*0x34

    print(string.format("%8X %8X %8X %17s %8X %8X %8X|%2X %2X %X:%4X:%4X %4X %4X %4X",
        R4s(addr+0x00),
        R4s(addr+0x04),
        R4s(addr+0x08),
        GetString_word(R4s(addr+0x0C)),
        R4s(addr+0x10),
        R4s(addr+0x14),
        R4s(addr+0x18),

        R2s(addr+0x1C),R2s(addr+0x1E),R2s(addr+0x20),
        R2s(addr+0x24),               R2s(addr+0x28),R2s(addr+0x2A),
        R2s(addr+0x2C),R2s(addr+0x2E)
    ))
end
]]--
-- In case you're having trouble, this is the end of my commented block.


--[[
02039B84 - Combat pointer. Find the combat structure (usually 02033E00)

Combat structure[size=0x1E0 + 0x20(heap header)]
-020[0x20] Heap header
+000,4s Cam X (actual, after limits applied)
+004,4s Cam Y
+008,4s Cam X (before limits applied)
+00C,4s Cam Y
+010,4s Cam X (Around where Sora is, it's slowly panning to here)
+014,4s Cam Y
+018,2x (timer)
+01A,2x (timer, probably for zoom)
+01C,4x
+020,4x
+024,4x Zoom
+028,4x Desired zoom
+02C,4x ptr Obj_all_start
+030,4x ptr Obj_all_end
+034,4x ptr Obj_active_start  [obj,prev,next]
+038,4x ptr Obj_active_end
+03C,4x ptr Obj task_btl_sora
+040,4x ptr HUD_all_start
+044,4x ptr HUD_all_end
+048,4x ptr HUD_active_start
+04C,4x ptr HUD_active_end
+050,4x ptr HUD_???
+054,4x ptr
+058,4x ptr
+05C,4x ptr
+060,4x ptr
+064,4x ptr
+068,4x data
+06C,4x data
+070,4
+074,4x data
+078,4x ptr (Sora attack?)
+07C,4x ptr
+080,4
+084,4
+088,4x ptr (enemy next?)
+08C,4x ptr (enemy prev?)
+090,4
+094,4
+098,4
+09C,4
+0A0,4
+0A4,4
+0A8,4x ptr
+0AC,4x ptr (rather temporary)
+0B0,4
+0B4,4
+0B8,4
+0BC,4
+0C0,4
+0C4,4
+0C8,4
+0CC,4
+0D0,4
+0D4,4
+0D8,4
+0DC,4
+0E0,4
+0E4,4
+0E8,4
+0EC,4
+0F0,4
+0F4,4
+0F8,4
+0FC,4
+100,4
+104,4
+108,4
+10C,4
+110,4x ptr (CPU)
+114,4x ptr (CPU)
+118,4
+11C,4
+120,4
+124,4
+128,4
+12C,4
+130,4x Sora X
+134,4x Sora Y
+138,4
+13C,4
+140,4
+144,4
+148,4
+14C,4
+150,4
+154,4
+158,4
+15C,4
+160,4
+164,4
+168,4
+16C,4
+170,4
+174,4
+178,4
+17C,4
+180,4
+184,4
+188,4
+18C,4
+190,4
+194,4
+198,4
+19C,4
+1A0,4
+1A4,4
+1A8,4
+1AC,4
+1B0,4
+1B4,4
+1B8,4
+1BC,4
+1C0,4
+1C4,4
+1C8,4
+1CC,4
+1D0,4
+1D4,4
+1D8,4
+1DC,4

Well, they seem to be happy to use pointers whenever possible.
In the main combat structure, there are pointers to linked lists.
Size of these linked lists is three pointers. Two are used to traverse the list
The first pointer leads to two more pointers: ROM (static) and RAM (dynamic)

The ROM data contains 5 pointers and a four-byte value.
Don't know about these, except the first pointer leads to its internal name.

In any case, I read memory so that I can read other memory to read even more
memory elsewhere. There's way too many pointers in this crazy thing!
]]--