Game Boy Advance

The integrated Game Boy Advance emulator

pureikyubu now contains a second machine: a Game Boy Advance written from the public hardware specifications (the ARM Architecture Reference Manual for the ARM7TDMI, GBATEK for the GBA peripherals, the Pan Docs for the Game Boy). It is not a port of anything — it is a separate core in src/gba with its own boot ROM, its own test harness and its own SDL2 frontend, built for the two jobs the issue asked for: a GBA Link peer and a Game Boy Player stand-in.

The boot ROM draws the pureikyubu logo

The official IPL is copyrighted and is not shipped. The emulator builds a free replacement from source instead — the boot animation is emulated ARM code, assembled at run time by the small emitter in src/gba/gba_armasm.cpp. A rotating wireframe hypercube collapses into the flat pureikyubu cube mark while the wordmark scrolls in underneath, and the boot ROM then hands the machine over to the cartridge exactly the way the real BIOS does.

The rotating hypercube of the boot animation

1. The hypercube turns. Every frame is painted by the boot ROM's own rasterizer.

The hypercube collapsing into the cube mark

2. The projection collapses and the wireframe settles into the cube mark.

The final boot screen: the cube mark and the pureikyubu wordmark

3. The final frame: the cube mark with the wordmark, then the cartridge starts.

The image can be dumped for review, together with its assembly listing: gba_bench --dump-bootrom bootrom.bin.

Running it

The GBA is a mode of the same executable. A cartridge selects it by its extension, and with no cartridge at all the boot ROM starts its link driver — which is the state the "GBA Link" mode needs.

CommandWhat it does
pureikyubu --gba game.gbaRun a cartridge: boot animation first, then the game.
pureikyubu --gbaNo cartridge: the boot ROM's SIO link driver takes over.
pureikyubu game.gbaThe same as --gba; the extension decides.
pureikyubu --gba --gba-bios bios.binUse a real 16 KByte BIOS image instead of the boot ROM.
pureikyubu --gba --no-gba-bootromSkip the BIOS entirely and start the cartridge directly.
pureikyubu --gba-linkInitialize the link port even with a cartridge loaded.

The window, the sound and the input come from SDL2. The keyboard and game controller bindings, the scale, the sample rate and the link options live in build/Data/GBASettings.json; a malformed file is rejected with a message and the built-in defaults are used.

The harness runs a cartridge it assembles itself

The GBA core has no dependency on SDL, OpenGL or ImGui, so it has its own harness (testing/gba_bench): unit tests, a headless ROM runner, a frame-hash log, PNG dumps, a speed measurement and a link test that plugs two instances into each other. The demo cartridge above is assembled at run time by the same emitter the boot ROM uses — a real ARM program, in a real cartridge image with a real header — so the whole machine (CPU, cartridge, LCD, timers, VCOUNT synchronisation) is exercised by a single command.

The demo cartridge rendering its animation

testing/gba_bench/check.sh --demo --frames 120 --png /tmp/demo
testing/gba_bench/check.sh --bootrom --frames 300 --png /tmp/shots
testing/gba_bench/check.sh --run game.gba --frames 600 --bench

The public test ROMs

jsmolka/gba-tests is a suite of MIT-licensed GBA test ROMs. They are not part of the repository (they are somebody else's build output); a small script fetches them and the harness runs them like any other cartridge. They are a real end-to-end check, because they report their results on screen: the memory, ARM and Thumb suites all report "All tests passed", and they are what found the VRAM mirroring, the byte-store rules of the video memory and the register-shift-by-zero carry rule.

The memory test ROM reporting that all its tests passed

testing/gba_bench/get_test_roms.sh
testing/gba_bench/check.sh --run testing/gba_bench/roms/memory.gba --frames 200
testing/gba_bench/check.sh --run testing/gba_bench/roms/arm.gba --frames 200

The Game Boy mode

The GBA can run Game Boy cartridges only because the console carries a second, older machine inside it. That machine is implemented as its own core as well (src/gba/gb_*.cpp): the LR35902 CPU, the DMG/CGB LCD with the CGB palettes and VRAM banks, the four sound channels, and the MBC1/2/3/5 mappers with battery saves. It has its own free 256-byte boot ROM, whose boot animation is the "pureikyubu" wordmark sliding into the middle of the screen.

The Game Boy boot ROM's sliding wordmark

What is implemented, and what is not

Implemented

The ARM7TDMI (ARM and Thumb, all seven modes, the exceptions, HALT), the memory map with the open bus and the WAITCNT waitstates, the LCD (tile modes 0-2, bitmap modes 3-5, sprites, windows, mosaic, blending, forced blank), the four timers, the four DMA channels including the sound-FIFO and video-capture timings, the keypad, the interrupt controller, the sound (the four legacy channels and the two direct-sound FIFOs), the serial port in normal/multiplayer/UART mode with an emulated link cable, the cartridge (ROM-only plus SRAM, Flash and EEPROM saves, the GPIO/RTC port), the BIOS calls in the host, and the emulator's own boot ROM with its SIO link driver.

Not implemented (yet)

The JOY bus (a GameCube controller on the link port) and the Game Boy Player's own boot protocol; the BIOS sound driver and the Huffman decompressor; save states and rewind; the EEPROM's "last byte is the AND of the old and the new value" quirk. The LCD composes a scanline when its HBlank starts rather than dot by dot, and the internal RAM's own access times are not modelled. The full list, including every deliberate deviation the tests pin down, is in testing/gba_bench/Readme.md.

Documentation

Wiki: GBA

How the machine is put together: the boot ROM, the link port, the settings, the tests and the deviations.

The core's own notes

src/gba/Readme.md: the file layout, the specifications each file is written from, and how a frame runs.

The test harness

testing/gba_bench: what the tests cover and which hardware behaviours are deliberately simplified.

Credits

The purple Game Boy Advance in the page icon is Evan-Amos' photograph (public domain, via Wikimedia Commons), cropped and keyed by src/res/make_gba_icon.py; the icon itself is src/res/gba_icon.png.