This past weekend I decided that I wanted to write an emulator for something in Go. As someone on twitter said to me, that only a developer would write en emulator just because! The main reasons though were to a) learn more about how CPUs work and b) build something fun.

Emulators and Me

I’ve always been a fan of emulation. Since I was a kid I’d get envious of friends who had a console that I didn’t and were able to play games I couldn’t. Admittedly it sometimes took a few years but I was eventually able to play those elusive SNES and N64 games on my PC.

So the way in which emulators work has always fascinated me. The ability to create working implementations of hardware purely in software is amazing to me.

Where to Start

Building emulators is hard. That became immediately apparent! I am a software engineer but I’ve spent my career working with high level languages. Meaning that I am quite far abstracted from the way in which CPUs and memory functions at a low level. The last time I even read about it would have been at Uni 10 years ago!

First step was to refresh my memory on binary, hex, CPUs and assembly. The internet is well stocked with information but I found Emulator 101 to be a great place to start. It explains the concepts in a really readable manner and even has a guide for building an 8080 emulator (watch this space :p).

Then of course I had to choose something to emulate. Initial thoughts of tackling an 8-bit game console were a tad ambitious to tackle at a first attempt. That’s when I came across CHIP8.

CHIP-8

Back in the 70’s there were a plethora of 8 bit microcomputers. These machines used hugely varying hardware between manufacturers and as a result had very different assembly languages. CHIP-8 was an interpreted programming language that ran on the CHIP-8 virtual machine. It was designed from the ground up to make writing video games easier for these computers. It only has 35 opcodes in it’s entirety so is a much smaller surface area to emulate.

I had never heard of CHIP-8 to be honest, shame on me. I find it’s whole concept fascinating, it’s not the earliest example of a virtual machine (they date back to the 60’s). But it is fun to draw parallels between this and modern interpreted languges with VMs (Java, Lua).

Progress so Far

Not a lot of code honestly! I spent most of the time getting familiar with the opcodes and CPU architecture. The article by Laurence Muller was an invaluable resource for getting started with CHIP-8. He is writing the emulator in C/C++ but the concepts are fairly easy to port to Go.

So far I have implemented the basic skeleton of the CHIP-8. The implementation has 4K of memory represented as a byte array:

type chip8 struct {
    ...
	memory [4096]byte
    ...
}
The first 512 bytes are reserved for the the interpreter, fonts etc. Programs are expected to start at 0x200. See map:

0x000 -> 0x1FF - Chip 8 interpreter (contains font set in emu)
0x050 -> 0x0A0 - Used for the built in 4x5 pixel font set (0-F)
0x200 -> 0xFFF - Program ROM and work RAM

Also implemented as a byte array are the CPU registers:

type chip8 struct {
    ...
	V [16]byte
    ...
}
The Chip 8 has 15 8-bit general purpose registers named V0,V1…VE. The 16th register (VF) is used for the ‘carry flag’.

Along with the registers we have an index register and program counter. These will be used during CPU cycles to step through memory and handle opcodes.

The next area of interest to me was the stack which we implement as an array of uint16:

type chip8 struct {
    ...
    stack [16]uint16
    ...
}
The Chip8 instruction set has opcodes that allow the program to jump to addresses or call subroutines. Consequently we need a stack to remember locations before a jump is performed.

Finally of course a modern CPU will run stupid amounts faster than the CHIP-8 would have done. Consequently we have two timers which we can use to ensure the cycles run at the correct speed. On the CHIP-8 these timers operate at 60Hz.

type chip8 struct {
    ...
    delayTimer byte // Intended for timing game events, can be set or read.
    soundTimer byte // Used for sound events. Beep when value is non-zero.
    ...
}

All the emulator does at the moment is initialise the CHIP-8 and load a rom into memory. The good thing about CHIP-8 games is that there are a huge amount of public domain roms available. Many of them clones of popular 70’s games like Pong and Space invaders. A quick search will hook you up.

Next Steps

Get something working basically. I need to get cracking with actually implementing the opcodes, only 35 of them to worry about, so could be worse. After I’m happy those are working then it’ll be time to hook in some graphics and sound.

Stay tuned!