MMC5 IRQ RE Results

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
MMC5 IRQ RE Results
by on (#5527)
I've finished a first round of MMC5 IRQ tests with my "stop-n-swop" technique. The following results cover registers $5203 (write) and $5204 (read). $5204 bit 7 is the IRQ flag, bit 6 is the in-frame flag, and $5203 sets the scanline on which the IRQ flag is set.

The notation VBL+n refers to n clocks after the PPU's VBL flag ($2002.7) is first set. These times are accurate within a couple of clocks, but not exact. Enabling PPU rendering means enabling OBJ and/or BG rendering ($2001 bits 4 and/or 3 set), and disabling rendering means disabling both OBJ and BG rendering.

- If PPU rendering is enabled, the in-frame flag is set at VBL+2386 (scanline 21.0) and cleared at VBL+29669 (scanline 261.0).

- Disabling the PPU by writing to $2001 immediately clears the in-frame flag. Apparently the MMC5 watches for writes to $2001.

- If the IRQ scanline is set to 1, the IRQ flag is set at VBL+2500 (scanline 22.0). If the IRQ scanline is set to 239, the IRQ flag is set at VBL+29555 (scanline 260.0).

- Reading $5204 clears the IRQ flag.

- If PPU rendering is disabled and then enabled later than VBL+2386, the in-frame flag is set when the next scanline starts and the IRQ scanline is also delayed by the same amount. This does not affect the time that the in-frame flag is cleared. Apparently the MMC5 watches the PPU address lines to determine when a scanline starts.

- The IRQ scanline can be changed mid-frame. If set to a scanline that hasn't started yet, the IRQ flag will be set when that scanline starts. If set to a scanline that's already started, the IRQ flag isn't affected.

- If the IRQ scanline is set to 0 or 240-255, the IRQ flag never gets set during the frame. Additionally, if the IRQ scanline is one of these values at the time the in-frame flag is set at the beginning of a frame, the IRQ flag is also cleared.

Post any problems or questions regarding these results. Raw test code available on request.

by on (#5540)
This seems to confirm what's stated in the following:

http://tripoint.org/kevtris/mappers/incoming/mmc5.txt


Although you mention the in-frame flag is raised on scanline 0, rather than scanline 1 (0=first scanline rendered... I don't usually include vblank/pre-render in my scanline numbers... confuzzles me).
Re: MMC5 IRQ RE Results
by on (#5541)
blargg wrote:
- Disabling the PPU by writing to $2001 immediately clears the in-frame flag. Apparently the MMC5 watches for writes to $2001.

How immediately? Perhaps it just sees the stream of nametable accesses stop. It could be the same circuitry that watches for nametable reads in order to inject its own ExGrafix data to replace the attribute data.

by on (#5551)
Disabling the PPU by writing to $2001 clears the in-frame flag immediately. Here's the test code I ran:

Code:
ldx   $5204     ; x = in-frame flag before disable
lda   #$00
sta   $2001     ; disable PPU
ldy   $5204     ; y = in-frame flag after disable
jsr   print_x   ; prints $40
jsr   print_y   ; prints $00


Quote:
This seems to confirm what's stated [...] Although you mention the in-frame flag is raised on scanline 0, rather than scanline 1


The in-frame flag was definitely always raised at least one scanline before the IRQ flag.

by on (#5556)
blargg wrote:
Disabling the PPU by writing to $2001 clears the in-frame flag immediately. Here's the test code I ran:

Code:
ldx   $5204     ; x = in-frame flag before disable
lda   #$00
sta   $2001     ; disable PPU
ldy   $5204     ; y = in-frame flag after disable
jsr   print_x   ; prints $40
jsr   print_y   ; prints $00

There are four CPU cycles between the STA $2001 and the LDY $5204. This means twelve PPU cycles, more than enough for a missed nametable access.

by on (#5558)
That code reads $5204 four cycles after writing to $2001, the equivalent of 12 PPU cycles (NTSC), plenty of time for the MMC5 to see the PPU going inactive.

Of course, you might try tricking the MMC5 by writing to $3F01 instead of $2001. Maybe the MMC5 is more sensitive to the actual address written (assuming that it is detecting $2001 writes).

I think the way the MMC5 detects a new scanline is by looking for three consecutive nametable fetches. This only happens once per scanline, with the third fetch coming at PPU cycle 1 of a new scanline (numbering cycles from 0-340 ). I'm thinking that when the MMC5 sees three straight NT fetches, if checks the in-frame flag and, if clear, sets it and clears the scanline counter. If the in-frame flag is set, the scanline counter would be incremented and the IRQ flag set if the value matches what was written in $5203. The in-frame flag remains set until at least three PPU cycles pass without a VRAM fetch, at which point the flag is cleared. That's my theory, anyway - I'm sure there are other ways to do it.

I would be particularly interested in how the MMC5 knows if 8x8 or 8x16 sprites are in use. The only way I can think of is to monitor writes to $2000. Maybe someone can try writing to $3FF0 to try to trick it?

by on (#5560)
Anonymous wrote:
Of course, you might try tricking the MMC5 by writing to $3F01 instead of $2001. Maybe the MMC5 is more sensitive to the actual address written (assuming that it is detecting $2001 writes).


Considering the MMC5 was designed by Nintendo with very intimate knowledge of the NES PPU in mind, I seriously doubt it would 'miss' writes to $2008-$3FFF.