R8 is a CHIP-8 emulator written in Rust. This repository is organized as a Cargo workspace with multiple crates, so each piece of functionality can be used independently or together to compose the application.
r8-core: core types & utilities (addresses, memory, opcodes, registers, timers, stack, errors)r8-emulator: the emulator runtime (usesr8-core); suitable to build your own frontends/toolsr8-assembly: assembler & tokenizer (standalone crate, planing to build a disassembler later)r8-gui: Bevy/egui frontend (usesr8-emulator,r8-core)r8-tui: Terminal UI frontend (usesr8-emulator,r8-assembly,r8-core)
- Project is now a Cargo workspace with multiple crates.
- The previous toggling of the TUI/GUI via features is no longer required. Each frontend is a separate crate + binary:
- GUI binary:
gui - TUI binary:
tui
- GUI binary:
- Each frontend is independent; you can use
r8-emulatoralone to build a new frontend (e.g. SDL, Web, or any UI system). - Assembly tooling (
r8-assembly) is a standalone crate used by frontend to assemby source files.
- Rust toolchain (rustup)
- On Linux:
- Other dependencies your system might require for Bevy or audio backends
- On Windows:
- Rust toolchain and any native dependencies for Bevy as needed
From repo root:
- Build everything:
cd R8
cargo build- Run GUI (Bevy + egui frontend):
cargo run --release --bin gui- Run TUI (terminal frontend):
cargo run --release --bin tui -- --rom path/to/rom.rom
# or use assembled text input:
cargo run --release --bin tui -- --asm path/to/asm.8sOn a workspace, binaries can be run with
cargo run --release --bin {gui|tui}. If you prefer to target the specific crate by package, use:cargo run -p r8-gui --release --bin guiorcargo run -p r8-tui --release --bin tui.
- No more feature flags are required to run GUI or TUI β each is a separate crate and binary.
- If you want to build a new frontend, depend on
r8-emulatorin your crate'sCargo.tomland use theEmulatortype to drive the emulation:
Example (minimal usage of r8-emulator in a new frontend):
use r8_emulator::Emulator;
fn main() {
let mut emu = Emulator::new();
// Load ROM from file (or another source)
let rom_file = std::fs::File::open("examples/pong.rom").unwrap();
emu.load_rom(rom_file).unwrap();
// A simple emulation loop
loop {
emu.tick().unwrap(); // handles CPU tick / timers
// Read emu.display() to render the frame, etc.
// Use emu.press_key(...) / emu.release_key(...) to forward input
}
}- The assembler can be used from
r8-assemblyby callingr8_assembly::assemble(...)from other crates or tooling.
r8-core/β Core libraryr8-emulator/β Emulator runtime (library)r8-assembly/β Assembler libraryr8-gui/β GUI binary (Bevy)r8-tui/β TUI binary (crossterm)
The TUI CLI supports:
USAGE:
tui [OPTIONS] [--rom <ROM PATH>] [--asm <ASM FILE>]
OPTIONS:
-d, --debug Enable debug mode (verbose logging)
-r, --rom <PATH> Load a ROM file
-a, --asm <PATH> Load an assembly file and assemble it to ROM
For the GUI, the recorder uses a file dialog to load ROMs by default (no CLI rom path required), and you can toggle debug logging via environment or the TUI debug flags.
- All CHIP-8 opcodes implemented
- Emulation (display, keyboard, timers, sound)
- Debugging UI (GUI + helper functions)
- Bevy GUI frontend
- TUI frontend with CLI options
- Assembler available as a library (
r8-assembly)
- Add a WebAssembly target
- Add disassembler crate or CLI
- Add save/load emulator state
- Improve the debug panel (memory, instruction pipeline view)
- Add more frontends or improve modularity (e.g., headless server mode)
- Wikipedia article on CHIP-8
- CHIP-8 Technical Reference
- Mastering CHIP-8
- Public domain ROMs: https://www.zophar.net/pdroms/chip8.html
See LICENSE for licensing details.
