It is currently Mon Dec 10, 2018 8:25 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 27 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: NMI vs. Vblank???
PostPosted: Mon May 15, 2006 4:21 am 
Offline
User avatar

Joined: Sun Mar 19, 2006 12:37 am
Posts: 223
Location: San ANto, TX
What is the difference between these two?
How do they relate?
What can you use them for?

What is Rendering?

Is NMI where all the sprite action and scrolling occur?

I think after getting hardcore ill write my own tutorials and documentation for the NES world.


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 15, 2006 5:34 am 
Offline

Joined: Sun May 14, 2006 10:26 am
Posts: 48
Location: Norway
The NMI-interrupt is triggered by the PPU when VBlank occurs. The CPU then push the PC and status registers on stack, and jumps to the NMI-routine that you give the adress to in $FFFA (correct me if any of this is wrong). The code in the NMI section should always end with a RTI instruction that makes the CPU pop back PC and status register, and continue where it had come when the NMI was triggered.

In the NMI-code, you will probably do all the stuff that has to be done each VBlank (50 / 60 times per second), like writing to VRAM (since you can't write to VRAM when the PPU are writing on the screen).


Top
 Profile  
 
 Post subject: Re: NMI vs. Vblank???
PostPosted: Mon May 15, 2006 6:37 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1440
nineTENdo wrote:
What is the difference between these two?
How do they relate?
What can you use them for?


VBlank is what happens once every ~1/60th of a second. NMI is an interrupt that happens at each VBlank if you enable it.

nineTENdo wrote:
What is Rendering?

I think after getting hardcore ill write my own tutorials and documentation for the NES world.


If you don't know what rendering is, then it'll probably be quite a while before you're qualified to write tutorials or documentation.

Also, with respect to your recent topic names, only one question mark is used when denoting a question.

_________________
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 15, 2006 10:18 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7599
Location: Chexbres, VD, Switzerland
That's exactly what I was saying in the other topic. Most tutorials doesn't insist too much on that very important aspect of NES programming that is rendering and timing.
Most tutorials just mention that NMI is happening 60 times per second if you enable them, and doesn't mention correctly what is VBlank, its relation with the screen rendering, why it is the base of timing in all NES games, that the frequency slows down in PAL systems, that you cannot write to the PPU outside of VBlank, that VBlank is about 10% of the frame and that means all updating should be here, etc, etc....
Everyone says that on the boards, but there is nothing in tutorials.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 15, 2006 2:22 pm 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
Quote:
Most tutorials just mention that NMI is happening 60 times per second if you enable them, and doesn't mention correctly what is VBlank, its relation with the screen rendering, why it is the base of timing in all NES games, that the frequency slows down in PAL systems, that you cannot write to the PPU outside of VBlank, that VBlank is about 10% of the frame and that means all updating should be here, etc, etc....
Everyone says that on the boards, but there is nothing in tutorials.


And that's why. Everyone wastes time posting well-worded answers in the forums, only to be lost in the mess over time. Rather than benefiting every single person looking for that information in the future, it only benefits a few. Want to work in a group and intentionally design some good documentation?


Top
 Profile  
 
 Post subject: Re: NMI vs. Vblank???
PostPosted: Mon May 15, 2006 7:37 pm 
Offline
User avatar

Joined: Sun Mar 19, 2006 12:37 am
Posts: 223
Location: San ANto, TX
Quietust wrote:
NMI is an interrupt that happens at each VBlank if you enable it.



Why would you want to enable it is want i dont understand. What im thinking what happens is that you mainly use them when making demos that sprite action is happening and scrolling action is happening. Take for example a sprite moving back and forth on the screen. It moves 20 steps.
Vblank,Step 1, Vblank, Step 2, Vblank, Step 3,Vblank...Step 20.

The NMI is the non maskable interrupt (sprite) that happen at the end of vblank that moves on the screen and is updated by the vblank each move.

Thats what im thinking is happening.


Top
 Profile  
 
 Post subject: Re: NMI vs. Vblank???
PostPosted: Mon May 15, 2006 7:51 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1849
nineTENdo wrote:
Why would you want to enable it is want i dont understand.


Two reasons:

1) So you can be notified when VBlank starts. This is important because VBlank is the only time that you can draw things to the nametables, palettes, or update sprites without having to shut off the screen or disrupt the picture being displayed to the player.

