How to write an emulator (CHIP-8 interpreter)

How to write an emulator (CHIP-8 interpreter)

This guide is intended to give a brief introduction to the world of emulation and will also teach you how to write one yourself from scratch.

Personally I have been excited about emulators since the late 90’s. As I didn’t own a console back in the days (our family only had a C64), I was pleasantly surprised when I learned that you could use an emulator to run console games on the PC. I still remember playing Super Mario 3 on the PC using a SNES/Super Famicom emulator Snes9x and a few years later completing Metal Gear Solid using Bleem! (a PSX emulator).

These days however I’m more focussed on providing support to emulator projects of recent consoles such as: PCSX2 (Sony Playstation 2), Dolphin-emu (Nintendo Gamecube and Wii) and nullDC (Sega Dreamcast).

While this guide expects you to have some basic knowledge of computer systems and assumes you know a program language, it should also be an interesting read for people who are interested in emulation in general.

Space Invaders title screen

#define emulator

I think it’s important to first understand what an emulator is and isn’t.

An emulator is a computer program that mimics the internal design and functionality of a computer system (System A). It allows users to run software designed for this specific system (Sytem A) on a totally different computer system or architecture (System B).

Often people confuse a simulator with an emulator and vice versa. Just remember that these words aren’t synonyms.

Let’s take a look at the following example:
Pong is a 2D tennis game which was developed by Atari and ran on their own hardware. However, the game wasn’t just available on Atari systems, but also on rival platforms such as Amstrad, Amiga and the C64.

Since not every Pong game was licensed by Atari to run on these platforms, it also meant that not every game was running the code from Atari. Basically what happened is that people created their own implementation (clones) of the game Pong. In this case they simulated the looks and game behavior of Pong.

In case of an emulator, we choose not to re-implement the game Pong for our native system. Instead, we re-create the environment with a computer program which allows us to run the original machine code of Pong. A benefit of this is that it won’t just allow us to run Pong, but also any other application developed for that platform.

What is a CHIP-8?

The Chip 8 actually never was a real system, but more like a virtual machine (VM) developed in the 70’s by Joseph Weisbecker. Games written in the Chip 8 language could easily run on systems that had a Chip 8 interpreter.

Why start with a CHIP-8 emulator?

Writing a Chip 8 emulator is probably the easiest emulation project you can undertake. Due to small number of opcodes (35 in total for Chip 8) and the fact that a lot of instructions are used in more advanced CPUs, a project like this is educational (get a better understanding of how the CPU works and how machine code is executed), manageable (small number of opcodes to implement) and not too time consuming (project can be finished in a few days).

Brix: a Breakout clone

Before you start…

Space Invaders

CPU Specifications

When you start writing an emulator, it is important that you find as much information as possible about the system you want to emulate. Try to find out how much memory and registers are used in the system, what architecture it is using and see if you can get hold of technical documents that describe the instruction set.

In the case of the Chip 8, I would recommend taking a look at the Chip 8 description on Wikipedia.

I’ll give you a brief overview of the Chip 8 system and some hints on how to implement the essential parts:

unsigned short opcode; 
unsigned char memory[4096]; 
unsigned char V[16]; 
unsigned short I; unsigned short pc; 
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 
unsigned char gfx[64 * 32]; 
unsigned char delay_timer; unsigned char sound_timer; 

It is important to know that the Chip 8 instruction set has opcodes that allow the program to jump to a certain address or call a subroutine. While the specification doesn’t mention a stack, you will need to implement one as part of the interpreter yourself. The stack is used to remember the current location before a jump is performed. So anytime you perform a jump or call a subroutine, store the program counter in the stack before proceeding. The system has 16 levels of stack and in order to remember which level of the stack is used, you need to implement a stack pointer (sp).

unsigned short stack[16]; unsigned short sp; 

Finally, the Chip 8 has a HEX based keypad ( 0x0-0xF ), you can use an array to store the current state of the key.

unsigned char key[16]; 

Game Loop

To give you an idea on how to design your emulator, I made a small example of a layout. It does not teach you how to use GLUT or SDL to handle graphics and input but merely shows you how the flow of your emulator should be.

 1. #include 2. #include // OpenGL graphics and input 3. #include "chip8.h" // Your cpu core implementation 4. 5. chip8 myChip8; 6. 7. int main(int argc, char **argv) 8.  9. // Set up render system and register input callbacks 10. setupGraphics(); 11. setupInput(); 12. 13. // Initialize the Chip8 system and load the game into the memory 14. myChip8.initialize(); 15. myChip8.loadGame("pong"); 16. 17. // Emulation loop 18. for(;;) 19.  20. // Emulate one cycle 21. myChip8.emulateCycle(); 22. 23. // If the draw flag is set, update the screen 24. if(myChip8.drawFlag) 25. drawGraphics(); 26. 27. // Store key press state (Press and Release) 28. myChip8.setKeys(); 29. > 30. 31. return 0; 32. >