This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

2 vblank/nmi questions

2 vblank/nmi questions
by on (#187998)
So the NMI is just a piece of code that automatically triggers at vblank right? If thats the case I have 2 questions:

1: Does that mean normal asm code runs asynchronously as the last or current frame is being drawn? Otherwise, wouldn't it only be able to be running during vblank as that's when it's not drawing?

2: If so, how does it stay in sync? What if the code is not completed when it comes time to start drawing the next frame? If the code is half done wouldn't it mean that only about half of the sprites would appear or am I wrong?
Re: 2 vblank/nmi questions
by on (#187999)
It's not asynchronous execution. There's only one CPU. It's an interrupt.

Execution stops, the program counter and status flags are pushed to the stack, and it jumps to the NMI code. When the RTI (return from interrupt) instruction is hit, it recovers that information from the stack and resumes.

Yes, NMI signals at the beginning of vblank, and the point is to run code during vblank that needs to mess with the PPU while it's not engaged in drawing the screen. (Trying to do so while it's rendering has unpleasant results.)
Re: 2 vblank/nmi questions
by on (#188001)
What I meant is does the CPU run while the PPU draws the frame or what? Because the way I know lots of newer games work is by first taking input then doing game logic then rendering and then repeating that as fast as possible, the idea of cpu beginning execution when something on the gpu/ppu happens is foreign to me, so it is hard for me to understand the order things are done in.
Re: 2 vblank/nmi questions
by on (#188002)
Yes. The PPU is idle during vblank (or if turned off), and otherwise it's occupied drawing the frame.

The PPU generates the NMI signal at the start of vblank (if the signal is turned on), and the CPU will be interrupted at that time and start executing its NMI handler code.

The PPU does not run the NMI code, it doesn't have software of its own, it just generates the video signal.
Re: 2 vblank/nmi questions
by on (#188003)
So if the cpu runs normal code while the ppu renders then how does it stay in sync? For example if only half of all "objects" or sprites are updated to their new positions in the cpu and then it comes time for the PPU to collect sprites to draw them then will half of the sprites be at their new position and half at the old position in the frame, or something else will happen? Or is that just not possible?
Re: 2 vblank/nmi questions
by on (#188004)
It normally goes like this:

1 - Main code processes game logic, computes new sprite positions, etc., then waits for the NMI;
2 - Vblank starts, the NMI fires and interrupts whatever the CPU is doing, then blasts all buffered video updates to the PPU;
3 - NMI handler gives control back to the main code, which detects that an NMI happened and proceeds to process the next frame.

Now, it's entirely possible that an NMI fires while step #1 hasn't finished yet, meaning that it can't reliably perform any graphical updates. This is normally detected by the NMI handler through the use of a flag, that the main code sets when it finishes processing each frame. If the flag isn't set, the NMI handler restricts itself to performing high priority tasks that aren't supposed to lag, such as updating the audio and setting up raster effects.

When the NMI handler is finished, control is transferred back to the main code, which then finishes the frame it couldn't finish before. It will set the flag indicating that the game logic has been fully processed and only when the next NMI fires will the video updates finally happen. This is why games lag when the CPU is under heavy load.

EDIT: Another important point that might not be clear: the CPU and the PPU run in parallel. The PPU is programmed (a program "embedded in the chip" that you can't change) to draw an image, pixel by pixel, using information from various parts of its memory (pattern, name and attribute tables, OAM and palette RAM), then "rest" for the duration of vblank, and repeat this process over and over. If the contents of the PPU memory don't change, neither does the picture it generates. So, to answer your question, synchronization of maintained by not changing the PPU memory at all if the CPU couldn't finish computing all the changes in time, effectively causing the PPU to draw the exact same picture again, which results in slowdown.
Re: 2 vblank/nmi questions
by on (#188008)
ittyBittyByte wrote:
So if the cpu runs normal code while the ppu renders then how does it stay in sync?

The PPU sends the NMI signal to the CPU every vblank. That's what's used to synchronize the PPU and the CPU. On the CPU, that signal gets to the software in the form of an interrupt, and it's the software's job to do things with appropriate timing in response.

Edit: sorry if I'm repeating myself. Maybe tokumaru's answer was what you're really looking for.
Re: 2 vblank/nmi questions
by on (#188371)
What happens if NMI code doesn't finish in time when the PPU actually starts to draw the next frame?
Re: 2 vblank/nmi questions
by on (#188373)
If you're still using $2006/7, the picture will get corrupted. The PPU will try to read stuff from VRAM/VROM while you're still manipulating the address register so it will end up fetching the wrong data and drawing garbage on the screen. If you're not using any of the PPU registers anymore, and the scroll has already been set, the NMI can safely perform other tasks (like audio or input, if you wish) as long as it finishes before the next NMI fires.