2) A steady framerate of 60 fps is how you time your game. You can't just run the game as fast as the code will execute, or else the game will fly by way too fast for the user to react to it. Plus it will move faster or slower depending on how much work is being done, causing an inconsistent framerate for the player, making the game very awkward to play.


Quote:
Take for example a sprite moving back and forth on the screen. It moves 20 steps.
Vblank,Step 1, Vblank, Step 2, Vblank, Step 3,Vblank...Step 20.


EXACTLY. That sprite would be moving 1 step (let's say 1 pixel) per frame. It'll produce a constant speed for the sprite. You'll want to do this in games, too, like have the screen scroll at a constant rate, or have the player walk at a constant rate.

If you want to have the player move 2 pixels per frame, then you need to be notified at every frame so that you know when to move the player a little more. The NMI is what notifies you that a new frame is starting.

Quote:
The NMI is the non maskable interrupt (sprite) that happen at the end of vblank that moves on the screen and is updated by the vblank each move.


No no. NMI is not a sprite. It has nothing to do with sprites. An NMI is what you said... a "non maskable interrupt". "Interrupt" meaning that all it does is interrupt your code and make you jump somewhere else. That's how you know that a new frame has started, when your program gets pulled to a different area of code.

Also -- NMI happens at the START of VBlank... not at the end.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 1:49 pm 
Offline
User avatar

Joined: Sun Mar 19, 2006 12:37 am
Posts: 223
Location: San ANto, TX
Hello Everyone,
I gotta new question about the STACK and the NMI. Are NMI routines carried out in the stack. Ive seen alot Push, Pull carried out in NMI routines before and after the code within the NMI. How does this work? Any Helpful tips? Also ive seen that on reset many people Set the stack at #$FF. Do they do this so it will start at the beginning "00" upon exection of the NMI code.

Thanks in Advance,
EL


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 2:15 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1849
A stack is a programming concept which stores variables in "FILO" (First In, Last Out) order.

Imagine, if you would, a stack of plates. You can only access the top plate in the stack, to reach the plate below it, you must first remove the top plate so that the plate below it is the new top.

A programming stack works in such a fashion. Numbers are "pushed" onto the stack (like adding a new plate on top), and then can later be "pulled" off the stack (like taking the top plate off). When you pull from the stack, you will receive the number most recently pushed.

To demonstrate this, here's some examples with PHA, and PLA. If you're unfamiliar with these instructions, PHA just pushes the value in A onto the stack, and PLA pulls the top value off the stack and puts it in A.

Code:
; assume for this example, that here, the stack is empty:
; Stack -> [empty]


LDA #$20
PHA      ; push $20 onto the stack

; Stack -> $20

LDA #$15
PHA

; Stack -> $15  (top)
;          $20  (bottom)

LDA #$3F
PHA

; Stack -> $3F
;          $15
;          $20  (bottom)

LDA #$00  ; fill A with garbage
PLA          ; pull from the stack, put in A

; Stack -> $15  (top)
;          $20  (bottom)
;
; A is now $3F -- the value pulled from the top of the stack
;  though it was briefly set to $00 -- I only did that to show that PLA
;  will change the value in A.  After that PLA, A will no longer be $00

PLA

; Stack -> $20  (top & bottom)
;
; A is now $15


Interrupts (NMI, IRQ), automatically push the old PC and status flags to the stack (so that when you RTI, status flags are restored to how they were before the NMI). However, A, X, and Y are NOT automatically pushed, so they will retain their values through an interrupt. This can be fatal if an NMI occurs during some calculations:

Code:
somecode:
  CLC
  LDA #$10
  ADC #$10
  STA $00
  RTS

nmi:
  LDA #$00
  RTI


if you look at 'somecode', you'll see that it will add $10 and $10 together, then store the result ($20) at address $00.

BUT! What happens if the NMI occurs right between that LDA and ADC command! The CPU will do the following:

Code:
  CLC
  LDA #$10

--  NMI OCCURING, jump to NMI code  --

  LDA #$00
  RTI

--  RTI returns to area before NMI occured, continue with original code --

  ADC #$10
  STA $00
  RTS


now, instead of adding $10 and $10 together, it's actually adding $00 and $10 together!

Because of this it's common practice for games to back up A X and Y in an interrupt, then restore them before RTI. This way A X and Y will not be changed by the interrupt.

You've probably seen this code:

Code:
nmi:
  PHA   ; push A onto the stack (back it up)

  TXA
  PHA   ; push X onto the stack

  TYA
  PHA   ; push Y onto the stack


;  blah blah, do NMI stuff here

  PLA
  TAY   ; pull Y off the stack (restore the backed-up version)

  PLA
  TAX   ; pull X off the stack

  PLA   ; pull A off the stack

  RTI



As for why games set the stack pointer to $FF at startup -- this is due to the stack being "upside down" and games want the bottom of the stack to start at the VERY bottom to allow for the most stack space possible. I'm too lazy/tired to explain it any further than this, maybe someone else will field this part.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 2:17 pm 
Offline

Joined: Sat May 13, 2006 1:05 pm
Posts: 76
Location: USA
Disch wrote:
A stack is a programming concept which stores variables in "FILO" (First In, Last Out) order.

BTW, the abbreviation normally used is LIFO (Last In, First Out).

_________________
This signature intentionally contains no text other than this sentence.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 2:20 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1849
I've seen both, but yeah that is clearer.

I actually mistakenly typed FIFO at first, then realized that wasn't right. I guess the change to FILO was just more instinctive, even though it would have been just as easy to change to LIFO.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 2:30 pm 
Offline
User avatar

Joined: Sun Mar 19, 2006 12:37 am
Posts: 223
Location: San ANto, TX
Disch wrote:

As for why games set the stack pointer to $FF at startup -- this is due to the stack being "upside down" and games want the bottom of the stack to start at the VERY bottom to allow for the most stack space possible.


So is starts $FF and goes to $00?

By the way thanks for the quick and lengthy reply. I appreciate it very much:)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 4:12 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1849
nineTENdo wrote:
So is starts $FF and goes to $00?


Yes. Not FF->00, but rather FF->FE->FD->...->01->00

If the Stack Pointer (hereon: "SP") is $FF, pushing a value to the stack will change SP to $FE. Pushing another value decreases SP again and makes it $FD. Pulling would increase it.

The stack lies in RAM on the $01xx page. The top of the stack is determined by SP -- if SP is $E4, then the top of the stack is $01E4 (here, when I say "top", I mean the space which is to receive the next pushed value). When SP is $FF it typically means the stack is empty -- hence why many games reset SP to that on startup.

Quote:
By the way thanks for the quick and lengthy reply. I appreciate it very much:)


No prob ^^


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 8:44 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20851
Location: NE Indiana, USA (NTSC)
nineTENdo wrote:
So [the 6502 stack] starts $FF and goes to $00?

Yes, it starts at $FF and grows toward $00. It goes through $FE, $FD, $FC, $FB, $FA, etc., with each push. A 'PHA' or 'PHP' is one push, a 'JSR' two pushes, and a 'BRK' or interrupt three pushes. Many games never push the stack pointer deeper than $C0, meaning they can use the rest of the memory normally used by the stack for other purposes. (The stack lives in addresses $0100 through $01FF of CPU memory.)

Quote:
By the way thanks for the quick and lengthy reply. I appreciate it very much:)

At least it's easier than having only the donknotts clone to talk to.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 28, 2006 3:05 pm 
Offline

Joined: Mon Mar 06, 2006 3:42 pm
Posts: 94
Location: Montreal, canada
The point of using the stack is that you don't have to know the exact address where your values are being stored -- it might even be different for different executions of the same code, under different circumstances. The stack pointer register (S) keeps track of the current "top" of the stack as you push or pop values.

The important thing about using the stack is that if you push 3 values---A then B and then C---and then try to pop 3 values, you know you will get the values C, B and A back in that order. It doesn't matter exactly where they were stored (unless you try to store too many and run out of space!)

Of course the stack abstraction is just that, a useful abstraction. You can still access the stack memory addresses with normal instructions if you know the address. But most of the time you won't want to know it.

So a subroutine call (JSR) works by pushing two bytes (the return address) and then changing the PC to the new address. When you return with an RTS or whatever, it will pop two bytes and set the PC back to that address, "return"ing you to the next instruction right after the JSR.

An "interrupt" is a hardware event that causes the CPU to automatically push its old PC (and perhaps other info, such as flags? it varies for different processor types, but the basic idea is the same) and then jump to a new address for handling the interrupt. When you return from the interrupt (with e.g. an RTI instruction) it will pop those same bytes that were pushed when the interrupt occurred, and your program can resume doing whatever it was doing before it was "interrupted". It won't even know the difference (unless you do something in your interrupt handler which affects the state of the main program).


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 27 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group