Emulation is a fickle thing. If every game released followed the platform’s accepted conventions, writing an NES emulator would be a piece of cake. On paper, it’s a simple system. But of course, games defy convention, and pull all sorts of weird tricks that make a naive approach difficult to achieve. Over the last few months, I threw my own naive approach out the window and decided enough was enough. RusticNES now emulates the PPU down to the last cycle, so that games which rely on obscure hardware behaviors and precise timing have a better chance at behaving correctly.
This was a straightforward undertaking, and kind of scary, since I had to completely destroy the most visible part of the emulator, then replace it with new, untested code. This provided some really fun bugs:
Now instead of rendering the graphics every scanline or every frame, the NES’s PPU exists in software the same way it does in hardware. All the internal registers are implemented, and writes to those registers from the CPU make the appropriate internal changes as on real hardware, including several bugs and unintuittive features. To draw the screen, the PPU is clocked 3 times per CPU cycle (on NTSC) and performs its operations, increments, reads and writes to memory in the same sequence as real hardware. That image above may look broken, but it’s still clearly the Zelda title screen, and that was a major milestone. This evolved rapidly as new features were re-implemented in the PPU:
The new implementation revealed some unusual behavior with PPU register writes from the CPU, which perform some funky impartial updates to the internal memory address. I learned that the scrolling “registers” don’t actually exist, and are instead weirdly mapped to the internal lookup address and, crucially, can be updated by a game in real time. This was the missing piece of the graphics puzzle for Zelda II’s title screen, which finally renders correctly:
Now that the PPU is working properly, I can implement a new cartridge type, MMU3! This cartridge has a special feature in the form of a scanline counter, which is used by games for special effects and simpler playing field splits without relying on a sprite zero hit or accurate CPU spin loops. For the first time, Super Mario 3 and Kirby’s Adventure are playable in RusticNES:
With the CPU and PPU accuracy issues worked out, I’m also pleased to report that Battletoads is now playable! At least, the first couple of levels definitely are. Battletoads is famous for its ridiculous difficulty, and for good reason. I can’t get more than 1-2 levels in. If anyone more practiced on the game wants to give it a whirl and let me know if the later levels are all working, I’d very much appreciate the bug reports.
Things are coming right along! Major features left to implement mostly include additional cartridge types and peripherals other than standard controllers. The user interface in rusticnes-sdl is also much improved at this point, and I’ll do another blog post on its new features and tricks later. Then maybe a release? Bah, it’ll be ready when it’s ready!