Skip to content

RaoulLuque/RustBoy

Repository files navigation

RustBoy

RustBoy is a Game Boy emulator written in Rust that can also be run in the browser. It emulates the original Game Boy as introduced in 1989. It is a work in progress and is not yet fully functional. However, some ROMs can already be run without and problems.

Emulation in this case describes the process of simulating the hardware and software of a device, in this case the Game Boy. This project is not about emulating the Game Boy as accurately as possible. Instead, a goal was, to structure the code in a way which is straightforward to understand and that may offer a good starting point for someone who wants to learn about (Game Boy) emulation.

Since this is my first emulation project, I used a lot of resources and tutorials to get started. As these might also be useful to others, I have listed some of them in Resources and Tutorials Used. I want to highlight the DMG-01 tutorial, which explains how to start writing a Game Boy emulator in Rust. A lot of parts are still missing, but this project can be seen as a continuation of that tutorial/implementation of what is still missing in that tutorial.

Showcase

Pocket Super Mario Land showcase Dr. Mario showcase Kirbys Dreamland showcase

Features

  • Emulation of the Game Boy
  • Passes all of Blarggs CPU instrs test roms
  • Implementation of all instructions except for STOP
  • Each scanline is rendered individually (to a buffer texture)
  • Scalable window
  • Runs in the browser using WASM

Implementation details

The emulator is implemented in Rust and tries to stay as close to the original hardware setup as possible. That is, there are three main components (structs) that make up the RustBoy (struct). These are:

  • CPU: responsible for executing the instructions and contains methods for doing so
  • PPU: responsible for handling the rendering of the graphics
  • MemoryBus: responsible for handling the memory access

The memory is stored in one single array like in the original hardware. This array is stored in the MemoryBus struct, which is then passed as a (mutable) reference to the different methods in case they need to read/write from/to memory.

Rendering to the PC/Browser is done using wgpu for the GPU interactions and winit for window handling. We render each scanline individually to a texture which stores the pixel data until a full frame is rendered. This texture is then rendered to the screen.

ROMs that work

The following is a list of ROMs that have been tested and work without any problems:

  • Dr. Mario
  • Tetris
  • Super Mario Land
  • Kirby's Dreamland
  • Is that a demo in your pocket?
  • TicTacToe

Resources and Tutorials Used

As stated in the introduction, the starting point for this project was the DMG-01: How to Emulate a Game Boy tutorial for writing a Game Boy emulator in Rust. Since that tutorial however, is not very complete, I had to look for other resources to fill in the gaps.

The main resource always mentioned in the context of Game Boy emulation is the Pan Docs. It is considered the "single most comprehensive technical reference to Game Boy available to the public". This reference includes information on all parts of the Game Boy. However, since it is a technical reference, it is not very beginner friendly. Instead I would recommend the above linked DMG-01, the Game Boy Emulation in JavaScript tutorial or this tutorial for an emulator written in C.

Pan Docs also misses another aspect, which is the specifications of the different opcodes. For this, I used two different resources. As the main reference, I used the RGBDS: gbz80(7) - CPU opcode reference. However, the Interactive GB Opcode Table visualizes the different opcodes in a much better way and also has brief explanations of what they do.

For the actual rendering to the computer screen/browser and learning wgpu and winit, I used the Learn Wgpu which gives a good introduction into wgpu and the basics of rendering/shaders (in Rust).

At last, for debugging (the CPU) I used the great Game Boy Doctor which is a tool that allows to compare logs with working emulators for Blarggs CPU instr test roms. I also used the Binjgb - A Game Boy emulator implemented in C with good trace logging for comparing logs instruction by instruction Game Boy emulator to compare my logs with its logs. For this, I wrote a small python script check_logs.py.

To debug the PPU and the rendering however, I used the dmg-acid2 test rom.

How to run the emulator

Although no special prerequisites should be needed, please check wgpu, winit and the learn wgpu for more information on possible issues with some platforms.

Running the emulator is as easy as running the following command:

cargo run --release -- --ROM "roms/[ROM_NAME].gb"

Note that [ROM_NAME] should be replaced with the name of the ROM you want to run. Some test roms are included in the roms folder.

One can also run the emulator in development mode by removing the --release flag. This will, however, slow down the emulator significantly.

Running the emulator in the browser

The emulator can also be run in the browser using WASM and wasm-pack. To do this, the build target wasm32-unknown-unknown needs to be installed. With this, one simply needs to run

wasm-pack build --target web --release  

A webserver can then, for example, be started by running

python3 -m http.server 8000

This just hosts the index.html file. The server is then running on localhost:8000.

Missing features

  • Being able to load a boot ROM
  • Sound emulation
  • MBCs

Releases

No releases published

Packages

No packages published