MCPcopy Index your code
hub / github.com/RamiHg/RustyBoy

github.com/RamiHg/RustyBoy @v1.1.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.1.0 ↗ · + Follow
617 symbols 1,651 edges 64 files 35 documented · 6%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

RustyBoy

RustyBoy is a cycle-accurate Gameboy emulator written to be as close to the real hardware as possible.

The emulator is designed to mimic the environment of FPGA development. It is therefore not written for speed or efficiency (but still runs pretty fast).

Getting Started

RustyBoy works on any target supported by Rust. The audio backend works on Linux, Mac OS X, and Windows.

Prerequisites

cmake is required in all platforms to build the 3rd-party audio backend (libsoundio). Install using your favorite package manager: sudo apt/brew/scoop install cmake.

If you are still not able to build the audio dependencies, remove "audio" from the default features in soc.

Linux

pkg-config and PulseAudio are required for audio playback on Linux. To install (on Debian-based systems):

sudo apt install pkg-config pulseaudio

Usage

To run a ROM:

cargo run --release -- path_to_rom.gb

[1.1.0] What's New

Full changelog here.

Audio now works! Tested on Mac OS X and Windows. There are still some minor issues regarding some unimplemented features, but all-in-all, it works quite well. libsamplerate is used to accurately downsample the audio to 48kHz.

If you are running into issues getting the audio dependencies to compile, simply remove "audio" from the default feature set in soc/Cargo.toml.

Fixed a pretty gnarly bug regarding interrupt servicing.

RustyBoy currently only supports MBC1 and MBC3 cartridges.

Implementation

CPU

RustyBoy's CPU is based on a microcode specification that is completely written in a Google Sheets document. The document describes each opcode's t-cycle execution at the micro-code level.

The microcode csv is then read by the asm compiler, which verifies and compiles the microcode into its final structure. This microcode is what is actually used both by the Rust emulator, and the FPGA CPU.

This has the interesting side-effect that the CPU control unit is relatively simple - almost 260 lines. Most of the heavy lifting is in the data!

GPU

Most demoscene and video game ROMs that fully utilize the GPU rely on behavior that is accurate to the T (no pun intended). Having a perfectly accurate CPU without an equally accurate GPU is like installing a race car engine in the body of a Lada - it's just not going to look very impressive.

Unfortunately, most GPU behavior is undocumented. There are even slight edge-case differences between different revisions of the same model.

But due to recent heroic efforts by researchers, I was able to put together something that is fairly accurate. Watching that video should give you a good understanding of about 90% of the GPU's inner workings.

Status

At this point, I consider the emulator to be feature-complete (except audio). It's (almost) perfectly cycle accurate; at least in the areas that I care about.

It passes all Blargh, all (but one) MooneyeGB, and almost all Wilbert Pol tests. See the complete test status for a more detailed list of all passing/failing tests.

Of course, passing unit tests is all fine and dandy. The real fun is being able to run demo-scene ROMs (and video games). oh.gb and pocket.gb run almost flawlessly. Here is a montage of my favorite parts:

<image src="https://github.com/RamiHg/RustyBoy/raw/v1.1.0/docs/rustyboy.gif" />

License

RustyBoy is currently released as GPLv3, because I see no reason why anyone would derive from it. If you'd like a more permissive license, email me!

Extension points exported contracts — how you extend this code

MemoryMapped (Interface)
(no doc) [11 implementers]
soc/src/mmu.rs
Sound (Interface)
The trait that all sounds (square, wave, and noise) implement. Allows for a generic way of handling updates and sampling [3 …
soc/src/apu/sound.rs
AtomicInt (Interface)
Helpful trait to allow using atomics with any data type convertable from/to primitive integers. Used mainly with the aud
soc/src/util.rs
Cart (Interface)
(no doc) [2 implementers]
soc/src/cart.rs
Register (Interface)
(no doc)
soc/src/io_registers.rs

Core symbols most depended-on inside this repo

set
called by 44
soc/src/cpu/register.rs
with_lhs
called by 37
gb_disas/src/op_creation.rs
clone
called by 37
soc/src/gpu/sprites.rs
with_rhs
called by 25
gb_disas/src/op_creation.rs
push
called by 25
soc/src/gpu/fifo.rs
expect_none
called by 21
soc/src/cpu/asm/mod.rs
remap_alu_placeholder
called by 19
soc/src/cpu/asm/op_map.rs
remap_lhs_reg
called by 15
soc/src/cpu/asm/op_map.rs

Shape

Method 339
Function 188
Class 56
Enum 29
Interface 5

Languages

Rust100%

Modules by API surface

soc/src/gpu.rs47 symbols
soc/src/system.rs35 symbols
soc/src/gpu/test/mod.rs28 symbols
soc/src/test/context.rs26 symbols
soc/src/cpu/asm/compiler.rs24 symbols
soc/src/gpu/fetcher.rs23 symbols
soc/src/cpu/test/test_8bit_alu.rs21 symbols
soc/src/cart.rs17 symbols
soc/src/gpu/fifo.rs16 symbols
soc/src/cpu/asm/op_map.rs16 symbols
soc/src/apu/sound.rs16 symbols
soc/src/apu/mixer.rs16 symbols

For agents

$ claude mcp add RustyBoy \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact