Another NES Emulator - written for fun & learning - first implementation of wideNES
Go to file
Daniel Prilik aee8509bfa fix travis
2018-06-28 10:03:10 -07:00
cmake building on MSVC 2017-10-26 10:29:37 -07:00
research move docs to research 2017-11-12 12:48:01 -08:00
resources upload macOS bundles to GDrive 2018-06-08 10:47:29 -07:00
roms added demo rom (2048) to releases 2018-06-12 11:39:31 -07:00
src replace heavyweight args with single-header clara 2018-06-19 18:58:48 -07:00
thirdparty replace heavyweight args with single-header clara 2018-06-19 18:58:48 -07:00
.gitattributes move docs to research 2017-11-12 12:48:01 -08:00
.gitignore upload macOS bundles to GDrive 2018-06-08 10:47:29 -07:00
.travis.yml fix travis 2018-06-28 10:03:10 -07:00
_config.yml Set theme jekyll-theme-minimal 2017-11-12 12:58:40 -08:00
appveyor.yml added demo rom (2048) to releases 2018-06-12 11:39:31 -07:00
CMakeLists.txt replace heavyweight args with single-header clara 2018-06-19 18:58:48 -07:00
cppcheck.sh cleanup movies + reorg memory management 2018-05-24 13:50:38 -07:00
LICENSE *initial commit 2017-10-13 20:18:31 -07:00
mk_msvc.ps1 ui and build improvements 2017-12-14 16:17:51 -08:00
nestest.sh render pattern tables in debug window 2017-11-02 22:23:02 -07:00
README.md replace heavyweight args with single-header clara 2018-06-19 18:58:48 -07:00

ANESE Logo

Build Status Windows Build Status macOS/Linux

ANESE (Another NES Emulator) is a Nintendo Entertainment System Emulator being written for fun and learning.

While accuracy is a long-term goal, ANESE's primary goal is to play some of the more popular titles. As of now, most basic Mappers have been implemented, so popular titles should be working! 😄

ANESE is built with cross-platform in mind, and is regularly built on all major platforms (macOS, Windows, and Linux). ANESE doesn't use any vendor-specific language extensions, and is compiled with strict compiler flags. It is also linted (fairly) regularly.

ANESE strives for clean and interesting C++11 code, with an emphasis on readability and maintainability. With that said, performance is important, but it's not ANESE's primary focus.

Downloads

Right now, there are no official releases of ANESE, but there are ways to get nightly releases.

Windows: You can download nightly versions of ANESE from AppVeyor's build artifacts page.

macOS: Travis uploads nightly ANESE.app bundles to this GDrive folder.

Building

Dependencies

While ANESE's emulation core (src/nes) doesn't have any major dependencies, there are a couple of libraries the UI uses. Most of these dependencies are bundled with ANESE (see: /thirdparty), although some do require additional installation:

  • SDL2 (video/audio/controls)
    • Linux: apt-get install libsdl2-dev (on Ubuntu)
    • MacOS: brew install SDL2
    • Windows:
      • Download dev libs from here and unzip them somewhere.
      • EITHER: Set the SDL environment variable to point to the dev libs
      • OR: Unzip them to C:\sdl2\ (Where I put them)
      • OR: Modify the SDL2_MORE_INCLUDE_DIR variable in CMakeLists.txt to point to the SDL2 dev libs

Generating + Compiling

ANESE builds with CMake. Nothing too fancy here.

# in ANESE root
mkdir build
cd build
cmake ..
make
make install # on macOS: creates ANESE.app in ANESE/bin/

On Windows, building is very similar:

mkdir build
cd build
cmake ..
msbuild anese.sln /p:Configuration=Release

If you're interested in looking under the hood of the PPU, you can pass the -DDEBUG_PPU flag to cmake and have ANESE show PPU debug windows.

Running

ANESE can run from the shell using anese [rom.nes] syntax.

If no ROM is provided, a simple dialog window pops-up prompting the user to select a valid NES rom.

For a full list of switches, run anese -h

Windows Users: make sure the executable can find SDL2.dll! Download the runtime DLLs from the SDL website, and plop them in the same directory as anese.exe

Mappers

There aren't too many mappers implemented at the moment, but the ones that are cover a sizable chunk of the popular NES library.

# Name Some Games
000 NROM Super Mario Bros. 1, Donkey Kong, Duck Hunt
001 MMC1 Legend of Zelda, Dr. Mario, Metroid
002 UxROM Megaman, Contra, Castlevania
003 CNROM Arkanoid, Cybernoid, Solomon's Key
004 MMC3 Super Mario Bros 2 & 3, Kirby's Adventure
007 AxROM Marble Madness, Battletoads
009 MMC2 Punch Out!!

If a game you love doesn't work in ANESE, feel free to implement it's mapper and open a PR for it :D

Controls

Currently hard-coded to the following:

Button Key Controller
A Z X
B X A
Start Enter Start
Select Right Shift Select
Up Up arrow D-Pad
Down Down arrow D-Pad
Left Left arrow D-Pad
Right Right arrow D-Pad

Any xbox-compatible controller should work.

There are also a couple of emulator actions:

Action Key Controller
Pause / Open Menu Esc Left Thumbstick Button
Reset Ctrl - R
Power Cycle Ctrl - P
Toggle CPU logging Ctrl - C
Speed +25% Ctrl - =
Speed -25% Ctrl - -
Fast-Forward Space Right Thumbstick Button
Make Save-State Ctrl - (1-4)
Load Save-State Ctrl - Shift - (1-4)

(there are 4 save-state slots)

DISCLAIMERS

  • The CPU is instruction-cycle accurate, but not sub-instruction cycle accurate. While this inaccuracy doesn't affect most games, there are some that that rely on sub-instruction level timings (eg: Solomon's Key).
    • The --alt-nmi-timing flag might fix some of these games.
  • The APU is not my code. I wanted to get ANESE at least partially up and running before new-years 2018, so I'm using Blargg's venerable nes_snd_emu library to handle sound (for now). Once I polish up some of the other aspects of the emulator, I'll try to revisit my own APU implementation (which is currently a stub)

TODO

This is a rough list of things I would like to accomplish, with those closer to the top higher on my priority list:

  • Implement: My own APU (don't use Blarrg's)
  • Implement: Robust menu system
  • Refactor: Modularize main.cc - push everything into src/ui/
    • Refactor: Split gui.cc into more files!
  • CMake: Make building macOS bundles less brittle
  • Refactor: Push common mapper behavior to Base Mapper (eg: bank chunking)
  • Implement: LibRetro Core
  • Implement: Sub-instruction cycle accurate CPU
  • Cleanup: Unify naming conventions (either camelCase or snake_case)
  • Cleanup: Comment the codebase even more
  • Security: Actually bounds-check files lol
  • Cleanup: Conform to the .fm2 movie format better
  • Cleanup: Remove fatal asserts (?)
  • Cleanup: Switch to a better logging system (*cough* not fprintf *cough*)

Roadmap

Key Milestones

  • Parse iNES files
  • Create Cartridges (iNES + Mapper interface)
  • CPU
    • Set Up Memory Map
    • Hardware Structures (registers)
    • Core Loop / Basic Functionality
      • Read / Write RAM
      • Addressing Modes
      • Fetch - Decode - Execute
    • Official Opcodes Implemented
    • Handle Interrupts
  • PPU
    • Set Up Basic Rendering Context (SDL)
    • Implement Registers + Memory Map them
    • Implement DMA
    • Generate NMI -> CPU
    • Core rendering loop
      • Background Rendering
      • Sprite Rendering - currently not hardware accurate
      • Proper Background / Foreground blending
    • Sprite Zero Hit
    • Misc PPU flags (emphasize RGB, Greyscale, etc...)
  • APU - Uses nes_snd_emu by Blargg - crashes sometimes
    • Implement Registers + Memory Map them
    • Frame Timer IRQ
    • Set Up Basic Sound Output Context (SDL)
    • Channels
      • PCM 1
      • PCM 2
      • Triangle
      • Noise
      • DMC
    • DMC DMA
  • Joypads
    • Basic Controller
    • Zapper
    • NES Four Score

Secondary Milestones

  • Loading Files with picker
  • Reset / Power-cycle
  • Fast Forward
  • Run / Pause
  • Saving
    • Battery Backed RAM - Saves to .sav
    • Save-states
      • Dump to file
  • Config File
    • Remap controls
  • Running NESTEST (behind a flag)
  • Controller support - currently very basic
  • A SDL GUI
    • SDL-based ROM picker
    • Options menu

Tertiary Milestones (Fun Features!)

  • Zipped ROM support
  • Rewind
  • Game Genie
  • Movie recording and playback
  • More ROM formats (not just iNES)
  • Proper PAL handling?
  • Proper NTSC artifacting?
  • Multiple Front-ends
    • SDL Standalone
    • LibRetro
  • Debugger!
    • There is a lot of great infrastructure in place that could make ANESE a top-tier NES debugger, primarily the fact that all memory-interfaced objects must implement peek, which enables non-destructive looks at arbitrary objects!
    • CPU
      • Step through instructions - super jank, no external flags
    • PPU Views
      • Static Palette
      • Palette Memory
      • Pattern Tables
      • Nametables
      • OAM memory

Accuracy & Compatibility

  • More Mappers!
  • CPU
    • Implement Unofficial Opcodes
    • Pass More Tests yo
    • (Stretch) Switch to sub-instruction level cycle-based emulation (vs instruction level)
  • PPU
    • Make the sprite rendering pipeline more accurate (fetch-timings)
      • This should fix Punch Out!! UPDATE: it totally did.
    • Pass More Tests yo
    • Make value in PPU <-> CPU bus decay

Attributions

  • A big shout-out to LaiNES and fogleman/nes, two solid NES emulators that I referenced while implementing some particularly tricky parts of the PPU). While I actively avoided looking at the source codes of other NES emulators as I set about writing my initial implementations of the CPU and PPU, I did sneak a peek at how others did some things when I got very stuck.
  • Blargg's nes_snd_emu makes ANESE sound as good as it does 😄
  • These awesome libraries make ANESE a lot nicer to use: