Mooneye GB is a Game Boy emulator written in Rust.
The main goals of this project are accuracy and documentation. Some existing emulators are very accurate (Gambatte, BGB >= 1.5) but are not documented very clearly, so they are not that good references for emulator developers. I want this project to document as clearly as possible why certain behaviour is emulated in a certain way. This also means writing a lot of test ROMs to figure out corner cases and precise behaviour on real hardware.
Non-goals:
- CGB (Game Boy Color) support. It would be nice, but I want to make the normal Game Boy support extremely robust first.
- A good debugger. A primitive debugger exists for development purposes, and it is enough.
- A user interface. Building native UIs with Rust is a bit painful at the moment.
Warning:
- Project is WIP
- Doesn't work properly without a boot ROM
This project already passes Blargg's cpu_instrs, instr_timing, and mem_timing-2 tests.
Things that need significant work:
- GPU emulation accuracy
- APU emulation in general
There's tons of documentation and tons of emulators in the internet, but in the end I only trust real hardware. I follow a fairly "scientific" process when developing emulation for a feature:
- Think of different ways how it might behave on real hardware
- Make a hypothesis based on the most probable behaviour
- Write a test ROM for such behaviour
- Run the test ROM on real hardware. If the test ROM made an invalid hypothesis, go back to 1.
- Replicate the behaviour in the emulator
All test ROMs are manually run with these devices:
Device | Model | Mainboard | CPU |
---|---|---|---|
Game Boy | DMG-01 | DMG-CPU-04 | DMG CPU B |
Game Boy Pocket | MGB-001 | MGB-ECPU-01 | CPU MGB Β |
Game Boy Pocket | MGB-001 | MGB-LCPU-01 | CPU MGB Β |
Super Game Boy | SNSP-027 | SGB-R-10 | SGB-CPU-01 |
Super Game Boy | SHVC-027 | SGB-R-10 | SGB-CPU-01 |
Super Game Boy 2 | SHVC-042 | SHVC-SGB2-01 | CPU SGB2 |
Game Boy Color | CGB-001 | CGB-CPU-03 | CPU CGB C |
Game Boy Color | CGB-001 | CGB-CPU-04 | CPU CGB D |
Game Boy Color | CGB-001 | CGB-CPU-05 | CPU CGB D |
Game Boy Advance | AGB-001 | AGB-CPU-10 | CPU AGB A |
Game Boy Advance SP | AGS-001Β | C/AGS-CPU-21 | CPU AGB B E |
Game Boy Advance SP | AGS-101Β | C/AGT-CPU-01 | CPU AGB B E |
These devices will also be used, but results for old tests have not yet been verified:
Device | Model | Mainboard | CPU |
---|---|---|---|
Game Boy | DMG-01 | DMG-CPU-02 | DMG CPU A |
Game Boy | DMG-01 | DMG-CPU-06 | DMG CPU B |
Game Boy Color | CGB-001 | CGB-CPU-02 | CPU CGB B |
Game Boy Color | CGB-001 | CGB-CPU-06 | CPU CGB E |
Game Boy Advance | AGB-001 | AGB-CPU-01 | CPU AGB |
For now, the focus is on DMG/MGB/SGB/SGB2 emulation, so not all tests pass on CGB/AGB/AGS or emulators emulating those devices.
Always compile in release mode if you care about performance!
On a i7-3770K desktop machine I can usually run ROMs with 2000 - 4000% speed. Without optimizations the speed drops to 150 - 200%, which is still fine for development purposes.
Raspberry Pi with X11 desktop works but is too slow because there is no OpenGL acceleration.
The emulator is runnable on Android, but cross-compiling and packaging is a huge pain and touch controls would have to be implemented, so I'm not supporting Android at the moment.
cargo run --release
- Follow the instructions
- Acquire a Game Boy bootrom, and put it to
$HOME/.mooneye-gb/dmg_boot.bin
cargo build --release
cargo run --release -- PATH_TO_GAMEBOY_ROM
On Windows, also download an SDL2 package containing SDL2.dll, and put it to target/debug
and target/release
.
Game Boy | Key |
---|---|
Dpad | Arrow keys |
A | Z |
B | X |
Start | Return |
Select | Backspace |
Function | Key |
---|---|
Fast forward | Shift |
Toggle performance overlay | F2 |
Versions used:
- mooneye-gb (master)
- BGB 1.5.2
- Gambatte 2015-03-23 (f9fb003)
- GiiBiiAdvance 2015-05-16 (dbf669a)
- Higan v098 (in Game Boy mode, except for SGB/SGB2-specific test ROMs)
- KiGB 2.05
- MESS 0.163
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
cpu instrs | π | π | π | π | π | β | π |
dmg sound 2 | β | π | π | β | β | β | β |
instr timing | π | π | π | π | π | β | π |
mem timing 2 | π | π | π | π | π | β | π |
oam bug 2 | β | β | β | β | β | β | β |
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
add sp e timing | π | β | π | β | π | β | β |
boot hwio G | π | π | π | β | π | β | β |
boot regs dmg | π | π | π | π | π | π | π |
call timing | π | β | π | β | π | β | β |
call timing2 | π | β | π | β | π | β | β |
call cc_timing | π | β | π | β | π | β | β |
call cc_timing2 | π | β | π | β | π | β | β |
di timing GS | π | π | π | β | π | π | π |
div timing | π | π | π | π | π | β | π |
ei timing | π | π | π | π | π | π | π |
halt ime0 ei | π | π | π | π | π | π | π |
halt ime0 nointr_timing | π | π | π | π | π | β | β |
halt ime1 timing | π | π | π | π | π | β | π |
halt ime1 timing2 GS | π | π | π | β | π | β | π |
if ie registers | π | π | π | π | π | β | π |
intr timing | π | π | π | π | π | β | π |
jp timing | π | β | π | β | π | β | β |
jp cc timing | π | β | π | β | π | β | β |
ld hl sp e timing | π | β | π | β | π | β | β |
oam dma_restart | π | β | π | β | π | β | β |
oam dma start | π | β | π | β | π | β | β |
oam dma timing | π | β | π | β | π | β | β |
pop timing | π | β | π | π | π | β | π |
push timing | π | β | β | β | π | β | β |
rapid di ei | π | π | π | π | π | π | π |
ret timing | π | β | π | β | π | β | β |
ret cc timing | π | β | π | β | π | β | β |
reti timing | π | β | π | β | π | β | β |
reti intr timing | π | π | π | π | π | π | π |
rst timing | π | β | β | β | π | β | β |
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
mem oam | π | π | π | π | π | π | π |
reg f | π | π | π | π | π | π | π |
unused_hwio GS | π | β | π | β | β | β | β |
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
hblank ly scx timing GS | π | β | β | β | β | β | β |
intr 1 2 timing GS | π | π | π | β | π | β | π |
intr 2 0 timing | π | π | β | β | π | β | β |
intr 2 mode0 timing | π | π | β | β | β | β | β |
intr 2 mode3 timing | π | π | β | β | β | β | β |
intr 2 oam ok timing | π | π | β | β | β | β | β |
intr 2 mode0 timing sprites | β | β | β | β | β | β | β |
stat irq blocking | β | β | π | β | β | β | β |
vblank stat intr GS | π | π | β | π | π | β Β | β |
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
div write | β | π | β | π | π | β | β |
rapid toggle | β | β | β | π | β | β | π |
tim00 div trigger | π | β | π | π | β | β | β |
tim00 | β | π | β | π | π | β | β |
tim01 div trigger | β | π | β | π | β | β | β |
tim01Β | π | π | π | π | π | β | β |
tim10 div trigger | βΒ | π | β | π | β | β | π |
tim10 | βΒ | π | β | π | π | β | β |
tim11 div trigger | π | β | β | π | β | β | β |
tim11 | βΒ | π | β | π | π | β | β |
tima reload | β | β | β | π | β | β | β |
tima write reloading | β | β | β | π | β | β | β |
tma write reloading | β | β | β | π | β | β | β |
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
mbc1 rom 4banks | π | β | π | π | π | β | π |
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
sprite priority | π | π | π | β | π | β | β |
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
boot hwio C | π | β | β | β | |||
boot hwio S | β | Β | β | π | β | β | |
boot regs A | β | β | β | ||||
boot regs cgb | π | β | β | π | |||
boot regs mgb | π | π | π | ||||
boot regs sgb | β | π | π | β | π | ||
boot regs sgb2 | β | π | β | β |
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
unused hwio C | β | β | β | β |
Test | mooneye-gb | BGB | Gambatte | GiiBiiAdvance | Higan | KiGB | MESS |
---|---|---|---|---|---|---|---|
vblank stat intr C | β | β | β | β |
Some tests are expected to pass only a single type of hardware:
- dmg = Game Boy
- mgb = Game Boy Pocket
- sgb = Super Game Boy
- sgb2 = Super Game Boy 2
- cgb = Game Boy Color
- agb = Game Boy Advance
- ags = Game Boy Advance SP
In general, hardware can be divided on to a couple of groups based on their behaviour. Some tests are expected to pass on a single or multiple groups:
- G = dmg+mgb
- S = sgb+sgb2
- C = cgb+agb+ags
- A = agb+ags
For example, a test with GS in the name is expected to pass on dmg+mgb + sgb+sgb2.
Mooneye GB is licensed under GPLv3+. Copyright (C) 2014-2016 Joonas Javanainen joonas.javanainen@gmail.com