~/labs/workshops/gba-firered/03-ferramentas
Tools and setupmGBA, Ghidra, Python, Capstone, and GDB ready for class.
This chapter prepares the environment. Do everything before the hands-on class, because downloads and installation take time and interrupt the workshop flow.
There are five pieces:
mGBA runs the game and has a built-in debugger.
Ghidra performs static analysis of the ROM code.
Python runs the project helpers (disassembler, RAM search).
Capstone the library used by the disassembler.
ARM GDB talks to mGBA for dynamic analysis.
mGBA
mGBA is the emulator. It also serves a debug server that GDB can access, which is why it is the workshop choice.
On Ubuntu or Debian:
sudo apt update
sudo apt install -y mgba-qt mgba-sdl
If your distribution does not have the package, or ships an old version, download the official AppImage from https://mgba.io/downloads.html and run it like this:
chmod +x mGBA-*.AppImage
./mGBA-*.AppImage
Load the ROM with File, Load ROM, and point it to rom/PokemonFireRed.gba. Keep
the save file with the same name next to the ROM, as explained in
notes/save-prep.md, so the game opens with the Continue option.
Ghidra
Ghidra is the static analysis tool. It disassembles the ROM into instructions, finds functions, and shows a pseudo-C version next to the Assembly.
It needs Java. Download Ghidra from the official NSA site (https://ghidra-sre.org) or from the project’s GitHub, unzip it, and run:
./ghidraRun
The first time, create a new project with File, New Project, and give it a name
such as firered-workshop. Chapter 04 shows the ROM import step by step.
Python and Capstone
The project helpers are Python 3 scripts. The main one depends on Capstone, the disassembly library.
sudo apt install -y python3 python3-pip
pip3 install capstone
Check that Capstone was installed:
python3 -c "import capstone; print(capstone.__version__)"
If a version number appears, you are ready.
The project disassembler
The file tools/disasm_gba.py disassembles any ROM address, in ARM or Thumb. It is
the way to check Ghidra without relying only on it. All chapter 02 examples were
generated with it.
Usage:
# ARM, starting from an address, with size in bytes
python3 tools/disasm_gba.py 0x08000204 --size 0x34
# Thumb, just add --thumb
python3 tools/disasm_gba.py 0x080003A4 --size 0x20 --thumb
It converts the memory address to the file offset by itself, using the base 0x08000000 explained in chapter 01. If you pass an address outside the ROM, it warns you.
The RAM finder
The file ram_find.py compares two EWRAM dumps and shows which addresses had one
value before and another value after. That is what reduces the entire memory to a
few candidates in chapter 05. It reads two files:
ewram_hp24.bin EWRAM dump with HP at 24
ewram_hp21.bin EWRAM dump with HP at 21
And prints the addresses where the value changed from 24 to 21, testing three sizes: 8, 16, and 32 bits. Chapter 05 uses this in practice.
GDB for ARM
GDB is the debugger that connects to mGBA to pause the game, read registers, and
set watchpoints. You need a version with ARM support. In many distributions the
package is gdb-multiarch:
sudo apt install -y gdb-multiarch
The project already includes a ready configuration file, gdbinit-gba. It sets
GDB to ARM little endian and Thumb mode by default, which is what the GBA uses
most. To connect GDB to mGBA, first enable the debug server inside mGBA, in Tools,
Start GDB server, and then run:
gdb-multiarch -x gdbinit-gba
Inside GDB, connect with:
target remote localhost:2345
How to confirm everything is right
Run this quick test. It exercises both sides, static and dynamic:
1. Run:
python3 tools/disasm_gba.py 0x08000000 --size 0x10
It should show:
08000000: b #0x8000204
2. Open the ROM in mGBA and see the game running with the save.
3. Open Ghidra. Leave the import for chapter 04.
If step 1 works, the ROM and Python are right. If step 2 works, the emulator and save are right. You can continue.
What to take from this chapter
- mGBA runs the game and serves debug on port 2345.
- Ghidra performs static analysis.
- tools/disasm_gba.py checks disassembly outside Ghidra.
- ram_find.py compares EWRAM dumps to find a value.
- gdb-multiarch with gdbinit-gba performs dynamic analysis.