News:

11 March 2016 - Forum Rules

Main Menu

PPU manipulation "during V-Blank"

Started by Trax, January 20, 2019, 06:29:20 PM

Previous topic - Next topic

Trax

So, I'm trying to manipulate the PPU to have animated palettes, like a pulsing light, or a waterfall. The way to go is to write the PPU address in 2006, in two writes, and then write the data with the 2007 port. Fine. According to basic knowledge of the PPU, we always read "you should never write to the PPU outside of V-Blank". What puzzles me is, what exactly is V-Blank? What exactly is NOT V-Blank? Isn't anything within a NMI call V-Blank by definition?

So, by that logic, pretty much any code in any ROM is executed during V-Blank. That said, why is it that any time, and any place in the code I try to add my own code that manipulates the PPU through 2007, I get a catastrophic result of a mismash of glitchy pixels on screen? I even tried to bridge exactly at the same place where the original code does 2007 manipulation, and I still get a glitchy mess. Does anyone has a ANY idea how that works when you hack an existing ROM? Has anyone has done that before?

By the way, I'm trying to do that on the Zelda II ROM. I know the difficulty is increased by the fact that this game uses PPU tricks to have part of the screen scrolling, while the other (the HUD) doesn't.

Disch

#1
Probably should have mentioned this is the NES  =P  But I gathered that from 2006 and Zelda 2.

QuoteWhat puzzles me is, what exactly is V-Blank? What exactly is NOT V-Blank? Isn't anything within a NMI call V-Blank by definition?

To answer your last question first:  no.  NMI is triggered at the start of VBlank, but that doesn't mean any code that runs in it is in VBlank.

VBlank is a period of time.  The NES is constantly rendering frames -- 60 of them per second.  Between each frame is a period of time where the raster gun on the display is resetting for the next frame, and therefore the system is not outputting any video.  This time is "VBlank".  Since there's no video being output, it is safe to mess with video settings.

If you want more detail -- each frame on the NES consists of 262 scanlines.  Each scanline is exactly 113.66667 CPU cycles*... so they all last for a fixed length of time.  The scanlines are broken down as follows (note the number system may be different depending on what emu or doc you're referring to, but this numbering is pretty common):

- scanlines 0 to 239 are "rendered".  This is when the PPU is drawing pixels to the screen.
- scanline 240 is "idle" ... this is REALLY where VBlank starts, but NMI hasn't happened yet
- scanlines 241 to 260 (or -21 to -2 depending on your numbering) is where VBlank officially starts.  NMI triggers at the very start of scanline 241.
- scanline -1 (or 261) is "pre-render"... this is where VBlank has officially ended (no longer safe to access PPU), and the PPU has begun doing work in preparation for rendering the next scanline.


Not counting the idle line, there are 20 scanlines of VBlank.  Each scanline is 113.66667 cycles, meaning you have 2273.3333** cycles of VBlank time.

Note it's a WINDOW OF TIME.  Each instruction that executes consumes some of these cycles (see any 6502 doc for how many cycles each instruction uses).  Once you run out of that time... you are no longer in VBlank... regardless of whether or not you are still in the NMI routine.



* Technically there's one exception to this rule, but don't worry about it.
** Keep in mind there might be some latency between the start of VBlank and the NMI trigger.  And remember the NMI itself consumes 7 cycles, so you probably have closer to 2260 CPU cycles of VBlank time by the time your NMI code starts running.  And to make things worse, games will almost always need to spend vblank time doing a sprite DMA (a write to $4014 to update all on-screen sprites) which consumes a whopping 513 cycles!  So REALLY, you have closer to 1747 cycles.


Quoteand I still get a glitchy mess.

FCEUX tells you what scanline the PPU is currently on, so you can gauge your timing.  Step through your code in the FCEUX debugger and keep an eye on the "Scanline" marker:

https://i.imgur.com/vimpWYj.png    <-  see this image


If the scanline is 240 to 260, you are safely in VBlank.  If it's anything else, you're in the middle of rendering.

Also if it's 260 you are REALLY close to running out of time, as all drawing code should probably be done a bit before VBlank ends.

Bregalad

If you're hacking an existing game you usually don't have to worry about that, and just use already existing routines to alter palettes, nametables or whathever. This is a worry only if you write your own homebrew game, or if you do some really advanced hacking that modifies the NMI routine.

Trax

Thanks Disch, that clears up a lot of questions I had. I'll keep an eye on the scanline value and make sure I'm in the allotted timeframe. If possible, I'll try to use existing mechanisms, like PPU macros, computed later in the code, but only executed when the PPU is ready.

jonk

#4
Quote from: Disch on January 20, 2019, 07:29:05 PM
If you want more detail -- each frame on the NES consists of 262 scanlines.
I've always kept in mind that this is 262.5, reinforced many times by encountering displays which use the half-line at the bottom of the first field before vsync to decide between interlaced or progressive mode of operation. In any case, here's a nice link for the OP that provides a lot of detail: ScienceDirect on Interlaced Scanning. See chapter 14 from digital signal processing: fundamentals and applications.
An equal right to an opinion isn't a right to an equal opinion. -- 1995, me
Saying religion is the source of morality is like saying a squirrel is the source of acorns.  -- 2002, me

Disch

I have no doubt you're right for most things, jonk, but the NES bends NTSC standards a bit.  The actual 2C02 counts for exactly 262 scanlines, and each of them are exactly the same length except for one which alternates between 340 and 341 cycles every other frame to avoid some visual weirdness.  Having a shorter frame might explain why the NES refreshes slightly faster than the NTSC standard  (60.01 Hz vs. 59.94 Hz).

In any case, frame length and timing on the NES has been thoroughly tested and documented so I am pretty confident in saying it's 262 even.

jonk

#6
I don't (and didn't, by the way) doubt your knowledge about the NES. My comment was more a "prod" of sorts to see what you'd add to the picture. Thanks for the clarity about the NES. Excellent!

I was drawing from my experience from developing my own embedded devices using a few I/O pins and some resistors to generate video and some experience making things work well. I learned a few things from "hard knocks" from not fully apprehending how some devices distinguish I from P mode when they receive their signals. (Matters to the fancier, newer displays that "try" to be smart. The old stuff was only I and had no capability for P.) I take your point. Thanks, again! (For me and for others helped by your knowledge and background.)
An equal right to an opinion isn't a right to an equal opinion. -- 1995, me
Saying religion is the source of morality is like saying a squirrel is the source of acorns.  -- 2002, me

Disch

Haha.  Nah I didn't take your comment as a challenge or anything.   :thumbsup:

Admittedly my understanding of NTSC is extremely spotty, and the few things I know about it are exclusive to NES/SNES behavior, so it's cool to see additional info.