Are writes to $2000 and $2001 ignored after reset?

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
anzihoio
Posts: 3
Joined: Sun Oct 24, 2010 10:10 am

Are writes to $2000 and $2001 ignored after reset?

Post by anzihoio »

This is my current init code - I want to disable NMI generation and disable rendering:

Code: Select all

reset:
  sei
  cld
  ldx #$FF
  txs

  lda #$00
  sta $2000 ; write 0 to $2000.7 to disable NMI generation
  sta $2001 ; write 0 to $2001.3 and $2001.4 to disable rendering

  ; wait for the PPU to warm up, clear memory, etc.
It seems to work, and every tutorial I came across does it this way, however this wiki page says it shouldn't work:
Writes to the following registers are ignored if earlier than ~29658 CPU clocks after reset: $2000, $2001, $2005, $2006.
The other registers work immediately: $2002, $2003, $2004, $2007, $4014.
So my question is this: are writes to $2000.7, $2001.3 and $2001.4 ignored right after reset or not?
User avatar
Bregalad
Posts: 8036
Joined: Fri Nov 12, 2004 2:49 pm
Location: Caen, France

Post by Bregalad »

I guess the "safest" way to go is to disable NMI and screens, wait 2 frames with $2002 polls, and then disable them again.

I'm pretty sure Final Fantasy would crash if an NMI would occur in the first 2 frames though. So I guess at least $2000.7 writes are acknowledged.
Useless, lumbering half-wits don't scare us.
User avatar
thefox
Posts: 3139
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Post by thefox »

Yeah, it may "not work", as in the writes will not go through, but you'll also see on that same page that rendering and NMI's will be by default disabled when system is powered on / reset, so it doesn't matter.

It''s just good practice to clear them. Some revisions / clone systems might work differently.

BTW, I could test the power-up/reset state of PAL NES, but I doubt there will be any significant differences.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
Memblers
Site Admin
Posts: 3901
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers »

There is also the case to consider for hitting the reset button, because at that point the screen and NMI probably are both turned on. Same deal with doing SEI as the first instruction, IRQs are disabled on power-on but that doesn't mean they weren't turned on before reset (worst case a program could have a bug and accidentally execute a CLI instruction).

Also, I know the toploading NES (and Famicom?) does not actually reset the PPU with the reset button (there is a reset pin on the chip), so it'd be wise to reset the PPU registers even it works OK on the 'usual' NES.
anzihoio
Posts: 3
Joined: Sun Oct 24, 2010 10:10 am

Post by anzihoio »

Alright, thanks guys. I'm not doing anything fancy so I guess I'll leave it this way.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames »

If your testing on a actual system, this wouldn't work. At least according to the Wiki, so a test on real hardware might be able to say more definitively.
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Reset clears $2000 on the front-loader NES, so you don't have to worry about a write just after reset being ignored, unless you're enabling it. If the PPU isn't connected to reset, then presumably writes work immediately after reset, and thus you're able to disable NMI.

But, I don't see how that helps. Let's say that NMI is enabled when your reset handler begins. This means that NMI could occur immediately after the first instruction, even if you disabled it there with something like LSR $2000. So writing 0 to $2001 just after reset is just making this less likely. Making bugs less likely seems like a bad idea, becuase it makes them harder to find during development. It seems that the hardware must disable NMI, or else there's no way to prevent this from occurring.
User avatar
Bregalad
Posts: 8036
Joined: Fri Nov 12, 2004 2:49 pm
Location: Caen, France

Post by Bregalad »

So in summary :
- After a PPU reset (power on, frontloader NES reset), $2000 and $2001 writes are ignored for 2 frames, but NMI and rendering is disabled by the reset anyway.
- After a CPU reset (toploader NES or FC reset), the PPU remains in it's old state, but $2000 and $2001 wrties works immediately.

In other words, to be "safe" that your program will work identically on all models of NESes and FCs, disable NMI and rendering, wait 2 frames, and then do whatever else you have to do.

I guess Final Fantasy would have a very low probability to crash when reseted on a FC.... If you hit the reset button at a time that the game is not in it's iddle loop, and that you are able to release the reset button a few cycles before a NMI triggers, the game will crash. The probability is less than 1/1000 though.
Useless, lumbering half-wits don't scare us.
anzihoio
Posts: 3
Joined: Sun Oct 24, 2010 10:10 am

Post by anzihoio »

