PPU powerup/reset behavior
Moderator: Moderators
PPU powerup/reset behavior
I think I've got most of the PPU power/reset behavior and timing determined and verified with test ROMs (so you can test your emulator too). I put the findings on the NesDevWiki. As usual, full ca65 source code included.
ppu_power_reset3.zip
EDIT: added test for $2000 low two bits and updated Wiki and test ROMs. Thanks for the trick, dvdmth.
ppu_power_reset3.zip
EDIT: added test for $2000 low two bits and updated Wiki and test ROMs. Thanks for the trick, dvdmth.
Last edited by blargg on Thu Mar 13, 2008 4:47 pm, edited 2 times in total.
You can use the following $2005/2006 magic to test those two bits:- My devcart is locked to single-screen nametable mirroring, so I can't test the low two bits in $2000.
Code: Select all
bit $2002
lda #0
sta $2005
sta $2005
sta $2005
sta $2006
"Last version was better," says Floyd. "More bugs. Bugs make game fun."
Same here after implementing the ignored writes in my emulator. I extracted the init code from Tiger-Heli and sure enough, it fails to enable NMI often at power on my NES. On further testing, I found that if I power the NES down for several seconds between tests, then it works most of the time. So apparently the VBL flag is usually clear at power if the NES was off for a while, and often set if it was recently on. What's the other game that someone was saying needed the VBL flag set at power?
$2002 power on with $00 instead of $A0:
- Ironsword: locks up at titlescreen with "Ironswor" and no sword in his hands
- Cobra Triangle: locks up when starting game
btw1: I probably don't need to mention that a lot of homebrew stuff fails.
btw2: $2007 read buffer.nes usually succeeds if I leave $2007 read buffer unchanged after reset, instead of setting it to 0
- Ironsword: locks up at titlescreen with "Ironswor" and no sword in his hands
- Cobra Triangle: locks up when starting game
btw1: I probably don't need to mention that a lot of homebrew stuff fails.
btw2: $2007 read buffer.nes usually succeeds if I leave $2007 read buffer unchanged after reset, instead of setting it to 0
Odd. Are you modifying it during rendering? It should only be modified when the 2A03 reads from $2007 (and its mirrors). The test sets PPUADDR to $0010, which is the beginning of a run of $FF bytes, then reads from PPUDATA, which should put $FF into the buffer. Then it goes into an infinite loop, so the buffer should still contain $FF after reset if your emulator isn't clearing it during reset.$2007 read buffer.nes usually succeeds if I leave $2007 read buffer unchanged after reset, instead of setting it to 0
On the hunch that maybe the VBL flag is getting cleared during the first frame, I tried delaying 26000 clocks then reading $2002 after power, and quickly powering off then on several times. I still got $80, so the VBL flag isn't getting cleared before it's next set at ~27384. Oh well.
We need someone with Tiger Heli, Ironsword, and Cobra Triangle (PowerPak won't suffice) to see how often they work when powering up the NES after being off for a while, and after being off for only a couple of seconds. I'm guessing some won't work all the time in these cases. I'm going to see if I can extract the init code from each and test it on my NES.
I found a couple of old threads dealing with this issue "Let's uncover power-up and reset behavior" and "APU Frame IRQ Flag and IRQ Timing".
Last edited by blargg on Thu Mar 13, 2008 11:48 am, edited 2 times in total.
OK, Ironsword doesn't have the problem because the loop that clears APU registers reads the register first since it uses the STA $4000,x addressing mode. So that reads $4015 after the frame IRQ flag has been set. This game should work regardless of the VBL flag at power. Same issue for Cobra Triangle (I checked init code too).

Yes indeed, I need to write one for this. So it's good you had this bug.hap wrote:hmmmmm... *shameful yes*Are you modifying it during rendering?
none of your test roms cover it

Last edited by blargg on Thu Mar 13, 2008 2:02 pm, edited 1 time in total.
Ah, good find, didn't know that that was an "RMW"? instruction. Maybe you could improve your NES CPU opcode test program to include such cases?OK, Ironsword doesn't have the problem because the loop that clears APU registers reads the register first since it uses the STA $4000,x addressing mode. So that reads $4015 after the frame IRQ flag has been set.
I think the dummy read for STA ABS,X addressing mode solves the problem, so no NES tests are needed for Ironsword and Cobra Triangle. I still predict that Tiger-Heli will fail if powered down then up without a long delay between.
hap, here's a new test ROM that verifies that $2007 is unchanged during rendering: Rendering_and_$2007_buf.nes.zip
hap, here's a new test ROM that verifies that $2007 is unchanged during rendering: Rendering_and_$2007_buf.nes.zip
Oh lovely, if I power the NES off for 20 seconds or so, at power PPUADDR is $0000, SPRADDR is $2F, and most registers work immediately, rather than being ignored until 29658. Time for more test rewriting.. maybe I can hit 40 or 50 test ROMs! Bleah.
EDIT: OK, got a big rewrite of the PPU power/reset test ROMs done, and covering these new findings ("only" 37 test ROMs). NesDevWiki page is updated as well. Main finding was that if the NES is off for 20 seconds or more, all registers work at power, and $2002, $2003, and $2006 are 0.
ppu_power_reset3.zip
EDIT: OK, got a big rewrite of the PPU power/reset test ROMs done, and covering these new findings ("only" 37 test ROMs). NesDevWiki page is updated as well. Main finding was that if the NES is off for 20 seconds or more, all registers work at power, and $2002, $2003, and $2006 are 0.
ppu_power_reset3.zip