Page 1 of 1

Screen flashes garbage chars when I update background tiles

Posted: Tue Aug 21, 2018 11:36 pm
by TriForced
I'm following the nerdy nights series. I created / finished the pong game. When the game finishes, I display GAME OVER using background tiles.
The user can press Start to restart the game. When they do, I overwrite the GAME OVER tiles with a solid tile (ie: no letter).
However, for some reason, the screen briefly displays a bunch of zeros (Tile #$00) on half the screen before looking normal again.

I'm new to NES programming (but not to programming in general).
Has anyone else seen this before?

Thanks!

TriForced

Re: Screen flashes garbage chars when I update background ti

Posted: Wed Aug 22, 2018 12:17 am
by tokumaru
It could be that you're writing to VRAM while the PPU is trying to use that same VRAM to render the image, and the VRAM can't be written to and read from at the same time, so you get visual glitches.

Whenever you have to redraw large portions of the screen, an operation that takes a lot of time, you have to disable rendering so the PPU won't touch the video memory, and you have full access to it. When you're done, turn rendering back on.

Small updates can be done with rendering on, as long as they're done during vblank, a time during which the PPU doesn't touch VRAM. That's how games that scroll work, they draw only the new parts of the background right before they scroll into view.

Re: Screen flashes garbage chars when I update background ti

Posted: Wed Aug 22, 2018 12:38 am
by TriForced
That worked tokumaru; thanks for the response!
Out of curiosity: how many background tiles can I update without having to disable rendering?

Re: Screen flashes garbage chars when I update background ti

Posted: Wed Aug 22, 2018 1:02 am
by tokumaru
In NTSC, vblank lasts 20 scanlines, or 2273 CPU cycles. Different types of loops will execute at different speeds, so there's not a definitive answer to your question... Writing to VRAM can be as fast as 6 cycles per byte (example A), as slow as 17 cycles per byte (example B), or even slower.

Example A:

Code: Select all

  lda #$00 ;2 cycles
  sta $2007 ;4 cycles
  lda #$05
  sta $2007
  (...)
Example B:

Code: Select all

  ldy Start
CopyByte:
  lda (Pointer), y ;5 cycles
  sta $2007 ;4 cycles
  iny ;2 cycles
  cpy End ;3 cycles
  bne CopyByte ;3 cycles
You also have to consider all the other operations that may take place during vblank, such as the sprite DMA, setting the scroll, and so on. In most cases, you should be able to update at least 100 bytes of VRAM, but you can do better than that with more optimized code.

Avoid single-byte loops like in example B like the plague if you're going for speed! Avoid indirect addressing (keep your update buffer under 256 bytes and use absolute/indexed addressing). If using indices/counters, count down instead of up and avoid the CPX/CPY. Unroll loops whenever possible, even if partially.

Re: Screen flashes garbage chars when I update background ti

Posted: Wed Aug 22, 2018 11:23 am
by koitsu
Another possibility isn't the amount of data being transferred during NMI/VBlank, but that PPU scroll aren't "reset" before the start of the next drawing cycle, e.g. lda #$00 / sta $2005 / sta $2005 may be needed at end of NMI routine to ensure "junk" isn't printed on the screen when the PPU begins drawing again. Most recent thread we have about that: viewtopic.php?f=10&t=17680

Re: Screen flashes garbage chars when I update background ti

Posted: Wed Aug 22, 2018 12:09 pm
by tokumaru
That's right. To completely avoid these kinds of glitches, you have to be sure to only manipulate the PPU during vblank (even turning rendering on/off should be done during vblank to avoid the drawing of misaligned partial frames), and always set the scroll after you're done manipulating the PPU but before rendering starts.

Re: Screen flashes garbage chars when I update background ti

Posted: Wed Aug 22, 2018 12:31 pm
by Bregalad
koitsu wrote:Another possibility isn't the amount of data being transferred during NMI/VBlank, but that PPU scroll aren't "reset" before the start of the next drawing cycle, e.g. lda #$00 / sta $2005 / sta $2005 may be needed at end of NMI routine to ensure "junk" isn't printed on the screen when the PPU begins drawing again
*cough cough* Final Fantasy II *cough cough*