Best vBlank Wait with $2002?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
User avatar
FARID
Posts: 499
Joined: Wed Apr 07, 2010 1:14 am
Location: Iran
Contact:

Best vBlank Wait with $2002?

Post by FARID »

Someone on the Nesdev IRC Channel said : "Don't spin around $2002, because it is unrealabe and there is a chance to miss a frame"
Someone else said : "My code is very fishy!" :

****************************************************

Here is my warm up routine :

Code: Select all

	LDX #$04            ; 4 Times vblank period will come and go

warmup_loop:           ; Do loop until vblank starts
	BIT $2002           ; It is not vblank period / 7th bit of $2002 is 0 / BIT, Clear the negative sign
	BPL warmup_loop     ; The result is Plus / BPL, Continue the loop!

; Vblank period has just started / 7th bit of $2002 is 1 / BIT, Set the negative sign / The result is Negative / BPL, Don't continue the loop!

vbend_loop:            ; Do loop until current vblank ends
	BIT $2002           ; It is vblank period / 7th bit of $2002 is 1 / BIT, Set the negative sign 
	BMI vbend_loop      ; The result is Negative / BMI, Continue the loop!

; Vblank period has just ended / 7th bit of $2002 is 0 / BIT, Clear the negative sign / The result is Plus / BMI, Don't continue the loop!

	DEX
	BNE warmup_loop
****************************************************

Here is my vblank wait routine :

Code: Select all

vblank_wait:           ; Do loop until current vblank ends
	BIT $2002           ; It is vblank period by sheer chance! / 7th bit of $2002 is 1 / BIT, Set the negative sign
	BMI vblank_wait     ; The result is Negative / BMI, Continue the loop!

; Vblank period has just ended / 7th bit of $2002 is 0 / BIT, Clear the negative sign / The result is Plus / BMI, Don't continue the loop!

vbstart_loop:          ; Do loop until a new vblank starts
	BIT $2002           ; It is not vblank period / 7th bit of $2002 is 0 / BIT, Clear the negative sign
	BPL vbstart_loop    ; The result is Plus / BPL, Continue the loop!		

; Vblank period has just started / 7th bit of $2002 is 1 / BIT, Set the negative sign / The result is Negative / BPL, Don't continue the loop!

	RTS                  ; Now the screen can be updated!
****************************************************

So, is it really fishy?! Or will I miss any frame?! :?
User avatar
Memblers
Site Admin
Posts: 4044
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Re: Best vBlank Wait with $2002?

Post by Memblers »

A BIT $2002 / BMI loop is never useful. Use BPL only. It's fine to use it during warm-up. But using it for timing will always result in some frames being missed. Reading the flag resets it, and the NES also resets it at a certain time every frame. If the register is read at the same time the NES resets it, then you'll miss that frame. Whenever correct timing is needed, you must enable NMI and set a flag there, then check that flag in your wait loop.

Read this:
http://wiki.nesdev.com/w/index.php/NMI
User avatar
FARID
Posts: 499
Joined: Wed Apr 07, 2010 1:14 am
Location: Iran
Contact:

Re: Best vBlank Wait with $2002?

Post by FARID »

I put that BIT $2002 / BMI in the vblank wait routine to skip any vblanks which is on its halfway and then wait for a new vblank to get a full vblank period.
Is it useless for that purpose?
Also NMI is disabled all the time.
User avatar
Bregalad
Posts: 8060
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Best vBlank Wait with $2002?

Post by Bregalad »

Is it useless for that purpose?
Yes. Just a bit $2002 with no BMI will have the same purpose.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Best vBlank Wait with $2002?

Post by thefox »

FARID wrote:I put that BIT $2002 / BMI in the vblank wait routine to skip any vblanks which is on its halfway and then wait for a new vblank to get a full vblank period.
Is it useless for that purpose?
Also NMI is disabled all the time.
To rephrase what was said already: BIT $2002 / BMI is useless because reading $2002 has the side-effect of clearing the vblank flag. So, if the BIT $2002 happened to return the vblank flag as set, it would also clear it at the same time, and the next iteration of loop would return it as unset, exiting the loop. And if BIT $2002 returned the vblank flag as already being cleared, then of course the BMI branch would never be taken. In any case, the end result is the same, the vblank flag is cleared.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
tepples
Posts: 22720
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Best vBlank Wait with $2002?

Post by tepples »

Memblers wrote:Read this:
http://wiki.nesdev.com/w/index.php/NMI
I was the one reviewing Farid's code. He's using it for a multicart, and the NMI handler is that of one of the games. In order to use NMI, he'd have to understand what variables the NMI handler uses and how to disable their game-related function so that it doesn't interfere.
User avatar
Dwedit
Posts: 4934
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Best vBlank Wait with $2002?

Post by Dwedit »

Trying to avoid NMI for a menu? Try putting sprite 0 at the bottom of the screen, then you can wait for a sprite 0 hit, then delay some cycles after that so you know you're in vblank time.

Before you display your first frame though, you'll probably need to do repeated 2002 polling for vblank, which can miss frames. Then you can display a frame with the correct scroll values and sprite contents, then sprite 0 hit will work after that.

But if the intent isn't true 60FPS, and is just to wait for vblank to update a menu or something, then does it really matter if you miss frames?
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
Bregalad
Posts: 8060
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Best vBlank Wait with $2002?

Post by Bregalad »

For a menu I wouldn't bother to miss frames. The game Portopia, which is entirely menu based, relies on $2002 polling only and doesn't use interrupts ever.
User avatar
tokumaru
Posts: 12434
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Best vBlank Wait with $2002?

Post by tokumaru »

Bregalad wrote:For a menu I wouldn't bother to miss frames.
Unless you have music/sound, right?
User avatar
rainwarrior
Posts: 8737
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Best vBlank Wait with $2002?

Post by rainwarrior »

If you are concerned about the missed frames, you can dramatically decrease their frequency by adding more cycles to your wait loop.

Code: Select all

; 7-cycle loop has 1/7 chance of waiting an extra frame
:
    bit $2002
    bpl :-

; 13-cycle loop has 1/13 chance of waiting an extra frame
:
    nop
    nop
    nop
    bit $2002
    bpl :-
Like, the naive loop has 14% slowdown because of the missed frames, but every cycle you add to the loop decreases your chances. If your loop had 100 cycles in it (and this is not unreasonable to do), it would go down to 1% slowdown.
User avatar
FARID
Posts: 499
Joined: Wed Apr 07, 2010 1:14 am
Location: Iran
Contact:

Re: Best vBlank Wait with $2002?

Post by FARID »

Thanks for everyone for the great info.
So BIT $2002 clears Negative sign, and as a result BMI will never branch, so it is useless.
But what about the BIT $2002, I feel that it is needed for skipping any halfway vblank periods, no?

Image
User avatar
rainwarrior
Posts: 8737
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Best vBlank Wait with $2002?

Post by rainwarrior »

Yes, an extra BIT $2002 before you enter your wait loop will clear the bit if you are already within vblank. Very useful if you need to avoid accidentally exiting the wait loop in mid-vblank (but not important if you don't).
Post Reply