cNES is the result of me wanting to get more experience with C and to work on some sort of computer architecture project. I settled on the NES due to the extensive documentation, especially that of the CPU and the meduim article by fogleman. There is already a plethora of NES projects online, so I wanted to make this project mine. I didn’t want to abandon the project or copy code, like many other NES emulators hosted online. It’s been a challenge so far, the result is an emulator that isn’t perfect but one that I’m proud of!
cNES supports multiple OSes via CMake or can be built using Make on Linux. I primarily develop on Linux however cNES can be ported over to other platforms via CMake.
Prerequisites:
- CMake (or Make for older builds) (with CMake SDL and libcheck can be downloaded and built from source if not present on your machine)
- gcc or clang compilers (or any compiler supported by CMake)
- gcc versions >= 4.8 or clang versions >= 3.1 are required to use the address sanitizer compile option (ASan)
- libcheck (currently unit tests are always run when compiling cNES)
- SDL2
With the prerequisites satisfied, it is as simple as:
# New cmake preset builds (see CMakePresets.json) $ cmake --preset release $ cmake --build --preset release # OLD MAKE BUILDS # Build cnes $ make # Build cnes (option 2) $ make all # Build cnes and clean previous build $ make clean all # For developers: # Build cnes debug version, contains debug symbols (useful for GDB) $ make DEBUG=1 # Build cnes with ASan enabled $ make DEBUG=1 ASAN=1 # Build cnes using a specific compiler (gcc by default) $ make CC=gcc # Build cnes using a specific compiler (clang) $ make CC=clang # Can also enable debug and ASan options with a compiler option too $ make CC=clang DEBUG=1 ASAN=1
For CMake: the compiled binary will end up in ./build/<PRESET_NAME>
For Make: the compiled binary will either end up in ./build/release/bin/
or ./build/debug/bin/
# Most common use case, opening a nes game/file with the correct build path $ ./build/release/bin/cnes -o FILE # Simplifying the path to the cnes binary, future examples will use this shortened notation (real path is likely above) $ ./cnes -o FILE # cnes usage, listing all the command-line options available to cnes $ ./cnes -h USAGE: cnes [options] OPTIONS: -h Shows all the possible command-line options -l Enable logging to a file -s Suppress logging to file or terminal -o FILE Open the provided file -c CYCLES Run the CPU up to the specified number of cycles -u UI_SCALE_FACTOR Scaling factor (integer) to be applied to the displayed output
Controls:
Player 1
Keyboard | NES |
---|---|
M | A |
N | B |
Q | Select |
E | Start |
W | Up |
S | Down |
A | Left |
D | Right |
Supported mappers
- NROM (mapper 0)
- MMC1 (mapper 1)
Test ROMS
Here is a place to find a source of legal (test) ROMS: https://wiki.nesdev.com/w/index.php/Emulator_tests
- No controller support for player 2
- No audio
- Only supports the NTSC region so far (no PAL)
- Limited mapper support, see above
cNES is zlib licensed, as found in the LICENSE file.
https://github.com/mwpenny/pureNES
http://www.dustmop.io/blog/2015/04/28/nes-graphics-part-1/
https://opcode-defined.quora.com/
http://www.fceux.com/web/help/fceux.html?PPU.html
https://www.dwheeler.com/6502/oneelkruns/asm1step.html
https://github.com/paramsingh/gameboi
At a certain point I understood how the NES PPU worked but I was unable to put this thinking into code (in terms of how to use SDL2 to display the PPU output). This project massively helped me because it served as a readable reference on how to add SDL2 into my project.
https://github.com/mwillsey/NES
Again, this project was crucial in generating my first iteration of my PPU rendering. I understood how the background was rendered. For an easy first attempt at rendering I tried to implement the drawing of a fixed nametable (no scrolling) i.e. starting from $2000, like what the title screen of Donkey Kong does. An important landmark for cNES as this guided me in generating my first visual output.
https://github.com/SourMesen/Mesen
I wouldn’t of made so much progress on my PPU and CPU without the amazing debugging qualities of Mesen. It is a great emulator! Several times I’ve consulted their source code to better my understanding of how to successfully emulate the NES.