Building a Chip-8 Emulator in Go

Bradford Lamson-Scribner
May 4 · 3 min read
Telmac 1800

Hey everyone, this post is less of a tutorial and more of a high level overview of chippy and how I went about building it. Hopefully it can serve as a starting point as well for anyone interested in building an emulator. Let’s jump in!

What is a Game Emulator?

A game emulator is a piece of software or hardware that emulates, or imitates, a video game console. With a video game emulator and the appropriate ROM or ISO files, it’s possible to play retro Nintendo, Sega, Playstation, N64, etc games right on your computer! I will be the first to admit that emulating something like an N64 would be much more fun to actually play afterwords. The problem is, I’ve never written an emulator and so I needed to start somewhere more approachable.

The Chip-8 is less complicated than a lot of other game systems you can emulate (with only 35 opcodes). So if you are interested in learning something like this, I highly recommend this as a starting point.

How Do I Build One?

I started by reading through a bunch of blogs, docs, etc. Then I chose the most helpful ones, and opened them up in their own set of tabs. Here are the sources I went with:

I chose these because they have a good mix of all the technical system data, opcodes, memory, etc for reference. The last post by Laurence Muller is more a tutorial for building a Chip-8 emulator written in C. This was really helpful at times for filling in some blanks, as he describes a lot around how the Chip-8 can be implemented.

Chippy

Chippy is my implementation written in Go. The entry-point for using chippy is a CLI, so to start up the emulator you would run:

chippy run path/to/rom

If your current working directory is the root of chippy, you can use the ROMs I pushed to the project. Example:

chippy run roms/pong.ch8

After spinning up the emulator, here is an overview of what happens:

  1. A new pixelgl window is created.
  2. A new chippy VM is created using the ROM and the pixelgl window.
  3. The font-set is loaded into memory.
  4. The ROM is loaded into memory
  5. Spins off a go routine that sets up audio and listens for audio events
  6. Spins off a go routine that runs the VM
  7. Listens for termination signals.

The VM itself is where most of the complexity comes in, which I’ve documented pretty heavily in the files, so I’m going to breeze over it here. Most of that lives in chippy/internal/chip8/chip8.go.

The idea is that it emulates CPU cycles at a particular clock speed (defaults to 60MHz, but will be configurable through a flag). Each cycle it reads an opcode and performs the intended operation (bitwise ops, shifting data to and from virtual registers, coordinating system graphics, decrementing/resetting timers, etc).

When the game window is closed, it pushes a shutdown event onto the Shutdown channel, cleans up, and shuts down. Contributions are welcome, thanks for reading!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store