A cycle-accurate Nintendo Entertainment System (NES) emulator built with Rust and SDL2. This project aims to create a fully functional emulator capable of playing classic NES games, with a strong focus on clean code, accurate emulation, and detailed documentation.
- Full 6502 Instruction Set: Implements all official opcodes.
- Undocumented Opcodes: Includes support for most common illegal/undocumented opcodes used in many games.
- Accurate Addressing Modes: All 13 addressing modes are precisely implemented.
- Cycle-Accurate Emulation: Handles additional cycles for page-crossing branches and memory accesses.
- Interrupts: Correctly handles NMI (Non-Maskable Interrupts) from the PPU and IRQ (Interrupt Requests) from the APU and mappers.
- Frame Rendering: Renders a full 256x240 frame.
- Sprite and Background Rendering: Supports up to 64 sprites per frame, with priority handling (behind/in front of background).
- Sprite 0 Hit Detection: Correctly detects collisions between sprite 0 and the background, a crucial timing mechanism for many games.
- VRAM and OAM: Full emulation of Video RAM, Object Attribute Memory (sprite data), and palette memory.
- Scrolling: Manages Name Table, Attribute Table, and fine/coarse scroll registers.
- Mirroring: Supports Horizontal, Vertical, and Four-Screen mirroring via the iNES mapper implementation.
- 5-Channel Audio Synthesis:
- 2 Pulse Wave channels (square waves).
- 1 Triangle Wave channel.
- 1 Noise channel.
- 1 Delta Modulation Channel (DMC) for playing DPCM samples.
- Envelopes and Sweeps: Volume envelopes and frequency sweeps are implemented for the pulse channels.
- Length Counters: All channels support length counters for note duration.
- Audio Sampling: Generates and outputs audio samples, which are played back via SDL2.
- iNES Format: Loads games from the standard
.nes
file format. - Mapper 0 (NROM): Fully supported, allowing a large number of early NES titles to be played.
- Memory Mapping: Correctly maps all system components (RAM, PPU, APU, Cartridge) into the CPU's address space.
- DMA Transfers: Emulates OAM DMA for fast sprite memory transfers.
- Joypad Support: Full support for one controller.
- Keyboard Mapping: Maps keyboard keys to the NES joypad for gameplay.
This project uses SDL2 for windowing, rendering, and audio. You need to install it on your system.
macOS (using Homebrew):
brew install sdl2
Ubuntu/Debian:
sudo apt-get install libsdl2-dev
Windows:
- Download the SDL2 development libraries for MinGW from the SDL2 release page (e.g.,
SDL2-devel-2.xx.x-mingw.tar.gz
). - Unzip the archive.
- Copy the contents of the
x86_64-w64-mingw32
directory into your MinGW-w64 toolchain directory. You may need to set theSDL2_PATH
environment variable to the SDL2 folder.
Once dependencies are installed, you can build and run the emulator using Cargo.
# Clone the repository
git clone https://github.com/atomkernel0/nes_emulator.git
cd nes_emulator
# Build the project
cargo build --release
# Run the emulator with a game ROM
# (You must provide your own legally-owned ROM file)
cargo run --release -- path/to/your/game.nes
The keyboard is mapped to the NES controller as follows:
NES Button | Keyboard Key |
---|---|
D-Pad | Arrow Keys |
A | A |
B | S |
Start | Enter / Return |
Select | Space |
ESC
: Quit the emulator.R
: Reset the emulator.
src/
├── main.rs # Entry point, main game loop, SDL2 initialization
├── cpu.rs # 6502 CPU emulation and instruction implementation
├── bus.rs # System bus, connects all components (CPU, PPU, APU)
├── apu.rs # Audio Processing Unit (all 5 sound channels)
├── ppu/ # Picture Processing Unit
│ ├── mod.rs # Main PPU logic, registers, and timing
│ └── registers/ # PPU register-specific logic (control, mask, etc.)
├── render/ # Rendering helpers
│ ├── frame.rs # Represents a single rendered frame
│ └── palette.rs # NES color palette
├── cartridge.rs # Cartridge loading and mapper implementation
├── joypad.rs # Controller input handling
└── opcodes.rs # 6502 opcode definitions and lookup table
While the emulator is quite capable, there are still many features to add for broader compatibility and a better user experience.
- PPU Upgrade: PPU is not well implemented.
- More Mappers: Implement common mappers like MMC1, MMC3, UxROM to support more games.
- Save States: Implement functionality to save and load the emulator's state.
- Debugger: Create a debugging interface to inspect CPU registers, memory, and PPU state.
- UI Improvements: Add a simple GUI for loading ROMs and configuring settings.
- Performance Optimizations: Profile and optimize the code for better performance.
- NESdev Wiki: The ultimate resource for NES development and emulation.
- 6502 Instruction Set: A comprehensive guide to the 6502 CPU.
- One Lone Coder's NES Emulator Series: A fantastic video series that served as an inspiration.
- Writing NES Emulator in Rust: A fantastic tutorial that served as the base for the actual codebase.
This project is licensed under the GPLv3. See the LICENSE
file for more details.
*Disclaimer: This project is for educational purposes only. You are responsible for obtaining game ROMs legally.*