go-headless-nes

module
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2026 License: MIT

README

go-headless-nes

License MIT Go Doc Release

The example frontend running Super Mario Bros.

A headless NES emulator core in Go. Zero dependencies, deterministic, cycle-accurate. You embed it as a Go library and drive it in-process. The UI, rewind and tooling are yours to build on top.

There is no window, no audio device, no scripting engine. Just the core and its primitives.

Features

  • Frame and instruction stepping: run a frame, single-step an instruction, reset.
  • Video and audio every frame: a 256x240 buffer of NES color indices and a block of float32 samples, plus ready-made RGBA and PCM conversion for frontends.
  • Memory access: peek (no side effects), poke, block reads.
  • Save states: save and restore the whole console as a blob. That's all you need to build rewind and save-slots.
  • Debugger: breakpoints, watchpoints, disassembly, nestest-format trace.
  • Live patching: edit RAM, ROM and mapper registers while the game runs.
  • Regions: NTSC, PAL and Dendy, auto-detected from the header and a built-in cartridge database (which corrects dumps that misreport their region), and overridable at runtime.

Window, audio output, key mapping, rewind and scripting are left out on purpose. They're policy, and they all fall out of the primitives above.

Installation

go get github.com/danielgatis/go-headless-nes

Quick Start

As a library:

import "github.com/danielgatis/go-headless-nes/nes"

console, _ := nes.NewConsole(rom)
console.RunFrame()
video := console.Video()   // 256*240 NES color indices
audio := console.Audio()   // float32 samples

Each Console is one independent instance, so N emulators are just N values. A Console is not safe for concurrent use; drive each from a single goroutine. A full runnable client lives in docs/CLIENT.md.

To run the tests:

git submodule update --init   # fetch the test ROMs
go test ./...                 # everything runs, no external deps

Example

A complete desktop frontend on Ebitengine, with video, audio and keyboard, lives in examples/nes. It is its own Go module, so the Ebitengine dependency never touches the core's go.mod:

cd examples/nes && go run . game.nes

Docs

License

Copyright (c) 2026-present Daniel Gatis

Licensed under MIT License

Buy me a coffee

Liked some of my work? Buy me a coffee (or more likely a beer)

Buy Me A Coffee

Directories

Path Synopsis
internal
apu
Package apu emulates the 2A03's audio unit: two pulse channels, a triangle, a noise channel, the DMC sample player, and the frame counter that paces their envelopes and length counters.
Package apu emulates the 2A03's audio unit: two pulse channels, a triangle, a noise channel, the DMC sample player, and the frame counter that paces their envelopes and length counters.
bus
Package bus is the CPU-side Memory fabric: a 64 KiB table of read and write handlers plus the console's work RAM and the two floating-bus latches.
Package bus is the CPU-side Memory fabric: a 64 KiB table of read and write handlers plus the console's work RAM and the two floating-bus latches.
cartridge
Package cartridge loads NES cartridge images and exposes their contents to the mapper layer.
Package cartridge loads NES cartridge images and exposes their contents to the mapper layer.
controller
Package controller emulates the standard NES joypad: a 4021 shift register that latches all eight buttons while strobed and shifts one bit out per $4016/$4017 read, plus the control manager that maps the two ports into the CPU address space and reproduces the read-clock cache (a same-address read on the same or an adjacent cycle does not shift the register twice).
Package controller emulates the standard NES joypad: a 4021 shift register that latches all eight buttons while strobed and shifts one bit out per $4016/$4017 read, plus the control manager that maps the two ports into the CPU address space and reproduces the read-clock cache (a same-address read on the same or an adjacent cycle does not shift the register twice).
cpu
Package cpu implements the Ricoh 2A03's 6502 core: the opcode and addressing tables, the master-clock cycle split (startCycle/endCycle), the two-stage NMI edge detector and IRQ pipeline, the end-of-instruction interrupt dispatch, and the cycle-accurate DMA unit driving OAM and DMC transfers with RDY-halt / dummy-read behavior.
Package cpu implements the Ricoh 2A03's 6502 core: the opcode and addressing tables, the master-clock cycle split (startCycle/endCycle), the two-stage NMI edge detector and IRQ pipeline, the end-of-instruction interrupt dispatch, and the cycle-accurate DMA unit driving OAM and DMC transfers with RDY-halt / dummy-read behavior.
debugger
Package debugger provides inspection tools built around the CPU's decode table: disassembly and execution tracing now, breakpoints and viewers as the debugger milestone lands.
Package debugger provides inspection tools built around the CPU's decode table: disassembly and execution tracing now, breakpoints and viewers as the debugger milestone lands.
errs
Package errs is this emulator's error-handling convention: every error created in production code carries a stack trace captured at its origin.
Package errs is this emulator's error-handling convention: every error created in production code carries a stack trace captured at its origin.
gamedb
Package gamedb is a CRC-indexed cartridge database that corrects ROM headers, the way the reference emulator does.
Package gamedb is a CRC-indexed cartridge database that corrects ROM headers, the way the reference emulator does.
mapper
Package mapper emulates cartridge boards: the address decoding, bank switching, on-board memory and expansion hardware between the console buses and the ROM.
Package mapper emulates cartridge boards: the address decoding, bank switching, on-board memory and expansion hardware between the console buses and the ROM.
nes
Package nes assembles the chips into a machine on one shared master clock: everything advances from inside the CPU's bus cycles.
Package nes assembles the chips into a machine on one shared master clock: everything advances from inside the CPU's bus cycles.
ppu
Package ppu emulates the 2C02 picture processing unit as a faithful sprite shifters, pixel output and the delayed-state machinery exactly as hardware does, so all observable timing (vblank/NMI, sprite 0 hit, overflow, the odd-frame skipped dot, $2007 buffering) matches.
Package ppu emulates the 2C02 picture processing unit as a faithful sprite shifters, pixel output and the delayed-state machinery exactly as hardware does, so all observable timing (vblank/NMI, sprite 0 hit, overflow, the odd-frame skipped dot, $2007 buffering) matches.
region
Package region holds the per-TV-system timing parameters that separate NTSC, PAL and Dendy consoles: master-clock dividers, PPU frame geometry, the odd-frame dot skip, and the audio rates.
Package region holds the per-TV-system timing parameters that separate NTSC, PAL and Dendy consoles: master-clock dividers, PPU frame geometry, the odd-frame dot skip, and the audio rates.
serial
Package serial is a tiny sequential binary reader/writer used by each emulated component to marshal its snapshot State.
Package serial is a tiny sequential binary reader/writer used by each emulated component to marshal its snapshot State.
testrom
Package testrom builds synthetic NROM cartridges for unit tests, so a test that only needs "a console that runs" does not have to load a real ROM.
Package testrom builds synthetic NROM cartridges for unit tests, so a test that only needs "a console that runs" does not have to load a real ROM.
Package nes is the public face of the emulator core.
Package nes is the public face of the emulator core.
test
assets
Package assets embeds the ROM images the integration suite runs against.
Package assets embeds the ROM images the integration suite runs against.
expect
Package expect is the suite's tiny assertion helper: a standard-library stand-in for the handful of testify helpers the tests used.
Package expect is the suite's tiny assertion helper: a standard-library stand-in for the handful of testify helpers the tests used.
harness
Package harness boots go-headless-nes consoles and drives ROM-based tests.
Package harness boots go-headless-nes consoles and drives ROM-based tests.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL