I've spent a week or so improving CPU and PPU timing in my emulator, Macifom, trying to improve compatibility with certain titles, especially everyone's favorite, Battletoads. Following the advice of others on the board I modified my renderer to perform VRAM address updates on exact cycles and only when the PPU is on (e.g. vertical increment on 251, horizontal reset on 256, copy temporary VRAM address on 303 of pre-render scanline). As my emulator renders in scanline units only, however, I am not emulating the timed reads during rendering - the first cycle of a new scanline is reached, it's rendered in its entirety.
With these improvements in place, the intro scenes and first level of Battletoads are now totally glitch-free. The second level, as you've probably already guessed, is somewhat less than perfect.
The start of the second level plays flawlessly for a time with no status bar shaking or other visible issues. Eventually, however, the game locks transitioning between status bar and normal background rendering. This seems to occur almost at random, with the status bar either near its normal position or three quarters of the way down the screen.
Everything starts so pleasantly:
When the sprite 0 hit misses and the game locks, the status bar is in one of a couple positions:
From an architectural standpoint, there's nothing remarkable about my emulator. Cycle-exact accounting is used for the CPU and PPU, which are synchronized using the common catch-up method. Here's where it stands on the correctness tests:
(CPU Test Programs)
* Kevtris' nestest.nes - Passes for all legal opcodes.
* Blargg's NES CPU Test 5 - Passes for legal opcodes.
* Blargg's CPU Timing Test 6 - Passes for legal opcodes.
* Branch Basics (Blargg's Branch Timing Tests) - Passes.
* Backward Branches (Blargg's Branch Timing Tests) - Passes.
* Forward Branches (Blargg's Branch Timing Tests) - Passes.
* Blargg's CLI Latency Test - Fails (#3).
(PPU Test Programs)
* Palette RAM (Blargg's PPU Tests 2005-09-15b) - Passes.
* Power-up Palette (Blargg's PPU Tests 2005-09-15b) - Fails (#2) (Palette values are initialized differently).
* Sprite RAM (Blargg's PPU Tests 2005-09-15b) - Passes.
* VBL Clear Time (Blargg's PPU Tests 2005-09-15b) - Fails (#3) (Currently clearing at cycle 6820, test checks for 6810).
* VRAM Access (Blargg's PPU Tests 2005-09-15b) - Passes.
* Sprite 0 Hit Basics (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Alignment (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Corners (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Flip (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Left Clip (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#2).
* Sprite 0 Hit Right Edge (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#2).
* Sprite 0 Hit Screen Bottom (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Double Height (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Timing Basics (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#3).
* Sprite 0 Hit Order (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#2).
* Sprite 0 Hit Edge Timing (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#2).
* Blargg's Sprite 0 Hit Timing - Fails (#3).
* Sprite Overflow Basics (Blargg's Sprite Overflow Tests) - Passes.
* Sprite Overflow Details (Blargg's Sprite Overflow Tests) - Passes.
* Sprite Overflow Timing (Blargg's Sprite Overflow Tests) - Fails (#2).
* Sprite Overflow Obscure (Blargg's Sprite Overflow Tests) - Fails (#2).
* Sprite Overflow Emulation (Blargg's Sprite Overflow Tests) - Passes.
* Frame Basics (Blargg's VBL/NMI Tests) - Passes.
* VBL Timing (Blargg's VBL/NMI Tests) - Fails (#3) (Seems to be one cycle off - read is occurring on 89341 rather than 89342).
* Even / Odd Frames (Blargg's VBL/NMI Tests) - Fails (#3).
* VBL Clear Timing (Blargg's VBL/NMI Tests) - Fails (#5).
* NMI Suppression (Blargg's VBL/NMI Tests) - Fails (#3).
* NMI Disable (Blargg's VBL/NMI Tests) - Fails (#3).
* NMI Timing (Blargg's VBL/NMI Tests) - Fails (#3).
* scanline.nes - All tests fail due to lack of partial scanline rendering.
This post describes a similar issue but the author didn't disclose precisely how he resolved it.
Before I start stepping through execution, do any old hands have some advice as to where I should focus my attention? Is the scanline-based rendering I'm using ultimately insufficient for Rare/Tradewest titles? Does Battletoads perform perform some periodic task (like DMC DMA?) that I might not be accounting for that could whack the status bar down that far? You help is much appreciated!
With these improvements in place, the intro scenes and first level of Battletoads are now totally glitch-free. The second level, as you've probably already guessed, is somewhat less than perfect.
The start of the second level plays flawlessly for a time with no status bar shaking or other visible issues. Eventually, however, the game locks transitioning between status bar and normal background rendering. This seems to occur almost at random, with the status bar either near its normal position or three quarters of the way down the screen.
Everything starts so pleasantly:
When the sprite 0 hit misses and the game locks, the status bar is in one of a couple positions:
From an architectural standpoint, there's nothing remarkable about my emulator. Cycle-exact accounting is used for the CPU and PPU, which are synchronized using the common catch-up method. Here's where it stands on the correctness tests:
(CPU Test Programs)
* Kevtris' nestest.nes - Passes for all legal opcodes.
* Blargg's NES CPU Test 5 - Passes for legal opcodes.
* Blargg's CPU Timing Test 6 - Passes for legal opcodes.
* Branch Basics (Blargg's Branch Timing Tests) - Passes.
* Backward Branches (Blargg's Branch Timing Tests) - Passes.
* Forward Branches (Blargg's Branch Timing Tests) - Passes.
* Blargg's CLI Latency Test - Fails (#3).
(PPU Test Programs)
* Palette RAM (Blargg's PPU Tests 2005-09-15b) - Passes.
* Power-up Palette (Blargg's PPU Tests 2005-09-15b) - Fails (#2) (Palette values are initialized differently).
* Sprite RAM (Blargg's PPU Tests 2005-09-15b) - Passes.
* VBL Clear Time (Blargg's PPU Tests 2005-09-15b) - Fails (#3) (Currently clearing at cycle 6820, test checks for 6810).
* VRAM Access (Blargg's PPU Tests 2005-09-15b) - Passes.
* Sprite 0 Hit Basics (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Alignment (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Corners (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Flip (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Left Clip (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#2).
* Sprite 0 Hit Right Edge (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#2).
* Sprite 0 Hit Screen Bottom (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Double Height (Blargg's Sprite Hit Tests 2005-10-05) - Passes.
* Sprite 0 Hit Timing Basics (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#3).
* Sprite 0 Hit Order (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#2).
* Sprite 0 Hit Edge Timing (Blargg's Sprite Hit Tests 2005-10-05) - Fails (#2).
* Blargg's Sprite 0 Hit Timing - Fails (#3).
* Sprite Overflow Basics (Blargg's Sprite Overflow Tests) - Passes.
* Sprite Overflow Details (Blargg's Sprite Overflow Tests) - Passes.
* Sprite Overflow Timing (Blargg's Sprite Overflow Tests) - Fails (#2).
* Sprite Overflow Obscure (Blargg's Sprite Overflow Tests) - Fails (#2).
* Sprite Overflow Emulation (Blargg's Sprite Overflow Tests) - Passes.
* Frame Basics (Blargg's VBL/NMI Tests) - Passes.
* VBL Timing (Blargg's VBL/NMI Tests) - Fails (#3) (Seems to be one cycle off - read is occurring on 89341 rather than 89342).
* Even / Odd Frames (Blargg's VBL/NMI Tests) - Fails (#3).
* VBL Clear Timing (Blargg's VBL/NMI Tests) - Fails (#5).
* NMI Suppression (Blargg's VBL/NMI Tests) - Fails (#3).
* NMI Disable (Blargg's VBL/NMI Tests) - Fails (#3).
* NMI Timing (Blargg's VBL/NMI Tests) - Fails (#3).
* scanline.nes - All tests fail due to lack of partial scanline rendering.
This post describes a similar issue but the author didn't disclose precisely how he resolved it.
Before I start stepping through execution, do any old hands have some advice as to where I should focus my attention? Is the scanline-based rendering I'm using ultimately insufficient for Rare/Tradewest titles? Does Battletoads perform perform some periodic task (like DMC DMA?) that I might not be accounting for that could whack the status bar down that far? You help is much appreciated!