PPUSTATUS not being read

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
PPUSTATUS not being read
by on (#208809)
Hello, I'm coding an NES emulator in JavaScript, and currently I'm facing a problem that I can't overcome.
I've not implemented any mappers or scrolling, and toying with simplest games like donkey kong.

DK runs, just that its slow. I've made a forums post previously but I didn't bump it viewtopic.php?f=3&t=16293

The reason for slowness is that in a second, the game is only triggering 20-25 NMIs. MS Pac-man in particular doesn't trigger NMIs at all.
I debugged and compared instruction flow with fceux, and found out that in my emulator, bit 7 of PPUCTRL is being disabled, so the emulator can't do NMI. On further inspection I found out that PPUSTATUS is not being read sometimes by the games. MS pac man reads PPUSTATUS once or twice, then never reads it and as a result the NMI bit is not set and the game renders nothing.

My CPU implementation is good, as it matches the nintendulator nestest.log.

Do any of you guys have any idea that what wrong/missing implementation might be responsible for this?
Re: PPUSTATUS not being read
by on (#208812)
Oh, I forgot to mention that i've not implemented APU at all, ignoring writes to the registers and returning 0 on read.
Is handling of APU IRQs required for correct game functioning?
Re: PPUSTATUS not being read
by on (#208825)
Games don't use PPUSTATUS to detect vblank, except during initialization while waiting for the PPU to become stable. After that, games usually enable NMIs and that's what they use to know when vblank starts. Games may or may not read PPUSTATUS to "acknowledge" the NMI, but that's not necessary since the NMI flag clears itself at the end of vblank. Games may also read PPUSTATUS to reset the $2005/6 hi/lo latch, but that's also optional, so it's highly possible that some games will only use PPUSTATUS during initialization and then never again.

Quote:
MS pac man reads PPUSTATUS once or twice, then never reads it and as a result the NMI bit is not set

As long as NMIs are enabled via PPUCTRL, they'll fire every time vblank starts, the game code doesn't have to do anything to "trigger" NMIs, they'll fire regardless of what the CPU is doing.
Re: PPUSTATUS not being read
by on (#208827)
If it matters, Ms. Pac-Man is on the tricky list for some edge-case stuff it does with PPUSTATUS. Lolo 2 and Spelunker have the same problem.
These rely on 1 cycle NMI delay when PPUSTATUS ($2002) bit 7 gets set inside vblank (if $2002 has not been read yet), in which PPUSTATUS bit 7 can be read as true.


Here's how I understand what's going on in games like that:

  1. CPU reads $AD (LDA abs) or $2C (BIT abs) from PC++
  2. CPU reads $02 (low byte of $2002) from PC++
  3. CPU reads $20 (high byte of $2002) from PC++
    Vertical blanking begins between these cycles. /NMI goes low, because the CPU checks for falling edges on /NMI only between instructions, the CPU's interrupt circuit doesn't notice.
  4. CPU reads $80 from $2002
    /NMI goes high because the read has acknowledged the interrupt

I'm not sure whether the NMI handler gets called at this point. I know there's a minimum high time of one cycle for it to recognize the next falling edge, but I couldn't find anything about a minimum low time.
Re: PPUSTATUS not being read
by on (#208828)
NMI goes to an S/R latch, so the minimum time will be an analog effect instead of a digital one. (Look at visual6502 nodes "NMIP" and "#NMIP")
Re: PPUSTATUS not being read
by on (#208836)
Thanks for the replies everyone. I've figured out the error by comparing the execution with fceux & mesen.
I noticed that in my case, write to PPUCTRL was hugely delayed. My emulator is of a catch up design with scanline accuracy.
Due to a bug, the cycle counting algorithm was incorrect which slowed the cpu down.
Now with proper cycle counting, Donkey Kong and pac man are running fine. I'm not introducing any delay after reading ppustatus, although I do NMI right after the first vblank scanline is rendered.
Re: PPUSTATUS not being read
by on (#208837)
How exactly does Ms. Pac-Man rely on such a fine timing detail like this? Is it something intentional or is it more like "the game ignores this hardware quirk that luckily prevents the program from crashing"?