Skip to content

LeviTrammell/evilwasmboy

Repository files navigation

EvilWasmBoy - GameBoy Emulator for AI

A headless GameBoy/GameBoy Color emulator written in Rust, designed for AI agents and automated testing. Targets both native (library) and WASM environments.

Philosophy

Test-First Development: This emulator is built with comprehensive testing infrastructure from day one, enabling rapid iteration and validation against known-good test ROMs.

Headless & Agent-Friendly: No GUI, no audio output. Just a programmatic API that provides:

  • Frame buffer access (160×144 RGB pixels)
  • Button input control
  • Battery-backed RAM persistence (save games)
  • Screenshot export for vision models

Project Structure

  • gb-core/ - Core emulator library (CPU, GPU, MMU, etc.)
  • gb-test-harness/ - Testing infrastructure for ROM validation
  • test_roms/ - Downloaded test ROMs (gitignored)
  • scripts/ - Automation scripts for ROM downloads and testing

Quick Start

1. Download Test ROMs

make setup
# or manually:
./scripts/download_test_roms.sh

2. Run Tests

# Run all passing tests
cargo test

# Run tests that are still failing (implementation in progress)
cargo test -- --ignored

# Run specific test suite
cargo test --test blargg_cpu_instrs

3. Build for WASM

cargo build --target wasm32-unknown-unknown --release --package gb-core

Features

Battery-Backed RAM Persistence

Save game data is preserved across sessions using battery-backed RAM emulation. Supports:

  • MBC1 + RAM + Battery - Early cartridges
  • MBC3 + RAM + Battery - Mid-era cartridges with optional RTC
  • MBC5 + RAM + Battery - Later cartridges

Usage:

// Native Rust
let mut gb = GameBoy::new();
gb.load_rom(&rom_bytes)?;

if gb.has_battery() {
    // Save to file
    if let Some(ram_data) = gb.save_battery_ram() {
        std::fs::write("game.sav", ram_data)?;
    }

    // Load from file
    let save_data = std::fs::read("game.sav")?;
    gb.load_battery_ram(&save_data);
}
// WASM / Browser
const gb = new WasmGameBoy();
await gb.load_rom(romBytes);

if (gb.has_battery()) {
    // Save to LocalStorage
    const ramData = gb.save_battery_ram();
    localStorage.setItem('save', btoa(String.fromCharCode(...ramData)));

    // Load from LocalStorage
    const saved = localStorage.getItem('save');
    const bytes = Uint8Array.from(atob(saved), c => c.charCodeAt(0));
    gb.load_battery_ram(bytes);
}

See docs/BATTERY_RAM.md for detailed documentation.

Examples:

Development Workflow

  1. Run tests to see current failures
  2. Implement CPU/GPU features to pass tests
  3. Re-run tests to validate
  4. Refactor with confidence

Test ROM Sources

This project uses industry-standard test ROMs:

  • Blargg's Test ROMs - CPU instruction accuracy
  • Mooneye GB - Timing and hardware behavior
  • dmg-acid2 - PPU rendering accuracy

All test ROMs are automatically downloaded via make setup.

Performance Targets

  • Native: >1000 FPS (headless, for RL training)
  • WASM: ~60 FPS (real-time for web agents)
  • Memory: <10MB heap usage
  • Binary size (WASM): <500KB (after wasm-opt)

License

MIT OR Apache-2.0

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors