Skip to content
dimiro1Public

About

A cycle accurate NES emulator written in Java.

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

MyNES

MyNES is a NES emulator written in Java. It runs on macOS, Windows, and Linux. It includes save states, rewind, video filters, and a debugger with source code, memory, and hardware views.

Super Mario Bros. 3 running in MyNES

Download

Download the latest archive from Releases and unpack it. Java 25 is required; builds are available from Adoptium.

Run ./mynes on macOS or Linux, or mynes.bat on Windows. You can also run java -jar mynes.jar from the unpacked directory.

Open a .nes file or a .zip through File > Open…. Drag and drop also works. ROMs are not included.

Once the repository's Pages source is set to GitHub Actions, the browser edition will be at dimiro1.github.io/mynes. Its static mynes-web-<version>.zip is also attached to each release for self-hosting; using it requires a browser, not Java.

Playing

MyNES supports NTSC and PAL, iNES and NES 2.0, and twelve mapper families. If a game runs at the wrong speed, change the region under Machine > Region.

There are nine save state slots per game. F5 saves and F7 loads the current slot. Hold Backspace to rewind up to 30 seconds by default, including sound. Fast forward and movie recording are also available. Battery saves use standard .sav files.

Video options include twelve palettes, NTSC and CRT filters, overscan, and TV aspect ratio. You can mute each of the five audio channels. Optional hacks remove the sprite limit or reduce slowdown. IPS patches and Game Genie codes do not change the ROM file.

Keys

Action Default key
D-pad Arrow keys
A / B X / Z
Start / Select Enter / Shift
Quick save / load F5 / F7
Rewind Hold Backspace
Full screen F11; Esc to leave
Save / copy screenshot F12 / Cmd or Ctrl+F12
Volume up / down Cmd or Ctrl+= / Cmd or Ctrl+-
Control Panel Cmd or Ctrl+D

Keys for both players can be changed under Settings > Controller…. Player two has no default keys. Gamepads and the Zapper are not supported yet.

Choose Settings > Appearance > Light or Dark to change the window theme. The choice takes effect immediately and is remembered for the next run.

Debugging

Open Debug > Control Panel or press Cmd/Ctrl+D. The Debugger tab has source code or disassembly in the center. The tree on the left has CPU, PPU, APU, input, stack, and RAM values. Memory and breakpoints are below the code.

Control Panel with the debugger stopped at a breakpoint

You can set conditional breakpoints and read or write watchpoints. The toolbar has Run, Break, Step Into, Step Over, and Step Frame. Register and memory values changed since the previous stop are highlighted.

PPU values, a conditional breakpoint, and a write watchpoint

For ca65/ld65 projects, attach the build's .dbg file in the Source tab. The debugger follows the current source line, shows symbols, and allows breakpoints in the source margin. These breakpoints keep their location when the cartridge switches PRG banks. Build with ca65 -g and ld65 --dbgfile game.dbg to generate the file.

After rebuilding, choose File > Reload ROM and Symbols. MyNES reads the ROM and attached .dbg file again, keeps CPU breakpoints and watches, and moves source breakpoints to their new PRG offsets by source file and line. A failed ROM load leaves the running machine alone.

Enter a decimal Line (0–261 for NTSC, 0–311 for PAL) and Dot (0–340), then choose Run to Raster. The debugger stops at the first CPU instruction boundary after the beam reaches that position; if it has already passed, it stops in the next frame. The Watches tab accepts RAM symbols or hex addresses; append :16 for a little-endian word. While stopped, edit a watch value or select a RAM byte in Memory and choose Write....

The Profile tab counts executed PRG instructions and CPU run cycles by source line, and reports source-line coverage when a .dbg file is attached. Start profiling only for the passage you want to measure, then Stop or Refresh to inspect it. Hotspots shows the flat totals; double-click a location to open its source line or raw PRG bytes.

Flame Graph shows how cycles are distributed across JSR calls and interrupt handlers. Balance widths uses square-root scaling to make small paths easier to see; uncheck it for widths proportional to run cycles. Hover for exact counts and click or double-click a frame to zoom. Once the final frame is zoomed in and has no children, double-click it to open its source line or PRG bytes. Back returns to the previous zoom; right-click or Reset Zoom returns to the full profile. Choose Maximize to open the graph in a large window, then Restore to return it to the debugger; the current zoom and profile remain in place. Procedure names come from ca65/ld65 scope records when available; otherwise frames show source locations or PRG offsets. The graph follows JSR/RTS and BRK/RTI, so code that changes the return stack or enters a routine through JMP may not form a precise call tree.

Source view and RAM variables from a dino-god build

The other Control Panel tabs show:

Tab Information
Nametables, Sprites, Palette, Tiles PPU graphics data and on-screen use
Sound Notes, levels, and waveforms for all five channels
Cartridge Active PRG/CHR banks and mapper state
Pads Held buttons and controller reads
Usage CPU time used in recent frames
Events Register writes and interrupts by scanline and dot

In Tiles, choose the PPU pattern table at $0000 or $1000 to inspect the CHR data currently mapped there. The header shows its physical 1 KB CHR banks. Select a tile with the mouse or arrow keys to see its PPU address, CHR offset, pattern bytes, pixel colours, and current uses. Show in Nametables outlines matching background cells; Show in Sprites selects matching OAM entries. The 8×16 option displays actual sprite pairs, and Zoom enlarges the tile sheet.

Sound debugger with channel notes, keyboards, and waveforms

The Control Panel also has CPU tracing and MIDI export.

Screenshots

Nametable viewer Sprite viewer
Nametables Sprites
Palette viewer Tile viewer
Palette Tiles

More images: NTSC filter, CRT filter, palette picker, debugger, controller settings, and Game Genie.

Files and settings

Save states (.mn1–.mn9), battery saves (.sav), and movies (.mnm) are stored beside the ROM. For a ROM inside a ZIP, they are stored beside the ZIP and named after the ROM. Save states only work in MyNES. Raw .sav files can be used in other emulators.

Settings are stored in ~/.mynes/config.properties. Most can also be changed in the menus. For example:

rewind.seconds=30
audio.latency-ms=60
ui.theme=dark

Headless mode

MyNES can run without a window:

java -jar mynes.jar --headless --rom game.nes --frames 900 \
    --input 60/40x3:start --screenshot 300,last --audio

Headless mode can save screenshots, audio, and a JSON report. --expect-not-blank and --expect-audio make checks return a failing exit code. --interactive provides a JSON command interface for stepping, breakpoints, watchpoints, traces, rewind, and movies. See --headless --help for all options.

Build

Java 25 and Maven are required:

git clone https://github.com/dimiro1/mynes.git
cd mynes
mvn -q compile exec:exec

Run mvn test for the test suite. CLAUDE.md has the design notes and detailed test results. Dendy mode is not supported yet.

Browser edition

The mynes-web module compiles the existing core to WebAssembly GC with TeaVM. To build the static distribution, use Java 25 and Maven:

mvn -pl mynes-web -am package -DskipTests
mkdir -p mynes-web/target/site
unzip -q mynes-web/target/mynes-web-*.zip -d mynes-web/target/site
python3 -m http.server 8080 --directory mynes-web/target/site

Open http://localhost:8080, choose a local .nes file, and play with the keyboard or a standard gamepad. The browser reads the file locally; no ROM is uploaded. Browsers require HTTP to load the Wasm file. The ZIP contains only static files and can be served by any static host. The Pages workflow deploys this same ZIP on pushes to master after Settings → Pages → Build and deployment → Source is set to GitHub Actions.

This prototype supports the core's ROM formats and mappers, video with the built-in NESdev palette, audio, player-one input, pause, and reset. Desktop features such as saves, rewind, filters, and the debugger are not wired up here yet.

License

MIT. See LICENSE.

About

A cycle accurate NES emulator written in Java.

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages