Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

danielgatis/go-headless-nes

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

Releases

Packages

Used by

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.