Inside GBAx: how the emulator works
Follow a game from cartridge bytes through CPU execution and timed hardware events to pixels and sound.
On this page
A Game Boy Advance game is a program written for a particular machine. Its instructions expect an ARM processor, specific memory addresses, a display controller, sound channels, timers and cartridge hardware. A Windows PC or a Mac does not provide that machine directly. GBAx makes the game work by maintaining a software model of those components and carrying out the operations the game requests.
The important part is their relationship. A processor can produce the correct arithmetic result and still run a game incorrectly if a timer overflows too late, a display register changes on the wrong scanline, or a cartridge save command behaves differently. Emulation is the work of keeping those observations consistent.
The hardware chapters cover GBA mode; Game Boy and Game Boy Color use different hardware paths. These articles follow the mGBA-derived code in GBAx 2.0.0 Preview 1, pinned to commit c1a826ae. They describe the implementation shipped in that source revision. The desktop interface and the website’s EmulatorJS player are separate frontends; sharing an emulation foundation does not make their features or save-state formats identical.
Three layers, three different jobs
The desktop application has a useful separation between finding a game, emulating the console and presenting the result. You encounter all three when you double-click a cover, but they solve different problems.
| Layer | What it does | What it does not decide |
|---|---|---|
| GBAx launcher | Scans folders, shows artwork, manages favourites and recent games, and opens a selected file. | The meaning of an ARM instruction or a GBA display register. |
| Emulation core | Maintains CPU registers, memory, display state, sound, timers, DMA and cartridge state. | How a cover grid should look or which operating-system window receives focus. |
| Host frontend | Displays completed images, plays audio and maps keyboard/controller events to console buttons. | The game’s rules, level design or original artwork. |
In the reviewed desktop build, the interface uses Qt, with SDL support for audio and controllers. The core exposes operations such as loading a ROM, advancing execution and saving state. The frontend calls those operations; it does not need to reproduce the hardware itself. That boundary is why a launcher theme can change without changing how an instruction executes.
What happens when you launch a game
The launcher resolves your selection to a file and starts a separate GBAx game process. The Launcher architecture article follows that Qt process handoff and the library behind it. The core loads the cartridge data, prepares its memory regions and establishes the starting machine state. Cartridge save handling, game-specific configuration and BIOS behaviour also matter at this stage. A file ending in .gba contains the program and data the game expects to read; it is not a recording of the game or a collection of screenshots.
Once execution begins, the ARM interpreter reads instruction bits and selects the corresponding implementation. Arithmetic changes register values. Loads and stores reach the emulated memory system. Writes to hardware registers can start a timer, configure a DMA transfer or change a background layer. The next instruction observes the state left by the previous one.
- LoadCartridge bytes and saved progress enter the machine model.
- ExecuteThe CPU interpreter changes registers and accesses memory.
- AdvanceTimed events update video, audio, timers and transfers.
- PresentThe frontend displays pixels and plays buffered sound.
One clock coordinates the machine
The original GBA clock runs at 16,777,216 cycles per second. The core accounts for emulated cycles rather than making the host computer wait for each physical clock edge. An instruction and its memory accesses consume a certain amount of this emulated time. Video transitions, timer overflows and audio work are scheduled against the same timeline.
The reviewed code has an instruction loop, ARMRunLoop, that continues until the next event boundary. GBA-specific event handling then advances the timing system and dispatches due callbacks. A callback can request an interrupt, start a transfer or schedule its next occurrence. The CPU resumes with the updated hardware state.
This approach is efficient because the program does not have to ask every component whether something happened after every host operation. It can calculate when the next relevant event is due. It is still a model: callback ordering, instruction boundaries and late-event handling all affect correctness. Tracking cycles should not be described as a guarantee of perfect, transistor-level or universally cycle-accurate emulation.
Follow one frame through the system
Consider a game that updates a scrolling background once per frame. It reads input, calculates a new camera position and writes the appropriate display registers. During visible scanlines, the video renderer combines the configured background data and sprites into output pixels. At the vertical-blank transition, the core updates display status and can trigger VBlank DMA or an interrupt requested by the game.
The game’s interrupt routine might copy new sprite attributes or prepare the next frame. Audio timers continue operating while this happens. A DMA transfer can occupy the emulated bus and block normal CPU execution. The resulting picture is therefore tied to the order of these events, not just to the final values in memory.
The GBA timing constants in this revision describe 1,232 cycles per scanline and 228 lines per frame, including blanking, for 280,896 cycles per frame. Dividing the clock by that total gives about 59.73 frames per second. A host FPS counter may round its display; that does not change the console’s underlying timing model.
Why a fast computer still needs careful emulation
Host speed and emulation accuracy are different properties. A fast computer can carry out an incorrect model quickly. Conversely, a correct sequence of hardware events can be presented poorly if the audio device runs out of buffered samples or the window misses its presentation deadline.
This distinction helps diagnose problems. A repeatable visual error in one scene may point toward emulated display behaviour. Crackling that changes with audio-buffer settings may involve host scheduling. Neither observation proves the cause on its own, but it tells you which layer to investigate. A useful bug report preserves the game revision, build version, relevant settings and a reproducible sequence of actions.
How browser play differs
The website currently embeds EmulatorJS, using its mGBA core through a WebAssembly runtime. Your browser provides the display, audio, input and storage environment. It does not launch the native GBAx desktop application, and the website plugin does not stream gameplay from a remote PC.
Browser controls, storage lifetime and save import/export follow the web player’s implementation. The desktop launcher’s favourites, artwork cache and local folders do not automatically become a browser library. GBAxJS is the planned dedicated browser-player project; the current player should be identified by the technology it actually uses.
Choose your next topic
Start with CPU execution to understand how a single instruction runs, then memory and the system bus to see where its reads and writes go. Continue with timers, DMA and interrupts before exploring video and audio. The BIOS and boot process explains how execution gets started.
Sources & implementation
Implementation references follow GBAx 2.0.0 Preview 1, commit c1a826ae. The hardware implementation derives from mGBA; these links point to the matching GBAx source, rather than assuming a newer upstream revision behaves identically.
Need help with a specific problem? Start with troubleshooting →
