-
Notifications
You must be signed in to change notification settings - Fork 23
Home
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.
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.
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.
The installation under Ubuntu 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-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
-
Install Mercurial. The
hg
command-line tool is required when usingpip
(see next step) to install the requirements for the project. To install Mercurial from the command-line:sudo apt-get install mercurial
-
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
-
Alternatively,
pip
may be distributed by Ubuntu's package manager. You can try:sudo apt-get install pip
-
Clone (or download) the Chip 8 emulator project:
sudo apt-get install git git clone [email protected]:craigthomas/Chip8Python.git
-
Install the requirements from the project:
pip install -r requirements.txt
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.
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
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).
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.
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 addressnnn
-
2nnn
- Call routine at addressnnn
-
3snn
- Skip next instruction if registers
value equalsnn
-
4snn
- Do not skip next instruction if registers
value equalsnn
-
5st0
- Skip if registers
value equals registert
value -
6snn
- Load registers
with valuenn
-
7snn
- Add valuenn
to registers
-
8st0
- Move value from registers
to registert
-
8st1
- Perform logical OR on registers
andt
and store int
-
8st2
- Perform logical AND on registers
andt
and store int
-
8st3
- Perform logical XOR on registers
andt
and store int
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