This is a Game Boy Advance (GBA) emulator, written in Rust. It's fairly accurate and efficient, and can play all of the games I tested without any issues.
I'd previously written an NES emulator, first in Go, and then rewritten and improved in Rust. For my next emulation project, I wanted to emulate a system that I had a closer personal connection to.
- Good accuracy (enough to play games without any problems)
- Full audio support
- Cartridge saves and emulator save states
- RTC emulation (e.g. for Pokemon)
- GUI (perhaps using imgui)
- Higher quality audio resampling and syncing
- Maybe: link cable support
- Maybe: more accurate timing (e.g. cartridge prefetch buffer, DMA)
- Maybe: debugger
- DMA open bus isn't properly implemented
- Slight click when PSG audio channels change frequency
- Prefetch buffer is approximated as 1 cycle per access
- Mosaic on affine backgrounds is unsupported
- Tile indexing allows doing things hardware doesn't (e.g. accessing invalid tileblocks for the current mode)
- SOUNDBIAS sampling rate isn't implemented (it's fixed to 32 KHz)
gba_emulator [OPTIONS] --bios-path <BIOS_PATH> <ROM_PATH>
You'll need to provide a GBA BIOS ROM. I've only tested with the official one, but others should work too.
I've developed and tested this emulator on macOS. Theoretically, it should work on any platform SDL2 supports (including Windows and Linux).
Z
: A buttonX
: B buttonA
: L buttonS
: R buttonEnter
: StartRight Shift
: SelectArrow keys
: D-Pad
There are also a few keyboard shortcuts to control the emulator itself:
Cmd-P
: Pause/Resume emulationCmd-N
: Step forward one frameCmd-S
: Save the save stateCmd-L
: Load the save stateTab
: Hold to fast-forward (4x speed)
Save states are saved to the same directory as the ROM, with the .save_state
extension.
These are unique to the emulator.
Cartridge saves are saved to the same directory, with the .sav
extension. These should
be transferrable between any emulator (or a physical cartridge).
You'll need a relatively recent version of Rust, as well as SDL2. Then, it's
as simple as running cargo build --release
. Make sure to build in release mode: debug
is likely too slow to run games at full speed.
This project wouldn't have been possible without a lot of resources from the emulation community.
I'd also like to thank everybody in #gba
on the Emulation Development Discord,
for answering questions and providing support.
- ARM Architecture Reference Manual
- ARM7TDMI-S Technical Reference Manual
- GBATEK: The main GBA resource, explains everything
- Rodrigo Copetti's Game Boy Advance Architecture: an interesting, detailed, and informative resource (and not just for GBA, either).
- TONC: Excellent tutorial on GBA programming. Especially useful as a resource for understanding the PPU (along with the demos)
- The Audio Advance: Detailed explanation of GBA audio (with demos).
- Gameboy sound hardware: detailed explanation of the original Gameboy's APU, which is part of the GBA's APU.
- The mGBA Blog
- DenSinH's explanations of Flash and EEPROM.
- jsmolka's CPU tests: The first ROMs I used to test my CPU as I was implementing it. Very thorough!
- armwrestler: more CPU tests
- FuzzARM: randomly generated CPU tests
- TONC Demos: Graphics demos that go along with the TONC guide.
- The Audio Advance Demos: GBA audio demos
- DenSinH's Flash and EEPROM Tests
- MichelOS's RTC Demo
- mGBA: I relied heavily on the debugging features when I was first working on the CPU, as well on the PPU inspection tools.
- NanoBoyAdvance: I used NanoBoyAdvance as a reference for certain details of the GBA's behavior, especially when GBATEK was too terse.
- RustBoyAdvance-NG: I used this as inspiration for some Rust-specific design decisions (especially the instruction decoder table).