My CHIP-8 Interpreter

Tetris Invaders
Click on the images above to play the games in your web browser. The games are from Frédéric Devernay's SVision-8 website. Controls are through the keyboard, so unfortunately you can't play on a tablet device at the moment.

Background

I was born in the early 1980s, and my earliest memories of computers are from IBM PC clones that my dad brought home in the mid 1980's. Alternative home computers, such as the Apple II and the Commodore 64, weren't that well known or common in South Africa.

What I'm trying to say is that I don't have any real experience with computers that came before the IBM clones, but I always enjoy reading up on the subject. So I was pleasantly amused to learn of CHIP-8, a virtual machine for playing video games from the mid-1970s. It was originally invented by Joseph Weisbecker.

It dates back to a time when users were still expected to assemble their computers from the discrete components themselves. In fact I've never even heard of the computers on which it originally ran: The COSMAC VIP and Telmac 1800.

The Wikipedia page describes CHIP-8 as a programming language, but that's a bit generous. CHIP-8 is more of a specification for a virtual machine that defines a set of instructions and an environment in which to interpret them.

To program in CHIP-8 you actually have to input the individual machine codes in hexadecimal. In other words you have to assemble your programs by hand, on paper, before entering the binary code into your computer.

The CHIP-8 environment has a 64×32 pixel display with monochrome graphics. CHIP-8 programs don't draw individual pixels, but rather copy sprites to the display memory.

Its sound consists of a single tone, the frequency of which depends on the implementation. The developer only gets to control the duration of the beep.

Games are limited to 4KB for the code and graphics.

In spite of these limitations, there is still a community of enthusiasts around it. There is also wide variety of games available for it, mostly simple games like Pong, Space Invaders and Tetris clones.

All in all, it is like stone age Flash: A cross-platform environment in which a variety of different games can be run.

Naturally I wanted such an interpreter of my own. I've now finished it, and I've placed the source code on GitHub: https://github.com/wernsey/chip8

My Implementation

The primary version uses the Simple DirectMedia Layer (SDL) (version 2) for managing the graphics. It has the advantage of being portable to a variety of operating systems. I've compiled and tested it on Windows and Linux and in web browsers.

The web browser version was created by compiling the C code to JavaScript with Emscripten.

At the moment there are some caveats to running it in a web browser. The most important being that if you want to run a new CHIP-8 binary file you have to recompile the entire interpreter because it uses Emscripten's --preload-file to store the CHIP-8 program in a format that can be read by the JavaScript.

Under Windows, there is also a second version that uses only Win32 (the Windows API) calls drawing the screen only with GDI (Graphics Device Interface) calls. This version has no third party dependencies, so it is easy to redistribute.

My interpreter also supports the SuperChip instructions, which is an extension of the original with a higher resolution graphics mode.

The interpreter also has a debugger. You can press F5 in a running program or start the interpreter with the -d command-line option. When in debug mode, press F6 to step through the code and F8 to resume the program (F7 would've been used for "step into", but CHIP-8 has no notion of function calls).

Here is a screenshot of the interpreter with the debugger active:
Debugger

Because it is 2016 and assembling your code by hand is so old fashioned, I've also implemented an assembler. The syntax is based on the syntax described in Cowgod's Chip-8 Technical Reference v1.0, by Thomas P. Greene.

The following is an example of a program that draws a companion cube bouncing horizontally across the screen:
Companion Cube

; Companion Cube Sample program. Disregard its advice.

; Define some more human-friendly names for the registers
define boxx V0 ; Sprite X,Y position
define boxy V1
define oldx V2 ; Previous sprite X,Y position
define oldy V3
define dirx V4 ; Sprite direction
define diry V5
define tmp VE

; Clear the screen
    CLS
    
; Load the variables' initial values
    LD  boxx, 1
    LD  dirx, 1
    LD  boxy, 10
    LD  I, sprite1
    DRW boxx, boxy, 8
    LD  tmp, 1  

; The main loop
loop:
    ; Store the current position 
    LD oldx, boxx
    LD oldy, boxy
    
    ; If the X direction is 0, go to sub1...
    SE dirx, 0
    JP sub1
    
    ; ...otherwise add 1 to the box' position 
    ADD boxx, 1
    
    ; If you reached the right edge of the screen, change direction
    SNE boxx, 56
    LD  dirx, 1
    jp draw1
sub1: 
    ; subtract 1 from the box' position
    SUB boxx, tmp
    
    ; If you reached the left edge of the screen, change direction
    SNE boxx, 0
    LD  dirx, 0 
    
; Draw the box
draw1:  
    ; Load the address of the sprite's graphics into register I
    LD  I, sprite1
    ; Erase the sprite at the old position
    DRW oldx, oldy, 8
    ; Draw the sprite at the new position
    DRW boxx, boxy, 8
    
    ; Return to the start of the loop
    JP  loop
    
; Binary data of the sprite.
; 1s represent pixels to be drawn, 0s are blank pixels.
sprite1:
    db  %01111110,
        %10000001,
        %10100101,
        %10111101,
        %10111101,
        %10011001,
        %10000001,
        %01111110,

To assemble the file, run the command ./c8asm -o GAMES/CUBE.ch8 cube.asm

Finally, I've also implemented a disassembler. It actually started as a program to test the assembler output, but it was fairly simple to convert it to a proper disassembler.

To run the disassembler, just run the command ./c8dasm GAMES/CUBE.ch8

References

Here are some references for further reading:

  1. https://en.wikipedia.org/wiki/CHIP-8
  2. Frédéric Devernay's SVision-8 website has a wealth of information. He also has a collection of CHIP-8 games and programs in his GAMES.zip file. The Tetris, Brix and Invaders games I link to from here comes from that file.
  3. Cowgod's Chip-8 Technical Reference v1.0, by Thomas P. Greene, http://devernay.free.fr/hacks/chip8/C8TECH10.HTM
  4. http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/
  5. CHIP8 A CHIP8/SCHIP emulator Version 2.2.0, by David Winter http://devernay.free.fr/hacks/chip8/CHIP8.DOC
  6. Chip 8 instruction set, author unknown(?), http://devernay.free.fr/hacks/chip8/chip8def.htm
  7. Byte Magazine Volume 03 Number 12 - Life pp. 108-122. "An Easy Programming System," by Joseph Weisbecker, https://archive.org/details/byte-magazine-1978-12
  8. http://chip8.wikia.com/wiki/Chip8
  9. http://chip8.wikia.com/wiki/Instruction_Draw
  10. Mastering CHIP-8 by Matthew Mikolay, http://mattmik.com/chip8.html
  11. Octo, John Earnest, https://github.com/JohnEarnest/Octo
  12. Octo SuperChip document, John Earnest, https://github.com/JohnEarnest/Octo/blob/gh-pages/docs/SuperChip.md
  13. http://www.codeslinger.co.uk/pages/projects/chip8/primitive.html