Yet another NES emulator written in C++23.
The initial plan was to get it going within one day which I did successfully. This is my second attempt writing a NES emulator (the first one was years ago in Lua and source code is kind of lost in time). The goal was to create a working emulator in one day or less which I somewhat completed: the third commit that was made within one day was actually able to run 2048.nes. This project was created just to have some fun and to have a handy lightweight tool with extensive control over 6502's execution flow with pretty basic programmer-friendly debugging interfaces.
Warning
The PPU is currently suffering around the same issues as my first emulator did because I still have to read a lot of those documentations on it to actually fix the thing. Also the APU is implemented but it is kind of inaccurate which could cause numerous issues in synchronization and applications execution in general. There's still a lot of lingering bugs yet the emulator still manages to run some games like SMB, Darkwing Duck, The Legend of Zelda, Duck Hunt and most likely way more than that. Additionally my CPU completely passes NEStest and 6502 timings tests, the emulator still struggless with 100thcoin's accuracy test but it passes 80/143 tests so far at the moment of me writing this warning.
Note
Note that "Implemented" doesn't mean "works completely flawlessly in all scenarios", a lot of games might straight up break because of missing or incorrectly implemented functionality inside those mappers.
- NROM
- MMC1
- MMC2
- MMC3
- MMC4
- MMC5
- CNROM
- UNROM
Currently any attempt to run other mappers will result in exception.
Just compile and run the executable with the *.nes file passed as argument.
It is possible to pipe your NES files aswell. You just need to specify - instead of a file path and the emulator will wait for a bytestream into the stdin. Ultimately this allows you to run any NES file from a web-server of some sort or through netcat for example. Here's little usage tutorial:
curl -L http://127.0.0.1:8486/path/to/a/totally/legal/storage/of/manually/dumped/roms/smb.nes | ./peNES -Note
Note that this approach DOES NOT support archived files! The incoming bytestream supposed to start with the NES\x1A magic!
If you want to to run a compressed rom, you have to pipe it through the decompression utility first.
--volume [0...1]- Set the master volume for the emulator, defaults to0.3--skipvalid- Skip NES dump validation and try to run it anyways, the game might run into even more issues than usual if it's fails the validation
Currently the emulator supports only Unix-like systems, it was tested on Arch Linux only so far.
On gamepad you can use DPAD to navigate, A/B buttons to make actions, Y to cause CPU to reset, Select/Start to pick options. LB/RB to save/restore current enulation state.
Keyboard bindings:
- G - Open debugger menu
- Escape - Reset CPU
- Arrows - Navigate
- Z/X - Action buttons
- Space/Enter - Select/Start options buttons
- S/R - Save/Restore current emulation state
- F1 - Set heatmap printing threshold to 1
- F2 - Set heatmap printing threshold to 10
- F3 - Set heatmap printing threshold to 100
Note
All of them will be downloaded automatically through CMake's FetchContent module.
- SDL3
- magic_enum
- ImGui
- imgui_hex_editor
- microprofile (optional, will be download only if CMake flag specified)
AI was used extensively to consult about NES' PPU and mappers architecture and summarize documentations. All the main architectural decisions, algorithms were made by me.