Is it even possible?
The title screen in my game uses a light green color for color #0, but there are large bands of dark green running across the top and bottom sections.
When I reset the game, the entire screen flashes light green for exactly one frame. Since the dark green bands are drawn the very next frame, the contrast makes the flash quite noticeable.
Ideally, I'd like to display a black screen (or possibly a dark green screen) for that first frame after resetting. But it appears that the PPU uses whatever color happens to reside in color #0 at that time. I tried initializing the palette as soon as humanly possible in the reset routine, but that didn't work.
So, is it possible to set the display color for the very first frame after reset? And if so, how?
I don't think it's possible. Even if it is, I honestly wouldn't worry about it...a lot of commercial games display the wrong color much longer than one frame.
After reset (well I mean after waiting the initial 2 VBlanks et ceatera), just set the palette to black, and after you get a stable setup with rendering and NMI on, fade it in to whathever you want to be on screen.
Personally I always use black for BG color for some reason, but I agree in some cases it may be desirable to have another color.
SecretServiceDude, I think blargg did a test of the PPU and apparently all writes to it are ignored for one full frame after reset. Check the wiki or with blargg.
If it's not possible, I can live with that. I just didn't want to give up without asking first.
I suppose the ppu unwritable-during-warmup issue would mean you have no control on the content of palette ram for the first frame.
Ooh! Maybe this will work for you, as yesterday I went through and rewrote how I handle palettes, so I can easily change the colors in my main loop while not having to worry about turning off the PPU and what-not. I finally figured out that it's possible to have some space set aside in RAM for the palette, and pull that in during every NMI. Maybe you could use the same sort of thing in this way: Have the first time you pull in a 'palette' be all $0f for your black, and the next frame write the actual palette to RAM, which will then be pulled in by the NMI.
If you end up using this method, just make sure you set $2006 back to it's original state before the NMI happened, which you can do with some reserved bytes.
Also it seems strange, but I believe the color shown for the background is actually the one being pointed to by $2006. So if light green is the last color written to your palette initially, I'm thinking if the screen is off and you do nothing else with $2006/$2007 for a while, that will be the background color during that time.
I've done all kinds of weird stuff with the palettes in tests, trying to get more colors, and I learned that if you want a 'clean' palette update that you need to be in vblank or hblank. So the way Roth said is best, it's what I do also, just keep a buffer and blast it into VRAM on every NMI. It's what a lot (most?) of commercial games do too (I've seen many NMI routines while ripping NSFs, heheh
).
Yeah that method is great and almost compulary. I also use a flag so the update is optionnal, because sometimes I prefer having other PPU updates and not the palette during the VBlank time.
As long as you set the PPU adress to $3f00 imediately after writing to the palette you should be fine. (you're sure the background color displayed is the desired one).
If I'm reading my notes/the Wiki right, you can write to $2006 and $2007 immediately after power, so you can set the screen to black immediately at power. Something like this should work:
Code:
lda #$3F ; VADDR = $3F00
sta $2006
lda #$00
sta $2006
lda #$0F ; set first entry to black
sta $2007
lda #0 ; VADDR = 0
sta $2006
sta $2006
blargg wrote:
If I'm reading my notes/the Wiki right, you can write to $2006 and $2007 immediately after power, so you can set the screen to black immediately at power. Something like this should work:
Code:
lda #$3F ; VADDR = $3F00
sta $2006
lda #$00
sta $2006
lda #$0F ; set first entry to black
sta $2007
lda #0 ; VADDR = 0
sta $2006
sta $2006
I thought that you said PPU writes were ignored for the first frame?
blargg wrote:
If I'm reading my notes/the Wiki right, you can write to $2006 and $2007 immediately after power, so you can set the screen to black immediately at power. Something like this should work:
Code:
lda #$3F ; VADDR = $3F00
sta $2006
lda #$00
sta $2006
lda #$0F ; set first entry to black
sta $2007
lda #0 ; VADDR = 0
sta $2006
sta $2006
I gave your code a shot, but unfortunately it didn't work.
Out of curiosity, what's the significance of setting the PPU address back to zero? Is that considered good form?
I thought that you said PPU writes were ignored for the first frame?
yeah what's up with that.
@servicedude: I remember reading that if the ppu address lies in the palette ram, and the screen is disabled, it displays the color pointed to in palette ram. So that would ensure that the display color is the one that has just been written (col 0).
Players will be looking at the NES's power button, not the TV, for at least the first five frames that your game is turned on.
tepples wrote:
Players will be looking at the NES's power button, not the TV, for at least the first five frames that your game is turned on.
That's true for the operator of the power button; however, if there's a crowd of spectators, I want to deliver the most professional presentation possible. That one frame could make the difference between a fun party and a trip to the emergency room following an epileptic seizure.
But in this particular case, it seems like a no-go. Oh well, no biggie.
WedNESday wrote:
I thought that you said PPU writes were ignored for the first frame?
- Not every single PPU write, dude. Do you know the PPU test ROMs regarding this behaviour?
WedNESday wrote:
I thought that you said PPU writes were ignored for the first frame?
I may have, but later found that it's only after pressing the reset button that they are ignored, or if powering up less than 20 seconds after having last been powered up, not after a "cold" powerup. See the
Wiki page about PPU powerup.
SecretServiceDude wrote:
I gave your code a shot, but unfortunately it didn't work.
Did you try just on emulators? They might not be implementing the correct behavior (as you can see, most people just thought all writes were ignored for a while). Let us know after you try it on hardware.
Quote:
Out of curiosity, what's the significance of setting the PPU address back to zero? Is that considered good form?
In that piece of code, it was probably to get the PPU address register away from the palette area. When it's within the palette area and rendering is off, the color pointed by it gets rendered instead of color 0. If the address register is not pointing at any color, color 0 gets drawn.
Some people, however, insist on resetting the scroll by writing to $2006, even though $2005 and $2000 are enough to do it.
tepples wrote:
Players will be looking at the NES's power button, not the TV, for at least the first five frames that your game is turned on.
Don't bet on it...
Quote:
Players will be looking at the NES's power button, not the TV, for at least the first five frames that your game is turned on.
Even worse, when I play games I usually plug the game in, power the console on, power the TV on and then spend some time so that channel '4' is selected (other channels are snow), so the player isn't likely to watch the screen for 20 seconds after a cold reset.
This is different for a warm reset, tough.
Bregalad wrote:
Even worse, when I play games I usually plug the game in, power the console on, power the TV on and then spend some time so that channel '4' is selected (other channels are snow), so the player isn't likely to watch the screen for 20 seconds after a cold reset.
So, by "the player" you mean you, basically? =)
I'm very different. I guess I have some sort of Obsessive-Compulsive Disorder... By the time I turn the console on, all cables must be already connected and the TV set to the proper input. Then I usually position my hand over the button but will not press it until I'm looking at the screen again. I want to know everything that's going on, and if the game does something weird at power-on I'll want to see it.