Guide To Writing Your First Emulator | CHIP - 8

Guide To Writing Your First Emulator | CHIP - 8

So you like playing retro games and want to make your own emulator ? Lesss Go !!!

ยท

5 min read

Motivation For This Article

I started programming in my childhood because of two things:

  1. I wanted to make games.
  2. I had keen interest in electronics or anything that can be controlled with code.

And as you might see where it's going, I have extreme interest in system programming and retro devices. And because of this, over years, CHIP - 8 emulator has become my de facto project whenever I learn a new language/framework. So, I have made CHIP - 8 emulator in Python (with PyGame for GUI), C++ (with Qt framework) and finally in Dart (with Flutter). Out of these, only Dart one is on GitHub as I made the other two long ago when I had not started putting projects on GitHub for no reason ๐Ÿซ .

Recently I started learning Rust, and obviously the first project I will build in it will be CHIP - 8 emulator. But the problem is that I always forget the OPCODES, Device Specs etc and have to look into my notes I made about CHIP - 8, over again. So this time I thought why not write all of that in an article as I have started blog writing so that I can have all of that on the web and maybe motivate others to build their emulator. So, let's write this.

I will try my best to not make it any language specific, but it's hard due to my C++ bias ๐Ÿซ . But if you have only worked with high level interpreted languages like Python and JS, and have no idea about signed/unsigned integers, words, bytes, bitwise operators etc, it's suggested to have a look at them first. Resource: This excellent playlist from the CrashCourse channel Watching only till video 24 will do.

What Is CHIP - 8 Exactly ?

CHIP - 8 isn't a real device so to say. It was in fact itself an interpreted languages written by Joseph Weisbecker in the mid 1970s. It was initially written for COSMAC VIP and later got to HP Calculators. CHIP - 8 made writing games for these devices very easy and you can easily see this by looking at the number of games made for it.

Telmac 1800 running CHIP-8 game Space Intercept (Joseph Weisbecker, 1978) Telmac 1800 running CHIP-8 game Space Intercept (Joseph Weisbecker, 1978) (Wikipedia)

And What's an Emulator ?

Emulator is just a program that behaves exactly the same as the device it is emulating. Basically a program that is a computer itself and can do all the functions of the computer in question. Fascinating, isn't it ?

Cool. But How Do You Write an Emulator ?

It's simple. All you need to do is, find the specifications of the device you want to emulate, i.e. CPU frequency, memory size, stack size and so on, and then write a program that behaves just like that. Let's understand this with an example of a hypothetical machine.

The Cheems Machine

Say there exists a device Cheems (sadly there exists a single programming language that compiles for Cheems and it's called Doge), which has following specifications:

  • 1 kilobytes of memory/RAM (1024 bytes)
  • 512 bytes of memory is already filled with system code like BIOS etc and you get only the remaining 512 bytes to work with.
  • It only supports integers and has neither software nor hardware support to work with floats.
  • It has special hardware such that whatever is fed as an input, it outputs the negative of it.
  • It's CPU supports only two instructions, namely PUT and OUTPUT. Doge supports both of these instructions.
  • You say put a b;, to write the integer 'a' to the memory location 'b'. Obviously a > 512 && a < 1024.
  • And output b, to print out the output of whatever is stored in the memory starting from memory address b.
  • Programs written for Cheems, when compiled, output the instructions in plain text. Eg: if a program wants the output of memory address 512, the compiled binary of this program is a plain text file containing "output 200" (as 512 in base 10 is same is 200 in hex).
  • Doge programs when run, store the output in a new text file in plain text.

Your task is to emulate Cheems. How would you do that ? Only things that we are concerned about are processing the compiled program (as eventually running all the programs of a system is what the emulator is made for) and then doing something with this processed program to give the same output as the original device. Let's think about it in pieces.

  • Cheems only has a memory and a CPU. No keyboard, no display, nothing. Only these two. How can these two be emulated ?
  • Since memory is only 1024 bytes, we can emulate it using an array of characters/unsigned short ints of size 1024, as an array is just a contiguous block of memory.
  • Since the CPU supports only two operations, we can simply emulate it using if-else.

So pseudo-code for a Cheems' emulator might look something like this:

// Read the program
inFile = readFile("program.txt");

// Create output file
outFile = makeFile("output.txt");

// Declare the memory and initialize with 0
memory = uint8_t[1024] {0};

for (line in inFile) {
    // get all the words of that line
    cmd = line.split(' ');
    if (cmd [0] == "output") {
        // The Function 'output' goes to memory location
        // cmd[1] (in hex) and starts reading bits till it finds 
        // an empty bit (a zero). It then puts the 
        // negative of whatever it has read till now to output.txt

        output(cmd[1]);
    } else {
        // The function 'put' copies all the bits of cmd[1]
        // bit by bit into memory, starting from address 
        // cmd[2] (in hex)

        put(cmd[1], cmd[2]);
    }
}

inFile.close();
outFile.close();

So the output of

put 255 200
output 200
put 255 201
output 200

will be

-255
-65535

How ? Draw an array of bits, do the operations of put, and see yourself.

I hope this gives you an idea of how exactly we think about when we start writing an emulator. Obviously we have not gone into finer details like whether Cheems uses Big Endian or Little Endian system, what happens in the case of overflows etc. All of those stuff, along with actually starting with CHIP - 8 emulator, we'll do in the next part of this article. Till then, why don't you write a Cheems' emulator in your favorite language ? ๐Ÿ˜Ž

ย