Skip to content

Instantly share code, notes, and snippets.

@DavidJCobb
Last active July 18, 2025 17:00
Show Gist options
  • Save DavidJCobb/a039fa94db90706ba6aa9709735fdcf4 to your computer and use it in GitHub Desktop.
Save DavidJCobb/a039fa94db90706ba6aa9709735fdcf4 to your computer and use it in GitHub Desktop.
mGBA CLI debugger reference

mGBA features a very basic embedded debugger. It has a help command, but this command doesn't explain what arguments any of the commands accept (or require). One has to look at mGBA's source code to get that information.

Syntax

Values

Integers are decimal by default, but can be prefixed with 0x or $ to allow hexadecimal. The 0b prefix marks binary literals. Any command which takes a memory address expects to receive it in the form of an integer.

Literals of the form $01:23 have a segment of 01 and a non-segment value of 0x00000023.

Register names (r0 through r15, and cpsr) can also be used, and will resolve to the registers' current values.

Expressions

The following two-term operators are supported:

+ - * / % & | ^ << >> == != > < >= <= && ||

Parentheses are also supported for grouping sub-expressions.

The unary * prefix operator will treat an integer value as a memory address, and read the byte at that address. This is treated as occurring within the context of the game (i.e. it will print [GAME ERROR] GBA Memory: Bad BIOS Load8 to the log if you read from an invalid address and have those messages enabled).

The unary ! prefix operator is supported, and is a logical "NOT" operator. It can be chained (e.g. !!5 == 1).

The unary ~ prefix operator is a bitwise "NOT" operator.

Commands

Breakpoints

break/t <address>
break/a <address>

Set a software breakpoint, to fire when execution reaches a given address. Breakpoints are specific to a CPU mode, with break/t setting a THUMB breakpoint and break/a setting an ARM breakpoint. Addresses are integer literals; if writing them in hex, they must be 0x-prefixed.

listb

List all breakpoints.

delete <address>
d <address>

This command is supposed to delete a breakpoint. In my experience, it doesn't work at all. Your only option to unset a breakpoint is to completely restart mGBA.

next

Executes the next assembly instruction, and prints the registers and instruction.

trace <count>

Executes the next count assembly instructions, printing the registers and instructions.

continue

Continues execution.

Watches

watch   <address> <condition>
watch/r <address> <condition>
watch/w <address> <condition>
watch/c <address> <condition>

Sets a watchpoint at the given address (an integer literal; if hexadecimal, it must be 0x-prefixed). The suffix indicates the operation you're watching for:

  • No suffix: reads or writes
  • r: reads
  • w: writes
  • c: writes, but only if they change the value

mGBA will break into the debugger when the given operation occurs at the given address. The condition is optional and, if specified, controls whether mGBA breaks into the debugger. It must be an incomplete expression with no whitespace separation (e.g. watch 12345==3 is valid; watch 12345 == 3 and watch 12345 3 == 3 are invalid).

watch-range   <address> <address>
watch-range/r <address> <address>
watch-range/w <address> <address>
watch-range/c <address> <address>

Same as the above, except that it watches a range of addresses. You provide a start and an end, and this adds a watchpoint for [start, end).

listw

Lists all extant watchpoints. Their conditions, if any, are not displayed.

Disassembly

disasm <address> <count>

The arguments are optional, and default to the current instruction pointer and to 1, respectively. Prints count many instructions starting at the given address. Addresses are integer literals; if writing them in hex, they must be 0x-prefixed.

If you've loaded a symbol file, then any known symbols will be identified by name in the printed disassembly.

disasm/t <address> <count>
disasm/a <address> <count>

Same as the above, except that these forcibly interpret the instructions as THUMB or ARM, regardless of the current CPU mode.

Stacks

stack <string>

Change the current stack tracing mode. The argument must be one of the following:

Value Meaning
off Disables stack tracing.
trace-only Enables stack tracing.
break-call Break on function calls.
break-return Break on function returns.
break-all Break on function calls and returns.

If you run the command without an argument, it prints the list of available options.

backtrace

Does nothing if stack tracing is not enabled.

If stack tracing is enabled, then this attempts to print a stack trace. It apparently can't see any stack frames that were passed through before tracing was enabled.

finish

Continues execution until the current stack frame returns.

Symbols

load-symbols <filepath>

Attempts to load the .elf file at the given path. If you're on Windows, you can use Windows or common path separators (i.e. \ or /).

symbol <address>

Looks up the symbol name for the given address, if there is one.

Miscellaneous

print   <expression>
print/t <expression>
print/x <expression>

Computes the result of the given expression, and prints it. The /t specifier formats the output in base-2, while the /x specifier formats the output in hex.

source <filepath>

Attempts to load and execute the given Lua script file, if scripting is enabled on your build of mGBA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment