← cd ../

~/labs/workshops/gba-firered/01-arquitetura-do-gba

The GBA architectureThe hardware, ARM7TDMI CPU, and console memory map.

Before opening any tool, you need a mental model of the console. Reverse engineering becomes much easier when you know where code lives, where data lives, and how the CPU sees all of it.

The hardware in one sentence

The Game Boy Advance is a small computer with a 32-bit ARM7TDMI processor running at about 16.78 MHz, little memory, a 240 by 160 pixel screen, and a cartridge that contains the game ROM.

CPU      ARM7TDMI, 32-bit, ~16.78 MHz
Screen   240 x 160 pixels
EWRAM    256 KB of "external" RAM (slower)
IWRAM    32 KB of "internal" RAM (faster)
ROM      the cartridge, up to 32 MB, read-only

The ARM7TDMI processor

All game logic runs on this CPU. It has characteristics that define everything we will do later:

- It is RISC. Instructions are simple and fixed-size.
- It is little endian. The least significant byte comes first in memory.
- It has 16 visible general-purpose and control registers.
- It executes two instruction sets: ARM (32-bit) and Thumb (16-bit).

Chapter 02 focuses only on ARM and Thumb, because that is where the intimidating part lives at first. For now, keep one idea: the game is a giant sequence of those instructions, and the CPU reads them one at a time.

The memory map

The CPU accesses everything through addresses. Each type of memory lives in a fixed address range. This is the map you will use all the time:

0x00000000  BIOS         internal console code
0x02000000  EWRAM        work RAM, 256 KB
0x03000000  IWRAM        fast RAM, 32 KB
0x04000000  hardware registers (video, sound, input, DMA, timers)
0x05000000  Palette RAM  colors
0x06000000  VRAM         video data (tiles, maps, bitmaps)
0x07000000  OAM          sprite attributes
0x08000000  ROM          the game cartridge, mapped here

Two ranges matter most for this workshop:

0x08000000  is where the game ROM appears. Fixed code and data.
0x02000000  is where the current game state lives. HP, position, battle.

The general rule is easy to remember:

ROM (0x08...)   = what the game is. It does not change while you play.
EWRAM (0x02...) = what is happening now. It changes every frame.

When we want to understand logic, we look at ROM. When we want to find a live value such as HP, we search EWRAM. Those two worlds meet when an instruction from ROM writes a value into EWRAM. Finding that moment is the core of game reverse engineering.

The ROM mapped at 0x08000000

This is the point that confuses people most at first, so it is worth stopping on.

The file PokemonFireRed.gba on disk starts at offset 0. But when the console boots, it maps that entire file starting at address 0x08000000. So byte 0 of the file becomes address 0x08000000, byte 0x100 of the file becomes 0x08000100, and so on.

The conversion is direct:

memory address = file offset + 0x08000000
file offset    = memory address - 0x08000000

Example:

address 0x08012345  ->  offset 0x00012345 in the file

You will use this in every patch. Ghidra shows addresses like 0x08xxxxxx, but to edit the file on disk you need the offset, which is the address minus 0x08000000.

Looking at the first ROM bytes

You can confirm all of this without any special tool, just with xxd. The first four ROM bytes are the first opcode the CPU executes:

xxd -g 1 -l 4 rom/PokemonFireRed.gba

Output:

00000000: 7f 00 00 ea

Those four bytes, read as a 32-bit ARM instruction in little endian, become a jump. In chapter 02 we decode it byte by byte. For now, trust this: it is the instruction b 0x08000204, a branch that skips the header and enters the real code.

The ROM also stores a header with the game title. It is at offset 0xA0:

xxd -g 1 -s 0xa0 -l 32 rom/PokemonFireRed.gba

Output, reading the ASCII column on the right:

POKEMON FIRE
BPRE

The code BPRE identifies Pokemon FireRed USA. If your ROM shows this, it is the right version for the workshop.

Video and sprites, at a high level

You do not need to master GBA video to make the patches in this workshop, but it helps to know the names so you do not get lost when they appear:

Backgrounds  background layers, built with tiles stored in VRAM.
Sprites      moving objects (the player, Pokemon in battle).
OAM          the list that says where each sprite is on screen.
Palette RAM  the colors used by tiles and sprites.

The screen is redrawn from top to bottom several times per second. At the end of each complete draw there is a small interval called VBlank. The game uses that moment to update graphics safely. That is why the game’s main loop always ends by waiting for VBlank, as you will see in chapter 04.

Interruptions, at a high level

An interrupt is a hardware signal to the CPU that something happened, for example “I finished drawing the screen” or “the player pressed a link button.” The CPU stops what it is doing, handles the signal in a specific routine, and then returns.

On the GBA, the FireRed routine that handles those signals is near the start of the ROM, and in the workshop map it is called intr_main. You do not need to reverse it entirely. What matters is understanding that it exists to synchronize video, sound, input, and timers.

Why FireRed is a good target

It is worth closing the chapter with the reason for the choice:

ARM/Thumb       well supported by Ghidra, so the disassembly is clean.
Direct ROM      less boot complexity than something like an N64.
Clear data      strings, Pokemon tables, items, and maps are readable.
Fast feedback   walk in grass, open a shop, battle. You can test a patch immediately.
Good debugger   mGBA has a debug server that talks to GDB.

What to take from this chapter

- The CPU is a 32-bit little-endian ARM7TDMI.
- Each type of memory lives in a fixed address range.
- The ROM appears at 0x08000000. Game state lives in EWRAM, at 0x02000000.
- file offset = address - 0x08000000.
- The game is a sequence of ARM and Thumb instructions. That is the next chapter.