Skip to content

c-blanding/Chip8Emulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CHIP-8 Emulator

A CHIP-8 interpreter written in C++20 with SDL2 rendering. Supports the full standard CHIP-8 instruction set and runs classic ROMs including Pong, Breakout, Tetris, and more.


What is CHIP-8?

CHIP-8 is an interpreted programming language developed in the mid-1970s by Joseph Weisbecker for the COSMAC VIP microcomputer. It was designed to make game development easier on early home computers. CHIP-8 programs run on a virtual machine with:

  • 4096 bytes of memory
  • 16 8-bit general purpose registers (V0–VF)
  • A 16-bit index register (I)
  • A program counter starting at address 0x200
  • A 16-level call stack
  • Two timers (delay and sound) that count down at 60Hz
  • A 64×32 monochrome display
  • A 16-key hexadecimal keypad

Features

  • Full CHIP-8 instruction set (35 opcodes)
  • 60Hz timer emulation
  • Keyboard input with standard CHIP-8 key mapping
  • Scalable display via SDL2
  • Generic renderer that is not tied to CHIP-8 specifically — reusable for other emulators
  • Sprite clipping at screen edges

Requirements

  • C++20 compiler
  • CMake 3.20+
  • SDL2 (via vcpkg)
  • vcpkg with x64-mingw-dynamic triplet (for MinGW/CLion on Windows)

Building

1. Install vcpkg

git clone https://github.com/microsoft/vcpkg C:/vcpkg
cd C:/vcpkg
bootstrap-vcpkg.bat
vcpkg install sdl2:x64-mingw-dynamic

2. Clone the repository

git clone https://github.com/yourusername/Chip8Emulator
cd Chip8Emulator

3. Configure CMake

In CLion go to Settings → Build, Execution, Deployment → CMake and set CMake options to:

-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-mingw-dynamic

4. Build

Open the project in CLion and hit Run, or from the command line:

cmake -B build
cmake --build build

5. Copy SDL2.dll

Copy C:/vcpkg/installed/x64-mingw-dynamic/bin/SDL2.dll into the same folder as Chip8Emulator.exe so it runs standalone.


Running a ROM

Place your .ch8 ROM file in a roms/ folder next to the executable, then update main.cpp:

chip8.loadROM("./roms/YourROM.ch8");

Rebuild and run. ROMs are not included in this repository — you can find public domain CHIP-8 ROMs at various emulation archives online.


Key Mapping

CHIP-8 uses a 16-key hexadecimal keypad. This emulator maps it to the following keyboard layout:

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

Press Escape to quit.


Project Structure

Chip8Emulator/
├── Chip8.h          # CHIP-8 class declaration
├── Chip8.cpp        # CHIP-8 interpreter implementation
├── renderer.h       # Generic SDL2 renderer declaration
├── renderer.cpp     # SDL2 renderer implementation
├── main.cpp         # Main loop, input handling, timing
├── CMakeLists.txt   # Build configuration
└── roms/            # Place your .ch8 ROM files here

Architecture

Chip8 Class

The core interpreter. Responsible for:

  • Loading ROMs into memory at address 0x200
  • Fetching, decoding, and executing opcodes each cycle
  • Managing all registers, stack, timers, and display state
  • Exposing the display buffer and draw flag to the renderer
  • Accepting keypad state updates from the input system

Renderer Class

A generic SDL2 renderer that knows nothing about CHIP-8 specifically. It accepts any pixel buffer with a given width, height, and scale factor. Each logical pixel is drawn as a scaled rectangle, making it reusable for other emulator projects.

Main Loop

The main loop runs at ~60fps with approximately 10 CPU cycles per frame (~600Hz effective clock speed). Timers are decremented every 16ms independently of the CPU cycle rate, matching the CHIP-8 spec of 60Hz timer updates.


Implemented Opcodes

Opcode Description
00E0 Clear display
00EE Return from subroutine
1NNN Jump to address NNN
2NNN Call subroutine at NNN
3XNN Skip if VX == NN
4XNN Skip if VX != NN
5XY0 Skip if VX == VY
6XNN Set VX = NN
7XNN Set VX = VX + NN
8XY0 Set VX = VY
8XY1 Set VX = VX OR VY
8XY2 Set VX = VX AND VY
8XY3 Set VX = VX XOR VY
8XY4 Set VX = VX + VY, VF = carry
8XY5 Set VX = VX - VY, VF = no borrow
8XY6 Shift VX right by 1, VF = shifted bit
8XY7 Set VX = VY - VX, VF = no borrow
8XYE Shift VX left by 1, VF = shifted bit
9XY0 Skip if VX != VY
ANNN Set I = NNN
BNNN Jump to NNN + V0
CXNN Set VX = random AND NN
DXYN Draw N-byte sprite at (VX, VY), VF = collision
EX9E Skip if key VX is pressed
EXA1 Skip if key VX is not pressed
FX07 Set VX = delay timer
FX0A Wait for key press, store in VX
FX15 Set delay timer = VX
FX18 Set sound timer = VX
FX1E Set I = I + VX
FX29 Set I = font sprite address for digit VX
FX33 Store BCD of VX at I, I+1, I+2
FX55 Store V0–VX in memory starting at I
FX65 Load V0–VX from memory starting at I

Known Limitations

  • Sound timer is tracked but no audio is produced (no SDL audio implementation)
  • CHIP-8 has two conventions for shift opcodes (8XY6/8XYE) — this emulator uses VX directly rather than copying VY first, which is the more common modern interpretation
  • Some ROMs may behave unexpectedly depending on which CHIP-8 quirks they were written for

License

MIT License. Feel free to use, modify, and distribute.

About

Created a chip-8 emulator in c++

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages