Skip to content

Instantly share code, notes, and snippets.

@FedericoPonzi
Created January 30, 2026 11:54
Show Gist options
  • Select an option

  • Save FedericoPonzi/b8c20391160d0aafc7b93a37704847a9 to your computer and use it in GitHub Desktop.

Select an option

Save FedericoPonzi/b8c20391160d0aafc7b93a37704847a9 to your computer and use it in GitHub Desktop.
-- mGBA Golden Sun Password Entry Script
-- Position cursor on 'A' before loading this script
console:log("Script loaded!")
--------------------------------------------------------------------------------
-- CONFIGURATION
--------------------------------------------------------------------------------
local INITIAL_DELAY = 60 -- Frames to wait before starting
local PRESS_DELAY = 1 -- Frames between button presses
-- GBA button bitmasks
local BTN = {
A = 1,
RIGHT = 16,
LEFT = 32,
UP = 64,
DOWN = 128
}
--------------------------------------------------------------------------------
-- KEYBOARD LAYOUT (matches Golden Sun password entry screen)
--------------------------------------------------------------------------------
local keyboard = {
{"A","B","C","D","E","F","G","H","J","K","L","M","N","P","Q","R","Space"},
{"S","T","U","V","W","X","Y","Z","2","3","4","5","6","7","8","9","Return"},
{"a","b","c","d","e","f","g","h","i","j","k","m","n","p","q","r"},
{"s","t","u","v","w","x","y","z","!","?","#","&","$","%","+","=","Finish"}
}
local function findChar(char)
if char == "\001" then char = "Finish" end
for y, row in ipairs(keyboard) do
for x, val in ipairs(row) do
if val == char then return x, y end
end
end
return nil, nil
end
--------------------------------------------------------------------------------
-- PASSWORD CODES
--------------------------------------------------------------------------------
local codes =
-- Page 1
"wXCMAJGzWW" .. "38yJk$nB8&" .. "uWxxRrN62v" .. "3P62wGHVfJ" .. "2PJ#RRFAUB" ..
-- Page 2
"=r9bUcHms3" .. "e62pgx%%vU" .. "J3e%S7KFP=" .. "mmX3kPzWbN" .. "jwxHPXQw&P" ..
-- Page 3
"9Wb7=Qa597" .. "VKkLAJQ6Az" .. "+pcub%Y4qa" .. "?65hCuXG#x" .. "&8+MLys=nC" ..
-- Page 4
"b6ZEt$gqp&" .. "V7buZbfy5Y" .. "gk&akq=eqj" .. "vEjvzJpz&y" .. "Pu$ATyAEXS" ..
-- Page 5
"&FK4=KP8D+" .. "QUvJUYhNYb" .. "5nT59sX9d8" .. "x4ei?8in%!" .. "dptChG7gmD" ..
-- Page 6
"y#Ms#%vwuS" ..
-- End
"\001" -- Finish marker
--------------------------------------------------------------------------------
-- STATE MACHINE
--------------------------------------------------------------------------------
local state = {
curX = 1, -- Current cursor X position
curY = 1, -- Current cursor Y position
charIndex = 1, -- Current character index in codes
moveQueue = {}, -- Queue of buttons to press
pressing = false, -- Currently pressing a button?
waitFrames = INITIAL_DELAY,
done = false,
callbackId = nil
}
local function buildMoveQueue()
if state.charIndex > #codes then
state.done = true
console:log("All done! (" .. #codes - 1 .. " characters typed)")
return
end
local char = codes:sub(state.charIndex, state.charIndex)
local tx, ty = findChar(char)
if not tx then
console:log("ERROR: Character not found: " .. char)
state.charIndex = state.charIndex + 1
return
end
-- Progress logging
if state.charIndex % 50 == 1 then
local page = math.floor((state.charIndex - 1) / 50) + 1
console:log("Page " .. page .. " - char " .. state.charIndex .. "/" .. #codes)
end
-- Queue horizontal moves
while state.curX < tx do
state.moveQueue[#state.moveQueue + 1] = BTN.RIGHT
state.curX = state.curX + 1
end
while state.curX > tx do
state.moveQueue[#state.moveQueue + 1] = BTN.LEFT
state.curX = state.curX - 1
end
-- Queue vertical moves
while state.curY < ty do
state.moveQueue[#state.moveQueue + 1] = BTN.DOWN
state.curY = state.curY + 1
end
while state.curY > ty do
state.moveQueue[#state.moveQueue + 1] = BTN.UP
state.curY = state.curY - 1
end
-- Queue A press to select character
state.moveQueue[#state.moveQueue + 1] = BTN.A
state.charIndex = state.charIndex + 1
end
--------------------------------------------------------------------------------
-- MAIN CALLBACK
--------------------------------------------------------------------------------
local function onKeysRead()
-- Cleanup when done
if state.done then
if state.callbackId then
callbacks:remove(state.callbackId)
state.callbackId = nil
console:log("Callback removed, manual input restored!")
end
return
end
-- Wait if needed
if state.waitFrames > 0 then
state.waitFrames = state.waitFrames - 1
emu:setKeys(0)
return
end
-- Build moves for next character if queue empty
if #state.moveQueue == 0 then
buildMoveQueue()
if #state.moveQueue == 0 and not state.done then
return
end
end
-- Process queue: alternate press/release
if #state.moveQueue > 0 then
if not state.pressing then
emu:setKeys(state.moveQueue[1])
state.pressing = true
else
emu:setKeys(0)
table.remove(state.moveQueue, 1)
state.pressing = false
state.waitFrames = PRESS_DELAY
end
end
end
--------------------------------------------------------------------------------
-- START
--------------------------------------------------------------------------------
state.callbackId = callbacks:add("keysRead", onKeysRead)
console:log("Starting in " .. INITIAL_DELAY .. " frames... (" .. #codes .. " chars to type)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment