Swift package that provides emulation back-end to make your own Game Boy emulator.
Here's a simple emulator (front-end) usage : https://github.com/MarcAlx/gb
Status Games that don't rely on advance CPU tricks or MBC special feature works, e.g Super Mario Land, Kirby Dream Land, Tetris, Tennis, F1 Race, Pokémon...
Under active development (full MBC-2-3-5-6-7 support on the way! now limited to RAM feature, ETA: when its done!). For now limited to GB, GBC support planned.
- CPU (Done)
- PPU (Done)
- APU (Done, not all obscure behaviors implemented)
- MBC handling (No MBC and MBC1: OK, MBC2,MBC3, MBC5 ROM/RAM Ok, full MBC-2-3-5-6-7 support in development, see status table below)
- Finish unit tests (TODO)
- Move from
XCTestto new SwiftTesting(Next) - GBC Support (Later)
MBC support status
Statuses: 🟢 supported, 🟠 partial support, 🔴 unsupported (todo), ✕ unconcerned
| Cartridge type | MBC/Feature | ROM banking | RAM | Battery | RTC | Rumble | Status | Game example |
|---|---|---|---|---|---|---|---|---|
| 0x00 | ROM_ONLY | ✕ | ✕ | ✕ | ✕ | ✕ | 🟢 | Tetris |
| 0x01 | MBC1 | 🟢 | ✕ | ✕ | ✕ | ✕ | 🟢 | Super Mario Land |
| 0x02 | MBC1_RAM | 🟢 | 🟢 | ✕ | ✕ | ✕ | 🟢 | |
| 0x03 | MBC1_RAM_BATTERY | 🟢 | 🟢 | 🔴 | ✕ | ✕ | 🟠 | |
| 0x05 | MBC2 | 🟢 | ✕ | ✕ | ✕ | ✕ | 🟢 | F1 Race |
| 0x06 | MBC2_BATTERY | 🟢 | 🟢 | 🔴 | ✕ | ✕ | 🟠 | F1 Race |
| 0x08 | ROM_RAM | 🔴 | 🔴 | ✕ | ✕ | ✕ | 🔴 | |
| 0x09 | ROM_RAM_BATTERY | 🔴 | 🔴 | 🔴 | ✕ | ✕ | 🔴 | |
| 0x0B | MMM01 | 🔴 | ✕ | ✕ | ✕ | ✕ | 🔴 | |
| 0x0C | MMM01_RAM | 🔴 | 🔴 | ✕ | ✕ | ✕ | 🔴 | |
| 0x0D | MMM01_RAM_BATTERY | 🔴 | 🔴 | 🔴 | ✕ | ✕ | 🔴 | |
| 0x0F | MBC3_TIMER_BATTERY | 🟢 | ✕ | 🔴 | 🔴 | ✕ | 🟠 | |
| 0x10 | MBC3_TIMER_RAM_BATTERY | 🟢 | 🟢 | 🔴 | 🔴 | ✕ | 🟠 | |
| 0x11 | MBC3 | 🟢 | ✕ | ✕ | ✕ | ✕ | 🟢 | Pokémon Red (JP) |
| 0x12 | MBC3_RAM | 🟢 | 🟢 | ✕ | ✕ | ✕ | 🟢 | Pokémon Red (JP) |
| 0x13 | MBC3_RAM_BATTERY | 🟢 | 🟢 | 🔴 | ✕ | ✕ | 🟠 | Pokémon Red (JP) |
| 0x19 | MBC5 | 🟢 | ✕ | ✕ | ✕ | ✕ | 🟢 | Pokémon Red (EU) |
| 0x1A | MBC5_RAM | 🟢 | 🟢 | ✕ | ✕ | ✕ | 🟢 | Pokémon Red (EU) |
| 0x1B | MBC5_RAM_BATTERY | 🟢 | 🟢 | 🔴 | ✕ | ✕ | 🟠 | Pokémon Red (EU) |
| 0x1C | MBC5_RUMBLE | 🟢 | ✕ | ✕ | ✕ | 🔴 | 🟠 | |
| 0x1D | MBC5_RUMBLE_RAM | 🟢 | 🟢 | ✕ | ✕ | 🔴 | 🟠 | |
| 0x1E | MBC5_RUMBLE_RAM_BATTERY | 🟢 | 🟢 | 🔴 | ✕ | 🔴 | 🟠 | |
| 0x20 | MBC6 | 🔴 | ✕ | ✕ | ✕ | ✕ | 🔴 | |
| 0x22 | MBC7_SENSOR_RUMBLE_RAM_BATTERY | 🔴 | 🔴 | 🔴 | ✕ | ✕ | 🔴 | |
| 0xFC | POCKET_CAMERA | 🔴 | 🔴 | 🔴 | ✕ | ✕ | 🔴 | |
| 0xFD | BANDAI_TAMA5 | ✕ | ✕ | ✕ | ✕ | ✕ | 🟢 | |
| 0xFE | HuC3 | 🔴 | 🔴 | 🔴 | 🔴 | ✕ | 🔴 | |
| 0xFF | HuC1_RAM_BATTERY | 🔴 | 🔴 | 🔴 | ✕ | ✕ | 🔴 |
From a game rom, inputs, audio/video configurations and 60fps timing GBKit produces video frames and audio samples.
graph TB;
GB[Game Boy]
MB[MotherBoard]
CPU[CPU]
MMU[MMU]
APU[APU]
LCDI[LCDInterface]
TIMI[TimerInterface]
JOYI[JoyPadInterface]
AUDIOI[AudioInterface]
JOY[JoyPad]
R[Registers]
INT[Interrupts control interface]
TIM[Timer]
GB --> MB;
MB --> CPU;
MB --> MMU;
MB --> PPU;
MB --> JOY;
MB --> APU;
MB --> TIM;
MMU --> INT;
MMU --> LCDI;
MMU --> JOYI;
MMU --> AUDIOI;
MMU --> TIMI;
CPU --> MMU;
CPU --> R
PPU --> MMU;
JOY --> MMU;
TIM --> MMU;
APU --> MMU;
| Timing (s) | Timing (ms) | CPU Speed (Hz/M cycle) | CPU Speed (Hz/T cycle) | Audio frequency (Hz) | FPS | Note |
|---|---|---|---|---|---|---|
| 1 | 1000 | 1 048 576 | 4 194 304 | 44100 | 60 | 60 fps |
| 0,000022 | 0,022 | ~23,75 | ~95 | 1 | 0,0013 | Per audio frame |
| 0,023 | 23 | 24 320 | 97280 | 1024 | 1,39 | Audio latency |
| 0,01668 | 16,67 | 17 476,25 | 69905 | 735 | 1 | 1 fps |
n.b 1 M cycle = 4 T cycles
Passing:
-
01-special.gb
-
02-interrupts.gb
-
03-op sp,hl.gb
-
04-op r,imm.gb
-
05-op rp.gb
-
06-ld r,r.gb
-
07-jr,jp,call,ret,rst.gb
-
08-misc instrs.gb
-
09-op r,r.gb
-
10-bit ops.gb
-
11-op a,(hl).gb
-
aging.gb
Passing :
Non passing:
- 01-read_timing.gb
- 02-write_timing.gb
- 03-modify_timing.gb
n.b requires CPU to decompose its instruction to reflect mmu state (see wip on branch /dev/mmu-timings)
Non passing:
- 01-registers.gb
- 02-len ctr.gb
- 03-trigger.gb
- 04-sweep.gb
- 05-sweep details.gb
- 06-overflow on trigger.gb
- 07-len sweep period sync.gb
- 08-len ctr during power.gb
- 09-wave read while on.gb
- 10-wave trigger while on.gb
- 11-regs after power.gb
- 12-wave write while on.gb
This repo is compliant with gameboy doctor for the following roms found here:
- 01-special.gb
- 02-interrupts.gb
- 03-op sp,hl.gb
- 04-op r,imm.gb
- 05-op rp.gb
- 06-ld r,r.gb
- 07-jr,jp,call,ret,rst.gb
- 08-misc instrs.gb
- 09-op r,r.gb
- 10-bit ops.gb
- 11-op a,(hl).gb
n.b Some initialization are required in order to be compliant with this tool (set F to 0xB0, MMU must return to 0x90 for LY (0xFF44), CPU must log at each instruction via cpu.registers.describe()) (see branch /dev/gb_doc)
This project contains some unit tests, objective is to test each core fonction of the implementation.
- Azayaka (c++)
- Cinoop (c)
- CoreBoy (c#)
- Gambatte (c++)
- gamebert (go)
- gameboy-emulator (typescript)
- IronBoy (rust)
- jitboy (c)
- GameBoy (js)
- PyBoy (python)
- Mooney gb (rust)
- SameBoy (c)
- retroboy (rust)
- Kokoboy (kotlin)
- GhostBoy (c++)
- AXWGameBoy (go)
- Argentum (rust)
- TLMBoy (c++)
- ayyboy (rust)
- A journey into GameBoy emulation
- Building a Gameboy From Scratch
- DMG-01: How to Emulate a Game Boy
- Émuler la gameboy (fr)
- emudev q00.gb
- Gamebert: a Game Boy emulator built by Robert
- Gameboy emulation
- Gameboy Doctor: debug and fix your gameboy emulator
- GameBoy-Emulation-in-JavaScript
- The Gameboy Emulator Development Guide
- Tetris Title Screen
- Reverse Engineering the Gameboy Boot Screen
- Programming A Gameboy Color Emulator
- Writting an emulator: the first steps
- Writing an emulator: memory management
- Writing an emulator: the first pixel
- Writing an emulator: the first (real) pixel
- Writing an emulator: timing is key
- GameRoy: JIT compilation in High-Accuracy Game Boy Emulation
- A Visual Guide to the Gameboy's Half-Carry Flag
- A Look At The Game Boy Bootstrap: Let The Fun Begin!
- WTF is the DAA instruction?
- Demystifying the GameBoy/SM83’s DAA Instruction
- Game Boy Sound Emulation
- Gameboy sound hardware
- GBSOUND.txt
- Nitty Gritty Gameboy Cycle Timing.txt
- TLMBoy: The Audio Processing Unit (APU) - Square Channel
- TLMBoy: The Audio Processing Unit (APU) - Noise Channel
- More than you wanted to know about how Game Boy cartridges work
-
https://www.reddit.com/r/EmuDev/comments/tl1pli/i_dont_know_how_to_implement_the_main_loop_gb/
-
https://www.reddit.com/r/EmuDev/comments/4o2t6k/how_do_you_emulate_specific_cpu_speeds/
-
https://www.reddit.com/r/EmuDev/comments/utyx2g/looking_for_help_understanding_gameboy_clock/
-
https://www.reddit.com/r/EmuDev/comments/5gkwi5/gb_apu_sound_emulation/
-
https://www.reddit.com/r/Gameboy/comments/a1c8h0/what_happens_when_a_gameboy_screen_is_disabled/
-
https://www.reddit.com/r/EmuDev/comments/5gkwi5/comment/dat3zni
-
https://www.reddit.com/r/EmuDev/comments/j4xn0s/gb_how_to_get_correct_memory_timings/
-
https://www.reddit.com/r/EmuDev/comments/1mx2k5e/audio_emulation_101_game_boy_example/
- https://github.com/aappleby/GBMicrotest
- https://github.com/adtennant/GameboyCPUTests
- Documenting swift code
- https://github.com/mattcurrie/dmg-acid2
- https://github.com/retrio/gb-test-roms
- https://github.com/c-sp/gameboy-test-roms?tab=readme-ov-file
- official swift documentation
- official GameBoy programming manual (internet archive)
- GameBoy CPU manual (internet archive)
- https://github.com/gbdev/awesome-gbdev
- https://datacrystal.romhacking.net/wiki/Tetris_(Game_Boy):RAM_map
Game Boy and Nintendo are used under nominative use. As for logo's bytes inclusion please read Sega v. Accolade.
