Build a CHIP-8 emulator from scratch¶
C++23 · SDL3 · macOS
In 1977, Joseph Weisbecker wrote an interpreter for the RCA COSMAC VIP, a 2 KB desk-sized computer. The interpreter gave the machine a tiny instruction set, a 64×32 display, a 16-key keypad, and two timers. Programs written for it were just bytes — and because the bytes were interpreted, they ran on any machine with the same interpreter. The virtual machine was called CHIP-8. It never had a CPU of its own.
This tutorial builds that machine again, from an empty main.cpp, in modern
C++ on a Mac. You will write the CPU loop, the memory, the display, the keypad,
and the buzzer yourself. No emulator library, no game engine, no copied ROM
listing: just 4,096 bytes of state and a while loop that advances it.
By the final chapter you will have:
- a working CHIP-8 and SUPER-CHIP emulator, with the historical quirks selectable;
- a test suite that proves it — golden traces, exhaustive decode, sanitizers;
- an optional XO-CHIP extension, an assembler, and a rewind debugger;
- a mental model that transfers to the Game Boy, the NES, and anything else with a fetch–decode–execute loop.
Start Chapter 1: A Computer in 4,096 Bytes See the roadmap
Why CHIP-8?¶
Most "write an emulator" advice points at the NES or the Game Boy, then abandons you somewhere around the PPU. CHIP-8 is different in a way that matters for learning:
- The whole machine fits on one page. Sixteen registers, 4 KB of memory, 35 instructions, one display, sixteen keys.
- The hard parts are still there. Fetch–decode–execute, timing, sprite collision, input, sound, compatibility, testing.
- Failure is visible immediately. A wrong flag shows up in a test ROM in seconds, not after a week of black screens.
- The platform is alive. People still write CHIP-8 games, and a mature test suite exists to tell you exactly what you got wrong.
Who this is for¶
You have written C++ before — variables, functions, classes, std::vector —
but you have never emulated anything. You are on macOS, you can run cmake and
clang++, and you want to understand the code rather than paste it.
You do not need to know SDL, assembly, or how a CPU works. This tutorial starts with a data sheet and a blank file.
How to use this tutorial¶
- Type the code. Every chapter shows the new pieces in small chunks, then the complete file so you can check yourself. Typing is where the learning happens.
- Build and run at each checkpoint. Every chapter ends with a program that works; nothing is left broken for "later".
- Run the checkpoint. It lists the exact things you should see. If they are not there, the troubleshooting table is the first place to look.
- Do at least one exercise. The stretch exercise is where the chapter's idea becomes yours.
- Say "next" when you are ready for the following chapter.
The machine comes first
Chapters 1–8 never open a window. You will see the CHIP-8 logo in your terminal before you see it on screen, and that is deliberate: when the window arrives in Chapter 9, you will know that the CPU was already correct.
The shape of the course¶
| Part | Chapters | What it covers |
|---|---|---|
| I — The Machine | 1–8 | Memory, decode, the CPU loop, flags, timing, sprites |
| II — The Frontend | 9–12 | SDL3 window, keypad, sound, playable games |
| III — Getting It Right | 13–14 | Historical quirks, golden traces, sanitizers, fuzzing |
| IV — Bigger Machines | 15–16 | SUPER-CHIP, then optionally XO-CHIP |
| V — Tools of the Trade | 17–19 | Assembler, rewind debugger, performance |
| VI — Beyond | 20 | The design doc for your next emulator |
The full chapter list, with prerequisites and status, is on the roadmap.
Before you start¶
You need Homebrew LLVM, CMake, and Ninja:
SDL3 joins in Chapter 9, when there is something worth drawing:
Check that the compiler is the Homebrew one, not Apple's:
You should see Homebrew clang version 23 or newer. The project's
CMakeLists.txt selects it for you; this command is just a sanity check.
The repository also contains the course's design notes, the CHIP-8 reference,
and the verification log in references/. You do not need them to follow the
tutorial, but they are there when you want to know why a chapter is shaped
the way it is.