An Octo compatible XO Chip, Super Chip, and Chip 8 emulator.
This project is a Chip 8 emulator written in Python 3. The original purpose of the project was to create a simple learning emulator that was well documented and coded in terms that were easy to understand. It was also an exercise to learn more about Python. The result is a simple command-line based Chip 8 emulator.
In addition to supporting Chip 8 ROMs, the emulator also supports the XO Chip and Super Chip specifications. Note that while there are no special flags that are needed to run an XO Chip, Super Chip, or normal Chip 8 ROM, there are other compatibility flags that may need to be set for the ROM to run properly. See the Quirks Modes documentation below for more information.
There are two other versions of the emulator written in different languages:
This project makes use of an MIT style license. Please see the file called LICENSE.
Copy the source files to a directory of your choice. In addition to the source, you will need the following required software packages:
I strongly recommend creating a virtual environment using the virtualenv builder as well as the virtualenvwrapper tools. With these tools, you can easily create a virtual sandbox to install pygame and run the emulator in, without touching your master Python environment.
The installation under Ubuntu 20.04 requires several different steps:
-
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 install python3 python3-dev libsdl-dev libfreetype6-dev \ libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsdl-sound1.2-dev \ libportmidi-dev
-
Install PIP. The
pip
package manager is used for managing Python packages. To installpip
from the command-line:sudo apt install python3-pip
-
(Optional) Install virtual environment support for Python:
-
Install virtual environment support:
pip3 install virtualenv pip3 install virtualenvwrapper
-
First you must update your
.bashrc
file in the home directory and add a few lines to the bottom of that file:cat >> ~/.bashrc << EOF export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 export WORKON_HOME=$HOME/.virtualenvs export PATH=$PATH:$HOME/.local/bin source $HOME/.local/bin/virtualenvwrapper.sh EOF
-
Next you must source the
.bashrc
file:source ~/.bashrc
-
Finally, you can create the environment:
mkvirtualenv chip8
-
-
Clone (or download) the Chip 8 emulator project:
sudo apt install git git clone https://github.com/craigthomas/Chip8Python.git
-
Install the requirements from the project:
pip install -r requirements.txt
-
Download and install Python 3.6.8 for Windows. Make sure that
pip
andAdd python.exe to Path
options are checked when performing the installation. Later versions of Python 3 are also likely to work correctly with the emulator. -
(Optional) Install virtual environment support for Python. Run the following commands from a command prompt:
- Install the virtual environment wrapper:
pip install virtualenv pip install virtualenvwrapper-win
-
Create a new environment for the Chip 8 emulator:
mkvirtualenv chip8
-
Install Git for Windows.
-
Clone (or download) the source files from GitHub. Run the following commands in a command prompt window:
git clone https://github.com/craigthomas/Chip8Python.git
-
Install the requirements for the project. Run the following commands in a command prompt window in the directory where you cloned or downloaded the source files:
pip install -r requirements.txt
Note that if you created a virtual environment as detailed above,
you will need to workon
that environment before starting the emulator:
workon chip8
The command-line interface requires a single argument, which is the full path to a Chip 8 ROM. Run the following command in the directory where you cloned or downloaded the source files:
python yac8e.py /path/to/rom/filename
This will start the emulator with the specified ROM.
The --scale
switch will scale the size of the window (the original size at 1x
scale is 64 x 32):
python yac8e.py /path/to/rom/filename --scale 10
The command above will scale the window so that it is 10 times the normal size.
You may also wish to experiment with the --delay
switch, which instructs
the emulator to add a delay to every operation that is executed. For example,
python yac8e.py /path/to/rom/filename --delay 10
The command above will add a 10 ms delay to every opcode that is executed. 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).
Over time, various extensions to the Chip8 mnemonics were developed, which resulted in an interesting fragmentation of the Chip8 language specification. As discussed in Octo's Mastering SuperChip documentation, one version of the SuperChip instruction set subtly changed the meaning of a few instructions from their original Chip8 definitions. This change went mostly unnoticed for many implementations of the Chip8 langauge. Problems arose when people started writing programs using the updated language model - programs written for "pure" Chip8 ceased to function correctly on emulators making use of the altered specification.
To address this issue, Octo implements
a number of quirks modes so that all Chip8 software can run correctly,
regardless of which specification was used when developing the Chip8 program.
This same approach is used here, such that there are several quirks
flags
that can be passed to the emulator at startup to force it to run with
adjustments to the language specification.
Additional quirks and their impacts on the running Chip8 interpreter are examined in great depth at Chromatophore's HP48-Superchip repository. Many thanks for this detailed explanation of various quirks found in the wild!
The --shift_quirks
flag will change the way that register shift operations work.
In the original language specification two registers were required: the
destination register x
, and the source register y
. The source register y
value was shifted one bit left or right, and stored in x
. For example,
shift left was defined as:
Vx = Vy << 1
However, with the updated language specification, the source and destination
register are assumed to always be the same, thus the y
register is ignored and
instead the value is sourced from x
as such:
Vx = Vx << 1
The --index_quirks
flag controls whether post-increments are made to the index register
following various register based operaitons. For load (Fn65
) and store (Fn55
) register
operations, the original specification for the Chip8 language results in the index
register being post-incremented by the number of registers stored. With the Super
Chip8 specification, this behavior is not always adhered to. Setting --index_quirks
will prevent the post-increment of the index register from occurring after either of these
instructions.
The --jump_quirks
controls how jumps to various addresses are made with the jump (Bnnn
)
instruction. In the original Chip8 language specification, the jump is made by taking the
contents of register 0, and adding it to the encoded numeric value, such as:
PC = V0 + nnn
With the Super Chip8 specification, the highest 4 bits of the instruction encode the
register to use (Bxnn
) such. The behavior of --jump_quirks
becomes:
PC = Vx + nn
The --clip_quirks
controls whether sprites are allowed to wrap around the display.
By default, sprits will wrap around the borders of the screen. If turned on, then
sprites will not be allowed to wrap.
The --logic_quirks
controls whether the F register is cleared after logic operations
such as AND, OR, and XOR. By default, F is left undefined following these operations.
With the flag turned on, F will always be cleared.
The original specification of the Chip8 language defined a 4K memory size for the
interpreter. The addition of the XO Chip extensions require a 64K memory size
for the interpreter. By default, the interpreter will start with a 64K memory size,
but this behavior can be controlled with the --mem_size
flag. Valid options are
64K
or 4K
for historical purposes.
The original Chip8 language specification called for pixels to be turned on or
off. It did not specify what color the pixel states had to be. The emulator
lets the user specify what colors they want to use when the emulator is running.
Color values are specified by using HTML hex values such as AABBCC
without the
leading #
. There are currently 4 color values that can be set:
--color_0
specifies the background color. This defaults to000000
.--color_1
specifies bitplane 1 color. This defaults toFF33CC
.--color_2
specifies bitplane 2 color. This defaults to33CCFF
.--color_3
specifies bitplane 1 and 2 overlap color. This defaults toFFFFFF
.
For Chip8 and SuperChip 8 programs, only the background color color_0
(for pixels
turned off) and the bitplane 1 color color_1
(for pixels turned on) are used.
Only XO Chip programs will use color_2
and color_3
when the additional bitplanes
are potentially used.
The file chip8/config.py
contains several variables that can be changed to
customize the operation of the emulator. The Chip 8 has 16 keys:
The original Chip 8 had a keypad with the numbered keys 0 - 9 and A - F (16 keys in total). The original key configuration was as follows:
1 |
2 |
3 |
C |
---|---|---|---|
4 |
5 |
6 |
D |
7 |
8 |
9 |
E |
A |
0 |
B |
F |
The Chip8 emulator maps them to the following keyboard keys by default:
1 |
2 |
3 |
4 |
---|---|---|---|
Q |
W |
E |
R |
A |
S |
D |
F |
Z |
X |
C |
V |
If you wish to configure a different key-mapping, simply change the KEY_MAPPINGS
variable
in the configuration file to reflect the mapping that you want. The
pygame.key documentation contains a
list of all the valid constants for keyboard key values.
In addition to the key mappings specified in the configuration file, there are additional keys that impact the execution of the emulator.
Keyboard Key | Effect |
---|---|
ESC |
Quits the emulator |
Here are the list of public domain ROMs and their current status with the emulator, along with links to public domain repositories where applicable.
ROM Name | Working | Flags |
---|---|---|
1D Cellular Automata | ✔️ | |
8CE Attourny - Disc 1 | ✔️ | |
8CE Attourny - Disc 2 | ✔️ | |
8CE Attourny - Disc 3 | ✔️ | |
Bad Kaiju Ju | ✔️ | |
Br8kout | ✔️ | |
Carbon8 | ✔️ | |
Cave Explorer | ✔️ | |
Chipquarium | ✔️ | |
Danm8ku | ✔️ | |
down8 | ✔️ | |
Falling Ghosts | ✔️ | |
Flight Runner | ✔️ | |
Fuse | ✔️ | |
Ghost Escape | ✔️ | |
Glitch Ghost | ✔️ | |
Horse World Online | ✔️ | |
Invisible Man | ✔️ | clip_quirks |
Knumber Knower | ✔️ | |
Masquer8 | ✔️ | |
Mastermind | ✔️ | |
Mini Lights Out | ✔️ | |
Octo: a Chip 8 Story | ✔️ | |
Octogon Trail | ✔️ | |
Octojam 1 Title | ✔️ | |
Octojam 2 Title | ✔️ | |
Octojam 3 Title | ✔️ | |
Octojam 4 Title | ✔️ | |
Octojam 5 Title | ✔️ | |
Octojam 6 Title | ✔️ | |
Octojam 7 Title | ✔️ | |
Octojam 8 Title | ✔️ | |
Octojam 9 Title | ✔️ | |
Octojam 10 Title | ✔️ | |
Octo Rancher | ✔️ | |
Outlaw | ✔️ | |
Pet Dog | ✔️ | |
Piper | ✔️ | |
Pumpkin "Dress" Up | ✔️ | |
RPS | ✔️ | |
Slippery Slope | ✔️ | |
Snek | ✔️ | |
Space Jam | ✔️ | |
Spock Paper Scissors | ✔️ | |
Super Pong | ✔️ | |
Tank! | ✔️ | |
TOMB STON TIPP | ✔️ | |
WDL | ✔️ |
ROM Name | Working | Flags |
---|---|---|
Applejak | ✔️ | |
Bulb | ✔️ | |
Black Rainbow | ✔️ | |
Chipcross | ✔️ | |
Chipolarium | ✔️ | |
Collision Course | ✔️ | |
Dodge | ✔️ | |
DVN8 | ✔️ | |
Eaty the Alien | ✔️ | |
Grad School Simulator 2014 | ✔️ | |
Horsey Jump | ✔️ | |
Knight | ❌ | |
Mondri8 | ✔️ | |
Octopeg | ✔️ | |
Octovore | ✔️ | |
Rocto | ✔️ | |
Sens8tion | ✔️ | |
Snake | ✔️ | |
Squad | ✔️ | |
Sub-Terr8nia | ✔️ | |
Super Octogon | ✔️ | |
Super Square | ✔️ | |
The Binding of COSMAC | ✔️ | |
Turnover '77 | ✔️ |
ROM Name | Working | Flags |
---|---|---|
An Evening to Die For | ✔️ | |
Business Is Contagious | ✔️ | |
Chicken Scratch | ✔️ | |
Civiliz8n | ✔️ | |
Flutter By | ✔️ | |
Into The Garlicscape | ✔️ | |
jub8 Song 1 | ✔️ | |
jub8 Song 2 | ✔️ | |
Kesha Was Biird | ✔️ | |
Kesha Was Niinja | ✔️ | |
Octo paint | ✔️ | |
Octo Party Mix! | ✔️ | |
Octoma | ✔️ | |
Red October V | ✔️ | |
Skyward | ✔️ | |
Spock Paper Scissors | ✔️ | |
T8NKS | ✔️ | |
Tapeworm | ✔️ | |
Truck Simul8or | ✔️ | |
SK8 H8 1988 | ✔️ | |
Super NeatBoy | ✔️ | |
Wonky Pong | ✔️ |
The best documentation is in the code itself. Please feel free to examine the code and experiment with it.