NesCore
A NES Emulator made in JavaScript for educational purposes. Try it!
Its main objective is to reflect the NES internals as simply as possible by using clean, object-oriented code. It doesn't have any complex bitwise operations, huge switch-case statements or files with lots of magic numbers.
Created by [r]labs.
⚠️ This is not a cycle-accurate emulator and performance is not the main concern.
Features
- 👾 It emulates the NES
- 👨🔧 It plays Super Mario Bros. 3!
- 💻 CPU
- All official instructions are implemented
- nestest passes ✔️
- Fully functional 🖥️ PPU and 🔊 APU
- 🔌 Supported mappers
- 🐏 SRAM support
- 💾 Save states support
- 🌎 Web frontend with Gamepad support
Usage
npm install --save nes-emu
const onFrame = (frameBuffer) => {
};
const onSample = (sample) => {
};
const nes = new NES(onFrame, onSample);
nes.load(rom);
{
nes.setButton(1, "BUTTON_A", true);
nes.setButton(2, "BUTTON_DOWN", false);
nes.frame();
}
const saveState = nes.getSaveState();
nes.setSaveState(saveState);
👀 Have a look at the demo implementation for more details.
Full API
constructor | onFrame , onSample , logger | Creates an emulator's instance. All properties can be set at any time. |
load | rom , saveFileBytes | Loads a ROM. If a saveFileBytes array is provided, it sets the SRAM content. |
frame | | Runs the emulation for a whole video frame. |
samples | requestedSamples | Runs the emulation until the audio system generates requestedSamples . |
scanline | | Runs the emulation until the next scanline. |
setButton | player , button , isPressed | Sets the button state of player to isPressed . The button can be one of: ["BUTTON_A", "BUTTON_B", "BUTTON_SELECT", "BUTTON_START", "BUTTON_UP", "BUTTON_DOWN", "BUTTON_LEFT", "BUTTON_RIGHT"] |
clearButtons | player | Sets all buttons of player to a non-pressed state. |
getSaveFile | | Returns an array with the SRAM bytes, or null. |
getSaveState | | Returns an object with a snapshot of the current state. |
setSaveState | saveState | Restores a saveState . |
Screenshots

Debugging
You can inspect the emulator state by using the global window.debug
object.
Also, if you add ?debug
to the URL and use a gamepad, shoulder buttons will behave as follows:
2--4
1--3
1: Enter debug mode
2: Exit debug mode
3: Hold to run frame
4: Hold to run scanline
Useful links