A Nintendo Entertainment System (NES) emulator implementation in C++ that aims to provide cycle accurate emulation of the original NTSC NES hardware. Implemented and tested on MacOS, but should probably work on Windows and Linux as well.
zelda.mp4
More videos
battletoads.mp4
debug.mp4
zelda2.mp4
mario.mp4
iceclimber.mp4
CPU
- All 256 opcodes implemented and cycle accurate
- BRK, IRQ and NMI implemented with vector hijacking
PPU
- Accurate pixel rendering
- Accurate sprite0 hit detection
- Scrolling via loopy registers
APU
- Pulse channels implemented
- Triangle channel implemented
- Noise channel implemented
- DMC channel mostly implemented
iNES Mappers
- 000 - NROM
- 001 - MMC1B
- 002 - UxROM
- 007 - AxROM
- 094 - UN1ROM
- 180 - Configured UNROM
CPU OPs are all verified against the good ol' JSON SingleStepTest https://github.com/SingleStepTests/65x02/tree/main/nes6502. All tests pass and are cycle accurate.
Test roms (https://github.com/christopherpow/nes-test-roms) passing:
-
CPU / Memory
- nes_test - 23 / 23
- branch_timing_tests - 3 / 3
- blargg_nes_cpu_test5 - official - 11 / 11
- blargg_nes_cpu_test5 - nes - 10 / 11
- cpu_exec_space - 1 / 2
- cpu_interrupts_v2 - 3 / 5
- cpu_timing_test6 - 3 / 3
- instr_misc - 2 / 4
- instr_test-v5 - 15 / 16
- instr_timing - 2 / 2
- nes_instr_test - 10 / 11
- oam_read - 1 / 1
- oam_stress - 0 / 1
-
PPU
- ppu_vbl_nmi - 10 / 10
- vbl_nmi_timing - 7 / 7
- scanline - 1 / 1
- sprite_hit_tests_2005.10.05 - 11 / 11
- sprite_overflow_tests - 0 / 5
-
APU
- apu_test - 7 / 8
- blargg_apu_2005.07.30 - 10 / 11
- dmc_tests - 4 / 4
Note: Sometimes the full test fails but all the singles succeed.
I have not implemented any type of save state yet. Neither have I implemented any kind of RESET functionality. Sprite overflow is not implemented yet. The DMA timing on APU DMC access is not really implemented. On Battletoads, text and logos on the title screen is a little weird, and audio seems a little off when playing the game.
After compiling, the binary will end up in the bin/
directory.
$ nesscape <rom_path> <flag>
Flags:
no flag (regular execution)
-d | --debug (debug execution)
-h | --help (print this help)
-v | --validate (validation execution)
-v <validation_log_path> (validate against provided log file)
-j <path to json test> (validate CPU against JSON test)
- Clone the repository and initialize submodules
git clone https://github.com/babaganosch/nes_emulator.git
cd nes_emulator
git submodule update --recursive --init
- Run the setup script to download and configure build tools, a new shell will be opened with the correct environment variables
./setup.sh
- Generate build files:
./generate.sh
- Build the project:
cd build
make
src/
- Source code filesinclude/
- Header filesthirdparty/
- Third-party dependencies (git submodules)tools/
- Build tools (GENie and Ninja)data/
- Some old nestest validation logsbuild/
- Generated build filesbin/
- Output directory for compiled binary
MiniAudio - Single source audio playback and capture library for C and C++.
MiniFB - Small cross platform library that makes it easy to render pixels in a window.
RapidJSON - A fast JSON parser/generator for C++ with both SAX/DOM style API. (Used only for parsing JSON tests for validation)
NesTestRoms - A collection of test roms used for functionality validation.
MacOS
The downloaded binaries for GENie and Ninja are probably compiled for Apple Silicon. If you're compiling on intel based mac, you probably need to download or compile tools manually.
Windows
I've only tested the emulator briefly on windows, but it seems to work fine if compiled with gcc.
Linux
Just like windows, I've only tested the emulator very briefly on Ubuntu. Here's some small details I've noticed..
- The audio thread does not sync very well and starts lagging behind, producing a disturbing noise.
- If genie complains about being built with a newer GLIBC version, rebuild it locally from source: https://github.com/bkaradzic/GENie/tree/master
- Missing X11 or XKB libraries will cause build failures - install the required development packages
# Install X11 and XKB development libraries
sudo apt-get install libx11-dev libxkbcommon-dev