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.
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
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.
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
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
-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
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.
; 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
Here are some references for further reading: