I've done some tests on my NTSC NES PPU's scanline times and found information that differs from what I've read. From my test I conclude that the first visible scanline begins around 7485 PPU clocks from NMI, and the right edge of the last visible scanline ends around 89250 PPU clocks from NMI. That is, there are 22 undisplayed scanlines at the start of VBL, rather than 21 and then a wasted scanline at the end of the frame. I also found that three PPU frames always total exactly 89342 CPU clocks, meaning that the average scanline duration is exactly 341 (rather than a hair less as I've read).
In my test the PPU is disabled and I have the VRAM address in the palette area to allow immediate feedback of $2007 accessess in the form of color change on screen. I figure the palette mapping is done at the final moment, so it has the least latency.
I wait for my NMI handler to be invoked so I get the most accurate beginning of a PPU frame. Then I wait 2486 clocks before accessing $2007 the first time, then 27255 more clocks and access $2007 again. This results in two color changes on screen, one just after the beginning of the first scanline, and the other just before the end of the last scanline. I then delay until 29781 clocks have passed (29780 every third frame) since the NMI and loop back (NMI is disabled at this point). The edges of the color changes wobble a bit, but they don't crawl over time. I also verified that my video capture is capturing all 240 scanlines.
This so strongly contradicts information I've read that I have to wonder what's going on.
In my test the PPU is disabled and I have the VRAM address in the palette area to allow immediate feedback of $2007 accessess in the form of color change on screen. I figure the palette mapping is done at the final moment, so it has the least latency.
I wait for my NMI handler to be invoked so I get the most accurate beginning of a PPU frame. Then I wait 2486 clocks before accessing $2007 the first time, then 27255 more clocks and access $2007 again. This results in two color changes on screen, one just after the beginning of the first scanline, and the other just before the end of the last scanline. I then delay until 29781 clocks have passed (29780 every third frame) since the NMI and loop back (NMI is disabled at this point). The edges of the color changes wobble a bit, but they don't crawl over time. I also verified that my video capture is capturing all 240 scanlines.
This so strongly contradicts information I've read that I have to wonder what's going on.
Code:
nmi: ; 1-3 clocks latency
; 7 clocks to vector nmi
lda #0 ; 2 disable nmi
sta $2000 ; 4
loop:
ldy #10 ; 2477 delay
lda #48
jsr delay_ya0
lda $2007 ; 4 write occurs at VBL + 2495 (scanline 21.95)
ldy #34 ; 27251 delay
lda #159
jsr delay_ya0
lda $2007 ; 4 write occurs at VBL + 29750 (scanline 261.73)
setup:
lda #$3f ; 2
sta $2006 ; 4
lda #$01 ; 2
sta $2006 ; 4
lda #3 ; 2
ldx <delay ; 3
dex ; 2
beq + ; 2/3 (every third frame branch is taken)
txa ; 2
: sta <delay ; 3
pha ; 16 delay
pla
pha
pla
nop
jmp loop ; 3
; 7 clocks to vector nmi
lda #0 ; 2 disable nmi
sta $2000 ; 4
loop:
ldy #10 ; 2477 delay
lda #48
jsr delay_ya0
lda $2007 ; 4 write occurs at VBL + 2495 (scanline 21.95)
ldy #34 ; 27251 delay
lda #159
jsr delay_ya0
lda $2007 ; 4 write occurs at VBL + 29750 (scanline 261.73)
setup:
lda #$3f ; 2
sta $2006 ; 4
lda #$01 ; 2
sta $2006 ; 4
lda #3 ; 2
ldx <delay ; 3
dex ; 2
beq + ; 2/3 (every third frame branch is taken)
txa ; 2
: sta <delay ; 3
pha ; 16 delay
pla
pha
pla
nop
jmp loop ; 3