Yet another CHIP8 emulator/interpreter. Written in C++ using SDL2 for graphics and input.
- Install Conan
- Install CMake
- Run
sh release.sh - Run
./build/bin/chip8passing the ROM file as argument- Example:
./build/bin/chip8 'roms/invaders.bin'
- Example:
Some games can present flickery graphics, this is due to the Graphic system on CHIP8 consistently XORing the video buffer + no synchronization support. To smooth out this effect the emulator provides double frame interpolation, which can be toggled by pressing SPACE.
Regular CHIP8 flickering vs Frame interpolated CHIP8
The emulator provides a disassembler, which can be accessed by passing --disassemble as argument. This will print the disassembled code to the console and exit.
You can #define LOG_VERBOSE for extra debug information.
Which includes all the opcodes, their arguments and an explanation of what they do in real time, performance impact is negligible.
+-----------------------+ | 0x0050 - 0x01FF | - Reserved memory (contains font set in emu) +-----------------------+ | 0x0200 - 0x1000 | - Program ROM and work RAM +-----------------------+
The CHIP-8 has a HEX based keypad (0x0-0xF), which maps to the following key-matrix:
╔═══╦═══╦═══╦═══╗ ╔═══╦═══╦═══╦═══╗ ║ 1 ║ 2 ║ 3 ║ C ║ ║ 1 ║ 2 ║ 3 ║ 4 ║ ╠═══╬═══╬═══╬═══╣ ╠═══╬═══╬═══╬═══╣ ║ 4 ║ 5 ║ 6 ║ D ║ ║ q ║ w ║ e ║ r ║ ╠═══╬═══╬═══╬═══╣ which translates to: ╠═══╬═══╬═══╬═══╣ ║ 7 ║ 8 ║ 9 ║ E ║ (in the keyboard) ║ a ║ s ║ d ║ f ║ ╠═══╬═══╬═══╬═══╣ ╠═══╬═══╬═══╬═══╣ ║ A ║ 0 ║ B ║ F ║ ║ z ║ x ║ c ║ v ║ ╚═══╩═══╩═══╩═══╝ ╚═══╩═══╩═══╩═══╝
This emulator uses SDL2 for audio. Generating a sine wave with a frequency of 440Hz for 1/60th of a second. This is the same frequency as the original CHIP-8.
| Instruction | Description |
|---|---|
| 0NNN | Not supported |
| 00E0 | Clear the screen |
| 00EE | Return from a subroutine |
| 1NNN | Jump to address NNN |
| 2NNN | Execute subroutine starting at address NNN |
| 3XNN | Skip the following instruction if the value of register VX equals NN |
| 4XNN | Skip the following instruction if the value of register VX is not equal to NN |
| 5XY0 | Skip the following instruction if the value of register VX is equal to the value of register VY |
| 6XNN | Store number NN in register VX |
| 7XNN | Add the value NN to register VX |
| 8XY0 | Store the value of register VY in register VX |
| 8XY1 | Set VX to VX OR VY |
| 8XY2 | Set VX to VX AND VY |
| 8XY3 | Set VX to VX XOR VY |
| 8XY4 | Add the value of register VY to register VX. Set VF to 01 if a carry occurs. Set VF to 00 if a carry does not occur |
| 8XY5 | Subtract the value of register VY from register VX. Set VF to 00 if a borrow occurs. Set VF to 01 if a borrow does not occur |
| 8XY6 | Store the value of register VY shifted right one bit in register VX¹. Set register VF to the least significant bit prior to the shift. VY is unchanged |
| 8XY7 | Set register VX to the value of VY minus VX. Set VF to 00 if a borrow occurs. Set VF to 01 if a borrow does not occur |
| 8XYE | Store the value of register VY shifted left one bit in register VX¹. Set register VF to the most significant bit prior to the shift. VY is unchanged |
| 9XY0 | Skip the following instruction if the value of register VX is not equal to the value of register VY |
| ANNN | Store memory address NNN in register I |
| BNNN | Jump to address NNN + V0 |
| CXNN | Set VX to a random number with a mask of NN |
| DXYN | Draw a sprite at position VX, VY with N bytes of sprite data starting at the address stored in I. Set VF to 01 if any set pixels are changed to unset, and 00 otherwise |
| EX9E | Skip the following instruction if the key corresponding to the hex value currently stored in register VX is pressed |
| EXA1 | Skip the following instruction if the key corresponding to the hex value currently stored in register VX is not pressed |
| FX07 | Store the current value of the delay timer in register VX |
| FX0A | Wait for a keypress and store the result in register VX |
| FX15 | Set the delay timer to the value of register VX |
| FX18 | Set the sound timer to the value of register VX |
| FX1E | Add the value stored in register VX to register I |
| FX29 | Set I to the memory address of the sprite data corresponding to the hexadecimal digit stored in register VX |
| FX33 | Store the binary-coded decimal equivalent of the value stored in register VX at addresses I, I + 1, and I + 2 |
| FX55 | Store the values of registers V0 to VX inclusive in memory starting at address I. I is set to I + X + 1 after operation |
| FX65 | Fill registers V0 to VX inclusive with the values stored in memory starting at address I. I is set to I + X + 1 after operation |
For when I have spare time:
- Disassembler
- Create a Graphical User Interface using Dear ImGui
- Load ROM files within the GUI
- Implement a register view within the GUI
- Implement a stack view within the GUI
- Implement a dissasembler view within the GUI
- Implement a memory view within the GUI
- Implement a keypad view within the GUI
- Implement a screen view within the GUI
- Implement a debug view within the GUI
- Implement a settings view within the GUI
- Define a CLOCK hz
- Define a Frame Rate hz
- Define the screen size
- Define the screen scale
- Define the screen color
- Define the audio frequency
| Name | Description |
|---|---|
| Corax89's - CHIP8 Test room | Used for testing |
| Zophar's domain - CHIP8 Game room pack | Used for rooms |
| Austin Morlan's - CHIP8 Article | Used as reference |
| Matt Mikolay's - CHIP8 Reference | Used as reference |
| Wikipedia - CHIP8 Page | Used as reference |
| faizilham's - CHIP8 Article | Inspiration for the Frame interpolation feature |
| fluentcpp.com - Warning article | Used to disable useless warnings due to macro conditions |






