Created
April 18, 2026 14:03
-
-
Save TheLeftExit/1f0577ec65bfc753a02c1f1afe45de3a to your computer and use it in GitHub Desktop.
Chao Memory solver v2 (mGBA script)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| if cbid then | |
| return | |
| end | |
| buffer = console:createBuffer("Test buffer") | |
| function indexof(t, v) | |
| for key, value in pairs(t) do | |
| if value == v then | |
| return key | |
| end | |
| end | |
| end | |
| function processFrameCore() | |
| local cardState = emu:read8(0x030019DC) -- 0..1: number of visible cards, else: waiting | |
| if cardState > 1 then return end | |
| local cursorX = emu:read8(0x030019AE) -- 0..5 | |
| local cursorY = emu:read8(0x030019AF) -- 0..4 | |
| local revealedCardX = emu:read8(0x030019EA) -- 0..5 | |
| local revealedCardY = emu:read8(0x030019EB) -- 0..4 | |
| local cardDataRaw = emu:readRange(0x03001990, 30) -- flattened 6x5 map (00..0D, FF) | |
| local cardData = {} | |
| for i = 0, 29 do | |
| cardData[i] = string.byte(cardDataRaw, i + 1) | |
| end | |
| -- find next target | |
| local targetPosition | |
| if cardState == 1 then | |
| -- find the matching card | |
| local revealedCardId = cardData[revealedCardY * 6 + revealedCardX] | |
| local targetId | |
| if revealedCardId % 2 == 0 then | |
| targetId = revealedCardId + 1 | |
| else | |
| targetId = revealedCardId - 1 | |
| end | |
| targetPosition = indexof(cardData, targetId) | |
| console:log("Revealed card: "..tostring(revealedCardId)) | |
| console:log("Matching card: "..tostring(targetId).." at "..tostring(targetPosition)) | |
| else | |
| -- find the closest remaining card | |
| local targetDistance = 10 | |
| for position, id in pairs(cardData) do | |
| local x = position % 6 | |
| local y = position // 6 | |
| local distance = math.abs(x - cursorX) + math.abs(y - cursorY) | |
| if id ~= 255 and distance < targetDistance then | |
| targetPosition = position | |
| targetDistance = distance | |
| end | |
| end | |
| console:log("Closest card at: "..tostring(targetPosition)) | |
| end | |
| for position, id in pairs(cardData) do | |
| buffer:moveCursor((position % 6) * 3, position // 6) | |
| if(id ~= 255) then | |
| buffer:print(tostring(id)) | |
| else | |
| buffer:print("--") | |
| end | |
| buffer:moveCursor(0, 5) | |
| buffer:print("Going to " .. tostring(targetPosition % 6) .. "," .. tostring(targetPosition // 6)) | |
| end | |
| local deltaX = (targetPosition % 6) - cursorX | |
| local deltaY = (targetPosition // 6) - cursorY | |
| if deltaX < 0 then | |
| emu:addKey(C.GBA_KEY.LEFT) | |
| elseif deltaX > 0 then | |
| emu:addKey(C.GBA_KEY.RIGHT) | |
| elseif deltaY < 0 then | |
| emu:addKey(C.GBA_KEY.UP) | |
| elseif deltaY > 0 then | |
| emu:addKey(C.GBA_KEY.DOWN) | |
| else | |
| emu:addKey(C.GBA_KEY.A) | |
| end | |
| end | |
| function processFrame() | |
| buffer:clear() | |
| if(emu:getKey(C.GBA_KEY.B) ~= 0) then | |
| buffer:setName("Discarded buffer") | |
| callbacks:remove(cbid) | |
| emu:setKeys(0) | |
| cbid = nil | |
| return | |
| end | |
| -- if we just pressed something, release and skip frame - effectively turboing the key | |
| if(emu:getKeys() ~= 0) then | |
| emu:setKeys(0) | |
| return | |
| end | |
| gameState = emu:read8(0x030019D8) | |
| if gameState == 00 then -- Not in memory game | |
| buffer:print("Not in Chao Memory") | |
| emu:addKey(C.GBA_KEY.A) | |
| elseif gameState == 06 then | |
| processFrameCore() | |
| else | |
| buffer:print("Waiting in Chao Memory") | |
| end | |
| end | |
| cbid = callbacks:add("frame", processFrame) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment