JSNES
JSNES is a Nintendo Entertainment System emulator written entirely in JavaScript by Ben Firshman, running in-browser with an HTML5 canvas and Web Audio output. Its portable core has been reused in many web-based and Node.js NES projects.
Runs on: Web browser
JSNES Online Emulator
Play JSNES using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Nova the Squirrel | JSNES | Nintendo NES | open | Open ⛶ | |
| Nova the Squirrel | JSNES | Nintendo Famicom | open | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
JSNES is a pure-JavaScript library. Vendor jsnes.min.js and drive it from a short script that renders each frame to a <canvas>.
Boot and load a ROM. Construct the machine with an onFrame callback, then hand it the ROM as a binary string:
const nes = new jsnes.NES({
onFrame: fb => { /* fb = 256×240 Int32 pixels, 0x00BBGGRR */ },
onAudioSample: (l, r) => { /* push into a Web Audio buffer */ }
});
const buf = await (await fetch(romUrl)).arrayBuffer();
let bin = ''; new Uint8Array(buf).forEach(b => bin += String.fromCharCode(b));
nes.loadROM(bin); // loadROM wants a binary string
(function loop(){ nes.frame(); requestAnimationFrame(loop); })();
The NES object. Once constructed, nes exposes the whole machine as ordinary methods and properties, so a host page can do far more than render:
| Member | Kind | What it does |
|---|---|---|
loadROM(data) | method | Load a ROM from an iNES .nes binary string and set up its mapper. |
frame() | method | Emulate one video frame, steps the CPU, PPU and APU, then fires onFrame. |
reset() | method | Reset the machine, like the console's reset button. |
reloadROM() | method | Reload the currently-loaded ROM from scratch. |
buttonDown(pad, btn) | method | Press a button - pad is 1 or 2, btn is a jsnes.Controller.BUTTON_* (A, B, SELECT, START, UP, DOWN, LEFT, RIGHT). What an on-screen gamepad calls. |
buttonUp(pad, btn) | method | Release a button. |
zapperMove(x, y) | method | Move the Zapper light-gun to screen coordinates. |
zapperFireDown(), zapperFireUp() | method | Pull and release the Zapper trigger. |
getFPS() | method | The current emulation frame rate. |
setFramerate(rate) | method | Set the target frame rate (recomputes frame timing and audio). |
stop() | method | Stop the audio processing unit. |
toJSON() | method | Serialise the full machine state, a save state. |
fromJSON(state) | method | Restore machine state produced by toJSON(). |
cpu | field | The 6502 CPU; cpu.mem is the 64 KB address space, readable and pokeable live (game state, cheats, a debugger). |
ppu | field | The Picture Processing Unit, nametables, sprites and palettes. |
papu | field | The audio processing unit (APU). |
mmap | field | The active cartridge mapper, created by loadROM. |
controllers | field | State of the two gamepads ({1: […], 2: […]}). |
opts | field | Merged options: onFrame, onAudioSample, onStatusUpdate, onBatteryRamWrite, preferredFrameRate, emulateSound, sampleRate. |
romData | field | The raw ROM data currently loaded. |
frameTime | field | Milliseconds per frame, derived from preferredFrameRate. |
fpsFrameCount | field | Internal frame counter behind getFPS(). |
ui | field | Internal binding of the frame and status callbacks. |
Because it is all JavaScript, the machine is fully inspectable and controllable at runtime, straight from the host page.
Architecture
JSNES is a readable, interpreted NES emulator, a JavaScript descendant of the vNES emulator (originally Java). Each hardware block is its own object hanging off the top-level NES:
CPU- an interpreter of the Ricoh 2A03's 6502 core, with the 64 KB memory map atcpu.mem.PPU- the Picture Processing Unit: it draws the background and up to 64 sprites into a 256×240 32-bit framebuffer, delivered once per frame toonFrame.PAPU- the audio unit, synthesising the two pulse, triangle, noise and DPCM channels into samples foronAudioSample.Mappers- one class per cartridge mapper (NROM, MMC1, MMC3, …) implementing bank-switching; the iNES header selects which.ROM- parses the iNES header and holds the PRG and CHR banks.Controller- the two gamepads and their button latches.
Each nes.frame() runs the CPU for one video frame's worth of cycles while stepping the PPU and APU in lockstep, then emits the finished framebuffer. Because the components are ordinary objects, the whole emulator state is inspectable and serialisable, which is how the toJSON/fromJSON save states work.