Every emulator has its share of tricky games to emulate, and the NES is no exception. Its unusual addressing scheme meant that game writers trying to push the performance of the system had to use every trick in the book. One of the hardest games to get working properly is also one of the most famous “NES Hard” games out there, Battletoads!
This game’s a masterpiece on the original hardware. It’s gorgeous and makes good use of the NES’s limited graphics hardware, and is also tough as nails. It also uses a bunch of weird tricks that rely on proper CPU and PPU timing, and relies on being able to change the state of the PPU as very precise points, making it a real pain in the rear for an emulator to run properly. In order for Battletoads to be playable, you need to be very nearly cycle accurate with your timings.
Naturally, I wanted to see just how badly it would run in RusticNES. At this stage, RusticNES processes one instruction at a time all in one go, and has an overclocked CPU: each instruction takes just one cycle. Let’s boot it and see:
So far so good! That this boots at all means my AxROM mapper is working correctly, for some definition of correct. Things go downhill quickly though:
I’m not entirely sure what’s going on up there. AxROM uses 8kb of CHR RAM, so the game should be in full control over tile updates, but it seems to miss part of the loading sequence and we get title screen tiles instead of the ship.
This is the meat and potatoes of the problem. I’m nearly certain the game is either relying on unimplemented Audio IRQs, or CPU-based spinwaits to time itself to individual scanlines and decide when to enable the display and adjust scrolling registers. Because my emulated CPU runs way too fast, Battletoads completely misses the mark and we get this instead.
This will be a fun little project! There is no one quick fix I can apply to improve this game. Instead, it should slowly improve and regress as the emulator strives for accuracy. I’ll revisit this game if new emulator features cause it to improve, and we’ll see where the journey takes us!