65024U wrote:If your testing on a actual system, this wouldn't work. At least according to the Wiki, so a test on real hardware might be able to say more definitively.
I'm only using emulators but some day I would like to run my code on a real NES.
Bregalad wrote:I guess Final Fantasy would have a very low probability to crash when reseted on a FC.... If you hit the reset button at a time that the game is not in it's iddle loop, and that you are able to release the reset button a few cycles before a NMI triggers, the game will crash.
I would prefer my code to be deterministic but I guess I can live with that ;)
blargg wrote:Let's say that NMI is enabled when your reset handler begins. This means that NMI could occur immediately after the first instruction, even if you disabled it there with something like LSR $2000. So writing 0 to $2001 just after reset is just making this less likely. Making bugs less likely seems like a bad idea, becuase it makes them harder to find during development. It seems that the hardware must disable NMI, or else there's no way to prevent this from occurring.
So should the write to $2000 be removed from the init code (replaced with a comment saying that "this can't happen") or should it be kept "just in case" (and maybe include it only in release builds)? Something like:

Code: Select all

reset:
  sei
  ; Keep this write as close to reset as possible.
  ; It does absolutely nothing if the NMIs are disabled on reset
  ; (the sane scenario) but it reduces the chance of a crash
  ; if they're not.
  .ifdef RELEASE
    lsr $2000 ; Let's hope for the best. Btw, nice trick with the lsr.
  .endif
  ldx #$FF
  txs
  ; ...
I'm just trying to write the best reset routine possible (and never touch this code again :)) but none of the tutorials I've read addresses the fact that NMIs might be enabled after reset and/or writes to PPU registers might be ignored (I've read most of the wiki, Nerdy Nights, NES 101 and some code posted here on NesDev - if there is a tutorial that explains this I would appreciate if someone could post a link).
It might not seem that important/interesting (and it probably isn't :P) but for me it's like an itch that just won't go away ;)
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

blargg wrote:Making bugs less likely seems like a bad idea, becuase it makes them harder to find during development.
And yet, most of you are big fans of clearing the whole memory at start up.
3gengames
Formerly 65024U
Posts: 2281
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames »

tokumaru wrote:
blargg wrote:Making bugs less likely seems like a bad idea, becuase it makes them harder to find during development.
And yet, most of you are big fans of clearing the whole memory at start up.
And using 2 reset routines would be wasteful of ROM so why not? Powerup/Reset should make the system start in a known state, IMO. Never know what variables could be set.

Question time:
I clear the memory, wait 2 frames, etc. Never had problems on a actual system. If you write 0 to the PPU to stop NMI if it's on a system that does reset the PPU, Will the PPU ignore it, be the first instruction clocked into it, or what?
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

tokumaru wrote:
blargg wrote:Making bugs less likely seems like a bad idea, becuase it makes them harder to find during development.
And yet, most of you are big fans of clearing the whole memory at start up.
The point of clearing memory is exactly the same as this: reduce the number of starting states the NES can be in when your program begins. If you could consistently get everything in the NES to the same starting state each time your program ran, testing would be very simple: run it once, and if it works, it has no bugs (up until it reads the controller or battery RAM, that is).
anzihoio wrote:'m just trying to write the best reset routine possible (and never touch this code again )
I'd treat EVERYTHING in this thread as unreliable. If I had some time and wanted to do what you describe, I'd first get available all the NES types for testing: NTSC frontloader, toploader, PAL frontloader (toploader?), and the various Famicom versions. Then write code that verifies that $2000 is not clear by reset on some of the machines. Then write code that clears $2000 just after reset, and see whether I can get an NMI to occur just before that (what's that, like a 1 in 5000 chance?). Either way, verify that removing the $2000 clear allows an NMI after reset on those machines, but not on ones like the NTSC frontloader. At this point there would be confirmation that the clear is needed for consistent behavior.

Basically, I wouldn't trust a one-code-fits-all-NES-units reset routine until it was tested well. Even if everything posted here is correct, we might be missing some detail or not thought it through. The standard one works fine, where you wait two frames before doing PPU writes.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

65024U wrote:
tokumaru wrote:
blargg wrote:Making bugs less likely seems like a bad idea, becuase it makes them harder to find during development.
And yet, most of you are big fans of clearing the whole memory at start up.
And using 2 reset routines would be wasteful of ROM so why not?
It's a waste of about 24 bytes of ROM to clear RAM once when you power on and again when you initialize variables for a menu or a level. However, it's not wasteful of CPU time if it's done between the two vblanks.
doppelganger
Posts: 183
Joined: Tue Apr 05, 2005 7:30 pm

Post by doppelganger »

The programmers at NCL seemed to be in the habit of clearing $2000 on reset. They're less consistent on clearing $2001, at least before the frame delay.
Be whatever the situation demands.
Post Reply