How do I use Vblank?

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

User avatar
tokumaru
Posts: 11749
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How do I use Vblank?

Post by tokumaru » Tue Mar 21, 2017 1:11 pm

DementedPurple wrote:I'm afraid that my Vblank my be too short
That's not a problem, don't worry.
and it'll finish early and go to the part where it will read the controllers and then you will be still pressing the right arrow and the x-position will be increasing too fast.
People will normally hold buttons for several frames (specially if it's a direction button, you have to hold them if you want to walk around!), so this is expected. What you have to do is structure your program so that only one cycle of game logic + PPU updates happens per frame. This will guarantee that your game runs at 60Hz (or 50 for PAL) and all the physics constants can be adjusted for that speed. What you absolutely can't do is read the controllers and react to input several times per frame, that'll sure make things go faster than they should, but if you're doing it only once per frame, it doesn't really matter *when* in the frame you're doing it, because 1/60th of a second is too little of a window for humans to be able to analyze what happens inside it. The vertical blank lasts about 20 scanlines, which is about 1.3 milliseconds, so it really doesn't matter.

User avatar
dougeff
Posts: 2710
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: How do I use Vblank?

Post by dougeff » Tue Mar 21, 2017 1:12 pm

I think, what tokumaru and tepples mean, is...for a new programmer, you aren't going to do anything that requires timing something mid-frame.

I think a sprite zero hit at the top left would be the easiest way to time when the frame is on scanline 1.

You could also do an MMC3 scanline IRQ count of 1 scanlines.

Neither one do you need, until much later, when you know much more about screen rendering.
nesdoug.com -- blog/tutorial on programming for the NES

User avatar
tokumaru
Posts: 11749
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How do I use Vblank?

Post by tokumaru » Tue Mar 21, 2017 1:19 pm

I've looked at your code from the other thread and yes, you're running the game logic over and over in the same frame, causing things to move too fast. This has nothing to do with a short vblank handler. You jump to a label called "wait" but... there's no waiting at all, the program simply reads the controller again and performs the movement again, over and over, without ever waiting for the next frame to start.

What you need to do is set up a way to make your program wait for the vblank handler to run, so it knows that one frame is complete and it can proceed to processing the next one. The simplest way to do this is to increment a counter anywhere in your NMI handler:

Code: Select all

INC FrameCounter
And wait for this counter to change in your main loop:

Code: Select all

  LDA FrameCounter
Wait:
  CMP FrameCounter
  BEQ Wait
Another thing you're not doing is backing up registers before you use them in the NMI handler. Remember, this code is going to interrupt the main loop, and if you change the registers without restoring them to their original values, when you return from the NMI the program will not be able to resume whatever it was doing, resulting in bugs and possibly even crashes. Most people have their NMI handlers save and restore all 3 registers, like this:

Code: Select all

NMI:
  PHA ;save A
  TXA
  PHA ;save X
  TYA
  PHA ;save Y
  ;(NMI logic here)
  PLA ;restore Y
  TAY
  PLA ;restore X
  TAX
  PLA ;restore A
  RTI
EDIT: Corrected mistake pointed out by tepples.
Last edited by tokumaru on Tue Mar 21, 2017 3:30 pm, edited 1 time in total.

tepples
Posts: 22014
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do I use Vblank?

Post by tepples » Tue Mar 21, 2017 2:45 pm

tokumaru wrote:And wait for this counter to change in your main loop:

Code: Select all

Wait:
  LDA FrameCounter
  CMP FrameCounter
  BEQ Wait
This will catch the change only if NMI happens between LDA and CMP, a roughly 1 in 3 chance if FrameCounter is in zero page.

A more reliable loop loads the previous frame counter value only once and then waits for it to change:

Code: Select all

  LDA FrameCounter
Wait:
  CMP FrameCounter
  BEQ Wait

User avatar
tokumaru
Posts: 11749
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How do I use Vblank?

Post by tokumaru » Tue Mar 21, 2017 3:29 pm

Oh yeah, I misplaced the label. Sorry about that.

Post Reply