Skip to content

A Game Boy research project and emulator written in Rust

License

Notifications You must be signed in to change notification settings

wilbertpol/mooneye-gb

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Mooneye GB

Mooneye GB is a Game Boy emulator written in Rust.

Build Status

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

Accuracy

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:

  1. Think of different ways how it might behave on real hardware
  2. Make a hypothesis based on the most probable behaviour
  3. Write a test ROM for such behaviour
  4. Run the test ROM on real hardware. If the test ROM made an invalid hypothesis, go back to 1.
  5. 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.

Performance

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.

Running the emulator

GUI

  1. cargo run --release
  2. Follow the instructions

Command-line

  1. Acquire a Game Boy bootrom, and put it to $HOME/.mooneye-gb/dmg_boot.bin
  2. cargo build --release
  3. 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 keys

Game Boy Key
Dpad Arrow keys
A Z
B X
Start Return
Select Backspace

Other keys

Function Key
Fast forward Shift
Toggle performance overlay F2

Accuracy comparison

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

Blargg's tests

Test mooneye-gb BGB Gambatte GiiBiiAdvance Higan KiGB MESS
cpu instrs πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘ ❌ πŸ‘
dmg sound 2 ❌ πŸ‘ πŸ‘ ❌ ❌ ❌ ❌
instr timing πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘ ❌ πŸ‘
mem timing 2 πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘ ❌ πŸ‘
oam bug 2 ❌ ❌ ❌ ❌ ❌ ❌ ❌

Mooneye GB acceptance tests

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 πŸ‘ ❌ ❌ ❌ πŸ‘ ❌ ❌

Bits (unusable bits in memory and registers)

Test mooneye-gb BGB Gambatte GiiBiiAdvance Higan KiGB MESS
mem oam πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘
reg f πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘
unused_hwio GS πŸ‘ ❌ πŸ‘ ❌ ❌ ❌ ❌

GPU

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 πŸ‘ πŸ‘ ❌ πŸ‘ πŸ‘ ❌ Β  ❌

Timer

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 ❌ ❌ ❌ πŸ‘ ❌ ❌ ❌

Mooneye GB emulator-only tests

Test mooneye-gb BGB Gambatte GiiBiiAdvance Higan KiGB MESS
mbc1 rom 4banks πŸ‘ ❌ πŸ‘ πŸ‘ πŸ‘ ❌ πŸ‘

Mooneye GB manual tests

Test mooneye-gb BGB Gambatte GiiBiiAdvance Higan KiGB MESS
sprite priority πŸ‘ πŸ‘ πŸ‘ ❌ πŸ‘ ❌ ❌

Mooneye GB misc tests

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 ❌ πŸ‘ ❌ ❌

Bits

Test mooneye-gb BGB Gambatte GiiBiiAdvance Higan KiGB MESS
unused hwio C ❌ ❌ ❌ ❌

GPU

Test mooneye-gb BGB Gambatte GiiBiiAdvance Higan KiGB MESS
vblank stat intr C ❌ ❌ ❌ ❌

Test naming

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.

License and copyright

Mooneye GB is licensed under GPLv3+. Copyright (C) 2014-2016 Joonas Javanainen joonas.javanainen@gmail.com

About

A Game Boy research project and emulator written in Rust

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Assembly 55.4%
  • Rust 40.4%
  • TeX 3.3%
  • GLSL 0.6%
  • Makefile 0.3%
  • Shell 0.0%