cmake | ||
research | ||
resources | ||
roms | ||
src | ||
thirdparty | ||
.gitattributes | ||
.gitignore | ||
.travis.yml | ||
_config.yml | ||
appveyor.yml | ||
CMakeLists.txt | ||
cppcheck.sh | ||
LICENSE | ||
mk_msvc.ps1 | ||
nestest.sh | ||
README.md |
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 inCMakeLists.txt
to point to the SDL2 dev libs
- Linux:
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
- 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 intosrc/ui/
- Refactor: Split
gui.cc
into more files!
- Refactor: Split
- 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
- Battery Backed RAM - Saves to
- 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
- 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
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
- Make the sprite rendering pipeline more accurate (fetch-timings)
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: