02. What’s a v-blank?

Writing to the screen with rendering on.

If you used the vram_adr() or vram_put() functions while the screen is ON, there is 92% chance that you will write garbage on the screen and misalign the scroll.

Why this happens, basically, the PPU can only do 1 thing at a time, and while the screen is running, it is busy reading data from the VRAM and sending it to output to your TV, 92% of the time.

It goes line by line, pixel by pixel, calculating which color to write for each dot. Here’s a nice slow motion camera watching SMB1 (at about 2:14).

Once it reaches the bottom, it waits a short period. That’s called the vertical blank period (v-blank). This is the only time the PPU is not busy, and we can safely write tiles to the screen during this time (not too many).

Also, we have turned NMI interrupts on (this bit in register 2000, 1xxx xxxx, somewhere in the startup code in crt0.s.). At the beginning of v-blank, the PPU generates a signal (NMI) which halts CPU execution, and it jumps to the nmi code in neslib.s, and executes that during the v-blank period.

We know that it will go to the nmi code (asm, in neslib.s) during this period, so we know that it is safe to write to the PPU during this time (well, a few bytes). We can use this to our advantage, because if we are playing a game, and you turn the screen off, write to the screen, then turn it back on…the screen will flicker black during that time, which is a bit annoying. So, we want to keep the screen on, and we want to write to the PPU during v-blank.

So, we will write to a buffer during rendering, and the nmi code will transfer it to the PPU automatically.

set_vram_update(address of data), to pass the address of our data or buffer to the neslib.

I have made some examples of data that the automated system can read. You can either send it 1 byte, or a contiguous set of data (tiles).

SINGLE BYTE
address high byte
address low byte
data (tile #)
EOF

MSB(NTADR_A(18,5)),
LSB(NTADR_A(18,5)),
‘B’,
NT_UPD_EOF

.

CONTIGUOUS DATA
address high byte / update horizontal
address low byte
# of bytes
data
EOF

MSB(NTADR_A(10,14))|NT_UPD_HORZ,
LSB(NTADR_A(10,14)),
12, // length of write
‘H’,
‘E’,
‘L’,
‘L’,
‘O’,
‘ ‘,
‘W’,
‘O’,
‘R’,
‘L’,
‘D’,
‘!’,
NT_UPD_EOF

(optional, update vertical, NT_UPD_VERT)

You can stack multiple writes into one frame, if you strip the EOF. See hello2.c below.

There is a limit as to how many bytes you can buffer…

About 31 single bytes, or 74 contiguous bytes, or mixed, somewhere in between. But this is fuzzy, you should err on less than this. If you never adjust the palette, you can get more (maybe 40 single, 97 contiguous) safely per frame.

Note, the ppu will rewrite the same bytes over and over, every frame, until the buffer changes.

You can turn it off with
set_vram_update (NULL)

.

02_hello2

https://github.com/nesdoug/02_Hello2/blob/master/hello2.c

https://github.com/nesdoug/02_Hello2

.

I’ve noticed that nearly nobody is using this function, nor a VRAM buffer.

I think it’s because it’s awkward to construct a VRAM update on the fly. So, I wrote a whole support library to make this a piece of cake.

Next time…

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s