Page 1 of 1
loading background tiles mid screen flash
Posted: Sun Feb 20, 2011 6:52 pm
by 8bitmatt
What's going on here? What am I doing wrong? I want the technical explanation.
When loading a different background the screen flashes for a split second showing the top of the new background graphics in the middle of the screen before the new background is completely loaded.
Here's an example rom and source file:
background-flash-example.zip
NESASM syntax.
Press A or B to change between background 1 & 2. Notice there's a slight flicker in the middle of the screen. Or if you hold one of the buttons down the new background graphics will stay in the middle of the screen.
I'm having an identical issue in the pong game I'm developing. When the game state changes and a new background is loaded I see the same mid-screen flash for a split second.
In the pong game:
Toward the top of NMI (after DMA sprite transfer) I jump to a subroutine to check scores. If someone has won I then:
Shut the screen off
Load the "game over" background
Change the game state to "game over"
Turn the screen on
Then it returns from these subroutines to the place it left off in NMI and right after that section is the PPU clean up section of code (like my simple example here). I have a feeling this PPU clean up section of code might be the issue.. is it turning the screen on too soon or something?
Posted: Sun Feb 20, 2011 7:04 pm
by 3gengames
Just looking at your loop how it works, if the game doesn't scroll, you should "create" the next screen on the page that isn't on the screen, then scroll to it in VBlank. I don't have time to look at source but thats what should happen in a non-scrolling game.
Posted: Sun Feb 20, 2011 7:18 pm
by Ian A
In the example file you posted it looks like when someone pushes the button you immediately turn off the screen and disable NMIs, draw the screen and then turn the screen on again when you are finished. Most likely it's turning the screen off in the middle of drawing it, and turning it on when the 'television' is in the middle of drawing the screen as well.
Here's how I'd handle your example.
Set a flag to disable rendering. During the next NMI (when we're not drawing the screen) turn the screen off. This the first thing I do in my NMI. Leave NMIs on.
Draw the screen.
Set a flag to enable rendering. During the next NMI, turn the screen on.
It's difficult to do with you entire game running in your NMI. A quick, but not ideal, fix would be to have a variable you increment every NMI. It might be easier for me to show you an example:
Code: Select all
NMI:
pha ; back up accumulator, since we're gonna mess it up
lda nmiflag ; load our nmi flag. if it's zero, it sets zero flag, we are not in NMI
beq ContinueNMI ; check if zero flag is set, if so branch to continue NMI
pla ; restore accumulator, since we're already in NMI and probably using it
rti ; we are already in NMI, so head back
ContinueNMI:
inc nmiflag ; set a flag saying we are in NMI
; no need to touch $2000
lda screenflag1 ; do we turn the screen off or on? we set this earlier
sta $2001
And pull the accumulator from the stack with pla at the end of your NMI. In a perfect world you'd back up X and Y too, but you aren't touching them in your shortened nmi.
You'd also have to change your forever loop:
Code: Select all
Forever:
lda #00
sta nmiflag ; we're not in nmi so clear flag
JMP Forever ;jump back to Forever, infinite loop
Posted: Sun Feb 20, 2011 7:49 pm
by tokumaru
Like it's been said, you are enabling rendering in the middle of the screen, so the new image starts rendering in the middle of the screen. Wait for the next VBlank before enabling rendering.
Posted: Mon Feb 21, 2011 11:49 am
by 8bitmatt
thanks for the help guys. I get it now.
For future noobs reading this & having similar issues, I found this helpful document by Disch while searching too:
http://nesdev.com/bbs/viewtopic.php?t=5062
Posted: Mon Feb 21, 2011 8:28 pm
by frantik
8bitmatt wrote:thanks for the help guys. I get it now.
For future noobs reading this & having similar issues, I found this helpful document by Disch while searching too:
http://nesdev.com/bbs/viewtopic.php?t=5062
in that doc, the first line of NMI is
Code: Select all
bit $2002 ; clear VBl flag, reset $2005/$2006 toggle
i don''t understand what that is doing.. i thought reading PPUSTATUS at the start of NMI was "bad" (tm)..?
Posted: Mon Feb 21, 2011 8:39 pm
by tepples
Reading PPUSTATUS ($2002) is not bad. On the contrary, it puts the toggle connected to $2005 and $2006 into a known state.
Posted: Mon Feb 21, 2011 8:42 pm
by Kasumi
I believe it's only "bad (tm)" to use $2002 as a way to check if the vblank occurred before starting the main loop, since it's possible to miss frames that way in rare occurrences.
Tepples ninja'd me on why it's good practice at the start of the NMI routine.
Posted: Mon Feb 21, 2011 9:13 pm
by frantik
i read more and i think i understand.. using BIT is just an easy way to read PPUSTATUS without affecting the accumulator, and since we're not checking for NMI it doesnt matter that were reading it at the beginning of NMI
BIT is a weird seemingly multipurpose opcode which until now i didnt understand too well so every time i saw it, i would be confused as to what was happening