PPU warmup is real

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

PPU warmup is real

Post by blargg »

I've been doing some power/reset research and have found justification for the "PPU warmup" code. I tested the following after power and reset to see if the PPU address was set to $1111. After power, it failed 50% of the time (10 trials). After reset, it failed 11% of the time (50 trials).

Code: Select all

reset:  sei             ; Standard init
        cld
        ldx #$FF
        txs
        inx
        stx $2000
        stx $2001
:       bit $2002       ; wait for VBL flag
        bpl :-
:       bit $2002       ; wait for VBL flag again
        bpl :-
        lda #$11        ; VADDR=$1111
        sta $2006
        sta $2006
The VBL flag is set about half the time at power, and 11% of the time at reset (when reset is pressed while the flag is set, most likely). The VBL flag is next set at reset+27383 CPU clocks. Writes to $2006 are ignored until reset+29658 CPU clocks. So merely waiting until two $2002 reads have the high bit set isn't enough if you plan on writing to $2006 immediately after. Adding one more $2002 read makes it work every time after power and reset:

Code: Select all

reset:  ...
        bit $2002       ; clear VBL flag (ADDED)
        
:       bit $2002       ; wait for VBL flag
        bpl :-
:       bit $2002       ; wait for VBL flag again
        bpl :-
        ...
$2006 isn't the only register I've found to be ignored like this, just one example that justifies this warmup wait.
dvdmth
Posts: 354
Joined: Wed Mar 22, 2006 8:00 am

Re: PPU warmup is real

Post by dvdmth »

blargg wrote:The VBL flag is set about half the time at power, and 11% of the time at reset (when reset is pressed while the flag is set, most likely).
I thought there was a commercial game that required VBL to be set at power-up to boot, because it wrote $80 to $4017 to prevent frame IRQ's (which won't work if an IRQ is pending). Are you saying this game will fail to boot 50% of the time at power-up?
"Last version was better," says Floyd. "More bugs. Bugs make game fun."
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

$4017 controls the APU IRQ. That's unrelated to the PPU and the VBL flag.
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

The game in question is either Ironsword, Time Lord, or something like that. The reason VBL status at powerup matters in that case is because the game does a warm up loop where it waits for it to be set twice before writing to $4017. Also it doesn't disable IRQs when it writes to $4017, it simply switches to the 5-step mode -- but since it doesn't disable or acknowledge them, if an IRQ tripped before it switched modes, that IRQ will be pending for the whole game which causes it to muck up.

If VBL is clear at powerup, then the game effectively waits two full frames at startup (or at least more than one full frame) which ensures a frame IRQ will trip. But if VBL is set, then it will only wait for one full frame (or less) making it still possible to slip the mode change in before the IRQ happens.
Celius
Posts: 2158
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Post by Celius »

Funny you should mention this, because when I started to really understand most things about NESdev, I decided to wait 3 Vblanks instead of 2 to be safe. So ever since then, I've waited 3 Vblanks, and now I know I should :) .
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Very interesting. I decided to convert those timings from CPU cycles to NTSC scanlines, and I saw some interesting correlations:
  • If power-on to first true vblank is 27383 cycles, that's close to 241 lines. This would be expected if the PPU starts at the top left pixel, going through all 240 active lines and the post-render line.
  • If power-on to first successful VRAM transaction is 29658 cycles, that's close to 261 lines, ending at the pre-render line.
Another thing you might want to check out: Spinning on $2002 might miss a vblank if the start of vblank and the $2002 read happen on exactly the same CPU cycle. Does NMI (lda #$80 sta $2000) work predictably before 30,000 CPU cycles? Or must programs spin on $2002 and potentially miss several vblanks in a row?
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

This code sometimes allowed an IRQ through at power. It didn't at reset if the APU mode was $80 before reset, so a game with this sort of code at reset that used mode $80 exclusively would reset reliably, even if it failed at power. I used an APU-based timer to find out how long the two VBL loops waited total and it was usually ~27331 clocks, only occasionally ~57113.

Code: Select all

reset:
:   bit $2002   ; wait for VBL flag
    bpl :-
:   bit $2002   ; wait for VBL flag again
    bpl :-
    lda #$80
    sta $4017
    cli
    sei
For whatever reason, the VBL flag was set most of the time at power today. Does the game in question sometimes fail to work on a NES until reset is pressed?
Does NMI (lda #$80 sta $2000) work predictably before 30,000 CPU cycles? Or must programs spin on $2002 and potentially miss several vblanks in a row?
A $2002 spin loop will never wait more than VBL period*2, since it can never suppress two VBL flag settings in a row. Writes to $2000 before +29658 are also ignored, so NMI can't be used immediately either. $2007 works immediately, just $2006 doesn't. So you can begin accessing VRAM $0001 upwards immediately (what PPUADDR powers up with).
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

For whatever reason, the VBL flag was set most of the time at power today. Does the game in question sometimes fail to work on a NES until reset is pressed?
Anyway, if you have ever played real games with a real nes and an unmodified cartridge connector, you have to reset the system and re-inster the cartridge so many times before getting the game to work that it would be impossible to tell if this is due to hardware or software fault.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper »

...or even if you need to (re)blow it. :)
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

blargg wrote:Writes to $2000 before +29658 are also ignored, so NMI can't be used immediately either.
So much for commercial games that write 0 to $2000 in their init code. It's a good thing you're discovering this now before I start propagating half-truths in the tutorial that I've been working on. Thanks again for this research.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

So much for commercial games that write 0 to $2000 in their init code.
Initializing these things is a good idea if one wants the code to be more compatible with NES clones (including inaccurate NES emulators). SEI, CLD, writing $00 to $2000, $2001, $4010, and $4015, $40 to $4017, and reading $4015 afterwards are all good ideas along these lines.
dvdmth
Posts: 354
Joined: Wed Mar 22, 2006 8:00 am

Post by dvdmth »

Does the VRAM address start out at $0001 after reset, or just after power?

Are any registers besides $2002 and $2007 usable before the end of the first VBlank period?

What is the initial state of the other $2002 bits (sprite hit and overflow)?

In short, how are all of the PPU registers set at power and/or reset?

Incidentally, some commercial games I looked at write zero to $2000 and $2001 repeatedly within the $2002 warmup loop(s). Also, one of the MMC5 games I examined watied much longer at this time (around 16 VBlanks IIRC). Writing to $2000 and $2001 is probably more important with the Famicom than with the NES, since its state after reset is more volatile (I'm not sure if the Famicom PPU gets reset at all).
"Last version was better," says Floyd. "More bugs. Bugs make game fun."
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

At least Dragon Warrior tries to write to $2006 possibly only one frame after powerup (however, I don't know big the issue is if the write fail). The game seems to write to pattern tables, even tough the game uses CHRROM, which has no effect, since /WR isn't even connected to cartridges with CHRROM. Weird.
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Post by Bananmos »

Hmm... I wonder if the PowerPak suffers from this as well, since it will often fail at power-up, just showing a single-colored screen.
dvdmth
Posts: 354
Joined: Wed Mar 22, 2006 8:00 am

Post by dvdmth »

Bananmos wrote:Hmm... I wonder if the PowerPak suffers from this as well, since it will often fail at power-up, just showing a single-colored screen.
No, the PowerPak waits three VBlanks in the reset code. It also initializes the FPGA before doing anything with the PPU, which adds further delay.
"Last version was better," says Floyd. "More bugs. Bugs make game fun."
Post Reply