Day 12 - VBlank and Interrupts

Published: 2005-07-22
Updated: 2010-12-19
Author: Mike Huber

VBlank?

If you don't know what VBlank is, pretend I'm hitting you with a trout. If you do know what VBlank is, pretend I'm hitting you with a trout. If you have no idea what a trout has to do with the NES, pretend I'm hitting you with a trout.

Now that we have an imaginary fish stench in the room, let's learn a better way to sync with VBlank.

How do we use it?

First, we have a label, say 'VBlank_Routine', so we put it in the addresses in Bank 1 at $FFFA. Like so:

.bank 1 .org $FFFA .dw VBlank_Routine ; address to execute on VBlank .dw Start ; address to execute at RESET. .dw 0 ; address to execute during a BRK instruction (Another Day, Another time).

.bank 0
.org $0000  ;variables VBlankOrNo  .db 0
.org $8000  ;code VBlank_Routine:
;start of function to execute on VBlank
inc VBlankOrNo
; add one (1) to VBlankOrNo, will be 1 if VBlank, 0 if not.
rti  ; RTI is (Interrupt RETurn or ReTurn from Interrupt)

Start: ;start of main code ;blah some code ;waitforvblank: old code ; lda $2002 old code ; bpl waitforvblank old code ; the new code is :

WaitForVBlank: lda VBlankOrNo ; A = VBlankOrNO cmp #1 ; if A == 1 then is VBlank bne WaitForVBlank ; if not VBlank, then loop and do again dec VBlankOrNo ; 1– or VBlankOrNO - 1 . VBlankOrNo will be 0 again.

; blah, code as usual. </code>

I hope you get the general idea. I may have gotten something backwards or something, so if you know this is wrong, please tell me (I'm tired and may have not typed right!).

UPDATE: Don't forget to set the "Generate VBlank bit" in one of the PPU Control ports! (it's bit 7 of one of them, I think).

This Day In Review

This method will, appearantely, be much more stable than our old loop.

Greetings!,
-Mike H a.k.a GbaGuy