Skip to content
Craig Thomas edited this page May 25, 2018 · 8 revisions

Yet Another (Super) Chip 8 Emulator

Yet Another (Super) Chip 8 Emulator (YASC8E) is a CHIP-8 virtual machine written in Python. The virtual machine is capable of running CHIP-8 ROMs as well as Super CHIP-8 ROMs.

Contents

What is a CHIP-8?

CHIP-8 is an interpreted language, not an actual hardware device. The whole point of the CHIP-8 was to create a language which would have a standardized execution profile across different hardware platforms (much like the Java language specification and Java Virtual Machine). According to sources such as Wikipedia, CHIP-8 virtual machines were written for several different platforms from the late 70's to the early 90's – the most notable being for HP graphics calculators.

What makes writing a CHIP-8 emulator a good learning project is it's simplicity. There are roughly 40 instructions, each of which is composed of 2 bytes. Compared to other architectures, the CHIP-8 has only a single addressing mode (inherent), a simple memory structure, and straightforward I/O routines. There is also a wealth of knowledge readily available about the CHIP-8, and many other implementations of it available for reference if you need to know how something should work.

Installation Instructions

In general, the emulator should run properly on any machine where Python 2.7+ and PIP are available. See the notes below for platform specific instructions.

Ubuntu

The installation under Ubuntu requires several different steps:

  1. Install SDL libraries. The SDL (Simple DirectMedia Layer) libraries are used by PyGame to draw images on the screen. Several other dependencies are needed by SDL in order to install PyGame. To install the required SDL libraries (plus dependencies) from the command-line:

    sudo apt-get install libfreetype6-dev libsdl-dev libsdl-image1.2-dev \ 
    libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsdl-sound1.2-dev \
    libportmidi-dev python-dev
    
  2. Install Mercurial. The hg command-line tool is required when using pip (see next step) to install the requirements for the project. To install Mercurial from the command-line:

    sudo apt-get install mercurial
    
  3. Install PIP. The pip package manager is used for managing Python packages. To install pip from the command-line:

    sudo apt-get install wget
    wget https://bootstrap.pypa.io/get-pip.py
    sudo python ./get-pip.py
    
  4. Alternatively, pip may be distributed by Ubuntu's package manager. You can try:

    sudo apt-get install pip
    
  5. Clone (or download) the Chip 8 emulator project:

    sudo apt-get install git
    git clone [email protected]:craigthomas/Chip8Python.git
    
  6. Install the requirements from the project:

    pip install -r requirements.txt
    

Cygwin

Running

Basic Usage

The command-line interface requires a single argument, which is the full path to a Chip 8 ROM:

python chip8/yac8e.py /path/to/rom/filename

This will start the emulator with the specified ROM.

Screen Scale

The -s switch will scale the size of the window (the original size at 1x scale is 64 x 32). For example, to scale the window so that it is 10 times the normal size:

python chip8/yac8e.py /path/to/rom/filename -s 10

Execution Delay

The -d switch instructs the emulator to add a delay to every operation that is executed. For example, add a 10 ms delay to every opcode that is executed:

python chip8/yac8e.py /path/to/rom/filename -d 10

This is useful for very fast computers (note that it is difficult to find information regarding opcode execution times, as such, I have not attempted any fancy timing mechanisms to ensure that instructions are executed in a set amount of time).

Keyboard Keys

The file chip8/config.py contains several variables that can be changed to customize the operation of the emulator. The most important one is the KEY_MAPPINGS variable. The Chip 8 has 16 keys:

  • The keys 0-9
  • The letters A-F

The default configuration of the emulator will map the keypad numeric keys 0-9 to the keys 0-9, and the keyboard keys a-f onto A-F. If you wish to configure a different key-mapping, simply change the variable to reflect the mapping that you want.

Instruction Set

The first hex digit of the instruction usually provides a hint at what major operation is about to occur. The next three hex digits encode numeric information, or the registers that the operations work on. Here is a mostly complete set of Chip 8 instructions:

  • 00E0 - Clear the screen
  • 00EE - Return from subroutine
  • 1nnn - Jump to address nnn
  • 2nnn - Call routine at address nnn
  • 3snn - Skip next instruction if register s value equals nn
  • 4snn - Do not skip next instruction if register s value equals nn
  • 5st0 - Skip if register s value equals register t value
  • 6snn - Load register s with value nn
  • 7snn - Add value nn to register s
  • 8st0 - Move value from register s to register t
  • 8st1 - Perform logical OR on register s and t and store in t
  • 8st2 - Perform logical AND on register s and t and store in t
  • 8st3 - Perform logical XOR on register s and t and store in t 8st4 - Add s to t and store in s - register F set on carry 8st5 - Subtract s from t and store in s - register F set on !borrow 8s06 - Shift bits in register s 1 bit to the right - bit 0 shifts to register F 8s0E - Shift bits in register s 1 bit to the left - bit 7 shifts to register F 9st0 - Skip next instruction if register s not equal register t Annn - Load index with value nnn Bnnn - Jump to address nnn + index Ctnn - Generate random number between 0 and nn and store in t Dstn - Draw n byte sprite at x location reg s, y location reg t Ft07 - Move delay timer value into register t Ft0A - Wait for keypress and store in register t Fs15 - Load delay timer with value in register s Fs18 - Load sound timer with value in register s Fs1E - Add value in register s to index Fs29 - Load index with sprite from register s Fs33 - Store the binary coded decimal value of register s at index Fs55 - Store the values of register s registers at index Fs65 - Read back the stored values at index into registers
Clone this wiki locally