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:
- Cowgod’s Chip-8 Technical Reference
- CHIP-8 Wiki
- Chip-8 Instruction Set
- Post by Matthew Mikolay
- Post by Laurence Muller
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 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:
- A new pixelgl window is created.
- A new chippy VM is created using the ROM and the pixelgl window.
- The font-set is loaded into memory.
- The ROM is loaded into memory
- Spins off a go routine that sets up audio and listens for audio events
- Spins off a go routine that runs the VM
- 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
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!