Skip to content

Moondip-Konwar/chip-8-emulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CHIP-8 Interpreter

A functional CHIP-8 interpreter written in Rust. This project emulates the hardware specifications of the 1970s CHIP-8 virtual machine, allowing it to run classic games like Pong, Tetris, and Blitz.


Technical Specifications

The interpreter implements the following virtual hardware components:

  • Memory: 4096 bytes (4KB) of RAM.
  • Registers: 16 general-purpose 8-bit registers ($V0$ to $VF$). $VF$ is also used as a flag for carry, borrows, and collision detection.
  • Index Register ($I$): A 16-bit register used for memory addresses.
  • Program Counter ($PC$): A 16-bit register pointing to the current instruction.
  • Display: A $64 \times 32$ monochrome display (2048 pixels total).
  • Timers: Two 8-bit timers (Delay and Sound) that decrement at 60Hz.
  • Stack: Used to store return addresses when calling subroutines.
  • Input: A 16-key hexadecimal keypad ($0$ through $F$).

Instruction Set

The CHIP-8 uses 35 opcodes, each 2 bytes long. In the table below:

  • NNN: Address (12 bits)
  • NN: 8-bit constant
  • X, Y: 4-bit register identifiers
Opcode Description
00E0 Clears the display.
00EE Returns from a subroutine.
1NNN Jumps to address NNN.
2NNN Calls subroutine at NNN.
3XNN Skips next instruction if VX == NN.
4XNN Skips next instruction if VX != NN.
5XY0 Skips next instruction if VX == VY.
6XNN Sets VX to NN.
7XNN Adds NN to VX (Carry flag unchanged).
8XY0 Sets VX to the value of VY.
8XY1 Bitwise OR (`VX
8XY2 Bitwise AND (VX &= VY). Resets VF to 0.
8XY3 Bitwise XOR (VX ^= VY). Resets VF to 0.
8XY4 Adds VY to VX. VF is set to 1 if there is a carry.
8XY5 Subtracts VY from VX. VF is set to 0 if there is a borrow.
8XY6 Stores LSB of VX in VF then shifts VX right by 1.
8XY7 Sets VX to VY - VX. VF is set to 0 if there is a borrow.
8XYE Stores MSB of VX in VF then shifts VX left by 1.
9XY0 Skips next instruction if VX != VY.
ANNN Sets I to address NNN.
BNNN Jumps to address NNN + V0.
CXNN Sets VX to result of rand() & NN.
DXYN Draws a sprite at (VX, VY) with width 8 and height N.
EX9E Skips next instruction if key in VX is pressed.
EXA1 Skips next instruction if key in VX is not pressed.
FX07 Sets VX to the value of the delay timer.
FX0A Awaits a key press and stores the result in VX.
FX15 Sets the delay timer to VX.
FX18 Sets the sound timer to VX.
FX1E Adds VX to I.
FX29 Sets I to the location of the sprite for character in VX.
FX33 Stores the BCD representation of VX in memory at I, I+1, I+2.
FX55 Stores registers V0 through VX in memory starting at I.
FX65 Fills registers V0 through VX from memory starting at I.

How to Run

Prerequisites

  • Rust compiler and Cargo.
  • Dependencies for Macroquad (system libraries for graphics).

Execution

To run a specific ROM, pass the path as an argument:

cargo run -- path/to/rom

By default, if no path is provided, the interpreter attempts to load a test opcode ROM.


Input Mapping

The original CHIP-8 used a 4x4 keypad. This interpreter maps the keys to a standard QWERTY keyboard as follows:

Keyboard CHIP-8
1 2 3 4 1 2 3 C
Q W E R 4 5 6 D
A S D F 7 8 9 E
Z X C V A 0 B F

Sources

About

A CHIP-8 emulator written in Rust.

Topics

Resources

Stars

Watchers

Forks

Contributors

Languages