A Rust GameBoy emulator!
Tetris | Zelda: Link's Awakening |
---|---|
Super Mario Land | Super Mario Land 2 |
Galaga & Galaxian | Mortal Kombat |
Pac-Man | Alleyway |
Space Invaders | Road Rash |
Donkey Kong | Frogger |
dmg-acid2 | |
gbrs supports:
- Mid-frame scanline effects (required for games like Road Rash)
- The Window (a GPU feature required for Pac Man and Zelda)
- Cycle-accurate CPU & counters
- Save files & saved games (Zelda & Super Mario Land 2 use these)
- The Window internal line counter (an unusual quirk required for perfect DMG-ACID2 rendering)
- LCD Stat interrupt bug (a bug present on the real Gameboy hardware required for Road Rash)
- Memory Board Controller 1 (MBCs are required for some more complex games)
- Memory Board Controller 2
- Memory Board Controller 3 (Real-time clock WIP)
- Sound!
& more!
I'm still working on gbrs (and having a tonne of fun doing it!).
The main thing(s) I'm working on:
- MBC3 RTC for real-world timekeeping in Pokemon
- Laying the foundations for GameBoy Color support
- Performance optimisations for bare-metal ports
gbrs is not yet finished enough to distribute binaries, but if you want to try it out:
The repo contains ports for multiple graphics backends. SDL is the easiest to build.
The SDL port comes with everything you need to compile & run in one command. If you experience issues with screen tearing or cracking sound, check out the SFML port instead.
git clone https://github.com/adamsoutar/gbrs
cd gbrs/sdl-gui
cargo run --release ROM_PATH
(Replace ROM_PATH with the path to a .gb file)
You'll need SFML set up, which you can find instructions for here.
Afterwards, in a terminal, you can execute these commands, assuming you have a Rust toolchain installed.
git clone https://github.com/adamsoutar/gbrs
cd gbrs/sfml-gui
cargo run --release ROM_PATH
gbrs is written to be ported to other platforms. Its default GUIs for Windows, macOS and Linux are just modules that it doesn't have to use.
You can port gbrs-core to almost anything - especially since it supports running without the Rust StdLib.
All a port needs to do is:
use gbrs_core::cpu::Cpu;
let mut gameboy = Cpu::from_rom_bytes(
include_bytes!("./tetris.gb").to_vec()
);
// Each frame:
gameboy.step_one_frame();
draw_screen(&gameboy.gpu.finished_frame);
// (where draw_screen is a platform-specific function left to the reader)