Skip to content
Back to skills

Mgba

ASecurity

Use when scripting mGBA emulator automation in Lua - console API, ROM and save state operations, frame callbacks, input handling, memory reading for cheats and RAM watches, sockets, or TAS and speedrunner tooling

  • 21 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 2, 2026
toolsgogitapidocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned October 2, 2026

npx -y skills add CodeAtCode/oss-ai-skills --skill mgba --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Mgba?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Mgba
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/codeatcode-mgba/badge)](https://www.skillsdirectory.com/skills/codeatcode-mgba)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mgba
description: Use when scripting mGBA emulator automation in Lua - console API, ROM and save state operations, frame callbacks, input handling, memory reading for cheats and RAM watches, sockets, or TAS and speedrunner tooling
metadata:
  author: mte90
  version: 2.0.0
  tags:
    - lua
    - emulator
    - gba
    - gameboy-advance
    - scripting
    - memory-hacking
---

# mGBA Scripting

Lua scripting for mGBA emulator.

## Overview

Starting with version 0.10, mGBA has built-in scripting capabilities. To use scripting, click "Scripting..." from the Tools menu. Currently, only Lua scripting is supported.

**Key Features:**
- Full memory access (ROM, RAM, MMIO)
- Input manipulation (button presses)
- Save state management
- Callbacks for frame/events
- TCP socket networking
- Console output
- Screenshot capture

### Opening Scripting Console

```
Tools → Scripting...
```

This opens a console where you can load and run Lua scripts.

## Top-Level Objects

### Available Objects

```lua
-- emu: CoreAdapter instance (available when game loaded)
-- C: Exported constants
-- callbacks: CallbackManager instance
-- console: Console instance
-- util: Basic utility library
-- socket: TCP socket library
```

### Console Output

```lua
console.log("Info message")
console.warn("Warning message")
console.error("Error message")

-- Create text buffer
buffer = console.createBuffer("My Buffer")
buffer:print("Text in buffer")
buffer:clear()
```

### Utility Functions

```lua
-- Expand bitmask to list
bits = util.expandBitmask(0xFF)  -- {0,1,2,3,4,5,6,7}

-- Make bitmask from list
mask = util.makeBitmask({0, 3, 5})  -- 0x29
```

## Core API

### ROM Operations

```lua
-- Load ROM file
success = emu.loadFile("path/to/rom.gba")

-- Get game info
title = emu.getGameTitle()  -- "POKEMON FIRE"
code = emu.getGameCode()   -- "AGB-P-FE"
size = emu.romSize()       -- ROM size in bytes
platform = emu.platform()  -- 0=GBA, 1=GB
checksum = emu.checksum()  -- CRC32
```

### Save States

```lua
-- Save to file
emu.saveStateFile("path/to/state.state")

-- Load from file
emu.loadStateFile("path/to/state.state")

-- Save to slot (0-9)
emu.saveStateSlot(0)
emu.loadStateSlot(0)

-- Save/load buffer
buffer = emu.saveStateBuffer()
emu.loadStateBuffer(buffer)

-- Flags: SCREENSHOT=1, SAVEDATA=2, CHEATS=4, RTC=8, METADATA=16
-- ALL = 31
emu.saveStateSlot(0, 31)  -- Save everything
```

### Frame Control

```lua
-- Run one frame
emu.runFrame()

-- Run one instruction
emu.step()

-- Get current frame number
frame = emu.currentFrame()

-- Get cycle info
cycles = emu.frameCycles()    -- Cycles per frame
freq = emu.frequency()         -- Cycles per second
```

### Input Handling

```lua
-- Set all keys at once
emu.setKeys(0x0000)  -- No keys

-- Add keys (OR with existing)
emu.addKeys(C.GBA_KEY.A + C.GBA_KEY.R)

-- Clear keys
emu.clearKeys(C.GBA_KEY.B)

-- Check key state
if emu.getKey(C.GBA_KEY.UP) == 1 then
    print("UP is pressed")
end

-- Get all pressed keys
keys = emu.getKeys()
```

### GBA Key Constants

```lua
C.GBA_KEY.A      = 0
C.GBA_KEY.B      = 1
C.GBA_KEY.SELECT = 2
C.GBA_KEY.START  = 3
C.GBA_KEY.RIGHT  = 4
C.GBA_KEY.LEFT   = 5
C.GBA_KEY.UP     = 6
C.GBA_KEY.DOWN   = 7
C.GBA_KEY.R      = 8
C.GBA_KEY.L      = 9
```

### Game Boy Key Constants

```lua
C.GB_KEY.A       = 0
C.GB_KEY.B       = 1
C.GB_KEY.SELECT  = 2
C.GB_KEY.START   = 3
C.GB_KEY.RIGHT   = 4
C.GB_KEY.LEFT    = 5
C.GB_KEY.UP      = 6
C.GB_KEY.DOWN    = 7
```

## Memory Access

### Reading Memory

```lua
-- Read 8/16/32 bit values
value8 = emu.read8(address)
value16 = emu.read16(address)
value32 = emu.read32(address)

-- Read range
data = emu.readRange(address, length)

-- Read from memory domain
rom = emu.memory["cart0"]
value = rom:read8(offset)
data = rom:readRange(offset, length)
```

### Writing Memory

```lua
-- Write 8/16/32 bit values
emu.write8(address, value)
emu.write16(address, value)
emu.write32(address, value)
```

### Memory Domains (GBA)

```lua
-- Available memory domains
emu.memory["bios"]    -- BIOS (0x00000000)
emu.memory["wram"]     -- EWRAM (0x02000000)
emu.memory["iwram"]    -- IWRAM (0x03000000)
emu.memory["io"]       -- MMIO (0x04000000)
emu.memory["palette"]  -- Palette (0x05000000)
emu.memory["vram"]     -- VRAM (0x06000000)
emu.memory["oam"]      -- OAM (0x07000000)
emu.memory["cart0"]    -- ROM (0x08000000)
emu.memory["cart1"]    -- ROM WS1 (0x0a000000)
emu.memory["cart2"]    -- ROM WS2 (0x0c000000)
```

### Memory Domains (GB)

```lua
emu.memory["cart0"]  -- ROM Bank ($0000)
emu.memory["vram"]   -- VRAM ($8000)
emu.memory["sram"]   -- SRAM ($a000)
emu.memory["wram"]   -- WRAM ($c000)
emu.memory["oam"]    -- OAM ($fe00)
emu.memory["io"]     -- MMIO ($ff00)
emu.memory["hram"]   -- HRAM ($ff80)
```

## Callbacks

### Adding Callbacks

```lua
-- Add callback (returns callback ID)
id = callbacks.add("frame", function()
    -- Called every frame
end)

id = callbacks.add("start", function()
    -- Called when emulation starts
end)

id = callbacks.add("reset", function()
    -- Called when emulation resets
end)

id = callbacks.add("shutdown", function()
    -- Called when emulation stops
end)

-- Remove callback
callbacks.remove(id)
```

### Available Callbacks

```lua
-- alarm     - In-game alarm went off
-- crashed   - Emulation crashed
-- frame     - Frame finished
-- keysRead  - About to read key input
-- reset     - Emulation reset
-- savedataUpdated - Save data modified
-- sleep     - Entered low-power mode
-- shutdown  - Powered off
-- start     - Started
-- stop      - Voluntarily shut down
```

### Frame Callback Example

```lua
-- Auto-press A every 10 frames
local counter = 0
callbacks.add("frame", function()
    counter = counter + 1
    if counter >= 10 then
        emu.addKeys(C.GBA_KEY.A)
        counter = 0
    else
        emu.clearKeys(C.GBA_KEY.A)
    end
end)
```

## Deep Dives

Detailed reference material is available in the `references/` directory. Load these on demand for specific topics:

- **Classes & Registers** — MemoryDomain class, TextBuffer class, GBA/GB register details
  - `references/classes-registers.md`
- **Networking** — Socket API details and constants
  - `references/networking.md`
- **Examples** — Complete working scripts (cheats, TAS tools, networked scripts)
  - `references/examples.md`

## Best Practices

### 1. Always Clear Keys

```lua
-- Bad: Keys stay pressed
callbacks.add("frame", function()
    emu.addKeys(C.GBA_KEY.A)
end)

-- Good: Clear after use
callbacks.add("frame", function()
    emu.addKeys(C.GBA_KEY.A)
    emu.clearKeys(C.GBA_KEY.A)
end)
```

### 2. Use Frame Callback for Input

```lua
-- Input should be handled in frame callback
callbacks.add("frame", function()
    if btnp(6) then  -- UP pressed this frame
        -- Handle input
    end
end)
```

### 3. Watch for Crashes

```lua
callbacks.add("crashed", function()
    console.error("Emulation crashed!")
    -- Save state before exit
    emu.saveStateFile("crash.state")
end)
```

### 4. Reset State on Script Load

```lua
-- Clear any previous state when loading
emu.clearKeys(0xFFFF)
callbacks.remove(cbid)  -- Remove old callbacks
```

## Common Issues

### Address Not Found

```lua
-- Some games use different RAM locations
-- Use mGBA's cheat search or memory viewer to find correct addresses
```

### Keys Not Working

```lua
-- Some games poll keys differently
-- Try using addKeys instead of setKeys
emu.addKeys(C.GBA_KEY.A)  -- OR with existing
```

### Socket Connection Timeout

```lua
-- Socket connect is blocking!
-- Use connect with timeout or run in separate thread
-- For async, use callbacks and poll()
```

## Complete API Reference

### Core Methods Summary

| Method | Description |
|--------|-------------|
| `loadFile(path)` | Load ROM file |
| `getGameTitle()` | Get ROM title |
| `getGameCode()` | Get ROM code |
| `romSize()` | Get ROM size |
| `platform()` | Get platform (GBA=0, GB=1) |
| `checksum(type)` | Get ROM checksum |
| `reset()` | Reset emulation |
| `runFrame()` | Run one frame |
| `step()` | Run one instruction |
| `currentFrame()` | Get frame number |
| `frameCycles()` | Cycles per frame |
| `frequency()` | Cycles per second |
| `screenshot(filename)` | Save screenshot |

### Memory Methods Summary

| Method | Description |
|--------|-------------|
| `read8(addr)` | Read 8-bit value |
| `read16(addr)` | Read 16-bit value |
| `read32(addr)` | Read 32-bit value |
| `readRange(addr, len)` | Read byte range |
| `write8(addr, val)` | Write 8-bit value |
| `write16(addr, val)` | Write 16-bit value |
| `write32(addr, val)` | Write 32-bit value |
| `readRegister(name)` | Read CPU register |
| `writeRegister(name, val)` | Write CPU register |

### Input Methods Summary

| Method | Description |
|--------|-------------|
| `setKeys(mask)` | Set key bitmask |
| `addKeys(mask)` | Add keys to current |
| `clearKeys(mask)` | Remove keys from current |
| `addKey(key)` | Add single key |
| `clearKey(key)` | Clear single key |
| `getKey(key)` | Get key state |
| `getKeys()` | Get all keys as mask |

### Save State Methods Summary

| Method | Description |
|--------|-------------|
| `saveStateFile(path, flags)` | Save to file |
| `loadStateFile(path, flags)` | Load from file |
| `saveStateSlot(slot, flags)` | Save to slot |
| `loadStateSlot(slot, flags)` | Load from slot |
| `saveStateBuffer(flags)` | Save to buffer |
| `loadStateBuffer(buf, flags)` | Load from buffer |
| `autoloadSave()` | Load associated save |

## References

- **Official Documentation**: https://mgba.io/docs/scripting.html
- **mGBA GitHub**: https://github.com/mgba-emu/mgba
- **Forums**: https://forums.mgba.io/
- **Discord**: https://discord.gg/em2M2sG
- **Scripting API Reference**: https://mgba.io/docs/scripting.html

Files in this skill

  • SKILL.md9.5 KB
  • references/classes-registers.md3.6 KB
  • references/examples.md6.5 KB
  • references/networking.md1.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…