How reliable is $2003?

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

Post Reply
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

How reliable is $2003?

Post by tokumaru »

With all the weirdness that exists related to the OAM, sprite evaluation and $2003/4, I'm wondering how reliable $2003 is under certain conditions.

For example, is it safe to set $2003 to a value other than 0 (but still a multiple of 4) before a sprite DMA? Can I expect to have all 256 bytes transferred from RAM to OAM without any sort of corruption? Do I need to set $2003 to 0 afterward or can it be left as is?

Some quirks of the PPU are hard to keep up with, so I figured I'd just come here and ask. Thanks.
User avatar
Quietust
Posts: 1918
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: How reliable is $2003?

Post by Quietust »

From what I understand (and from some tests I performed a number of years ago), it might be safe to set $2003 to a nonzero value, perform a DMA, then immediately set it to zero afterwards. More tests would still be a great idea, though.

If you leave the address as-is, all 256 bytes will still be copied successfully, but sprites 0 and 1 are likely to get corrupted when rendering starts (a behavior which the Sachen game "Huge Insect" relies on).
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: How reliable is $2003?

Post by lidnariq »

My understanding is that with the 2C02G:

* At the end of normal rendering, $2003 will be set to 0
* If you change it via writes to $2003, regardless of what you change it to or from, it will corrupt OAM, and in a not particularly predictable fashion.
* If rendering is enabled normally, and it's more than 7 when rendering starts, it'll corrupt OAM in a predictable manner, copying the 8 bytes at (OAMADDR & $F8) to the first 8 bytes.

The only thing remaining question is whether delaying turning on rendering until a later scanline will change that final behavior.

We know that the 2C02E is different, but haven't quantified how. We know that the 2C07 is approximately bug-free, although it has a few obnoxious deliberate design decisions.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How reliable is $2003?

Post by tokumaru »

Thanks for the replies. So it looks like it should indeed be safe to use values other than 0 for OAMADDR before the DMA as long as you set if back to 0 afterwards. I was mostly thinking about alternate ways to implement sprite cycling, but these 2 registers ($2003 and $2004) are so odd that I'm not sure I should take the risk.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: How reliable is $2003?

Post by lidnariq »

Er... that's not what I said at all.

In the 2C02G, writing to $2003 always causes corruption, regardless of what you're changing it to or from. It's basically never safe to write any value other than 0 to $2003, and even then you have to follow it with OAMDMA.

(edit) There is one very precise exception:
* If you write a non-zero multiple of 8 to $2003
* and you follow it with OAMDMA
* and you let rendering start normally, copying the 8 bytes at [OAMADDR]&$F8 to the beginning of the buffer
THEN the first eight bytes of the shadow OAM buffer will always end up being copied to sprites 0 and 1, and the remaining 62 sprites will rotate (of which two will be destroyed)

So ... in a roundabout way, it's safe to use, with the caveat that it will guarantee that there will always be something that looks like sprite dropout flicker.
User avatar
Quietust
Posts: 1918
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: How reliable is $2003?

Post by Quietust »

lidnariq wrote:In the 2C02G, writing to $2003 always causes corruption, regardless of what you're changing it to or from. It's basically never safe to write any value other than 0 to $2003, and even then you have to follow it with OAMDMA.
Back about 3 years ago, when these problems were being identified, I wrote a test program to try out various special combinations of doing offset DMAs, modifying $2003 immediately afterwards, and possibly waiting a frame before reading it back, and what I personally found (on my CopyNES) is that writing $2003 only caused corruption with certain CPU/PPU clock alignments (in my case, it would always corrupt $20-$27), but for other alignments it was consistently safe to write to $2003 immediately after a DMA without causing any corruption.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How reliable is $2003?

Post by tokumaru »

lidnariq wrote:Er... that's not what I said at all.
Oh crap, I totally overlooked the fact that writing 0 to OAMADDR after the DMA could also cause corruption.
Quietust wrote:writing $2003 only caused corruption with certain CPU/PPU clock alignments (in my case, it would always corrupt $20-$27), but for other alignments it was consistently safe to write to $2003 immediately after a DMA without causing any corruption.
See, that's the problem right there... We're still debating what's safe and what's not, so until we finally reach a consensus, I guess it's better to leave OAMADDR as 0 at all times.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: How reliable is $2003?

Post by lidnariq »

I mean, I trust Quietust's findings. I don't quite have the right hardware to put his program on a flashcart (i.e. I still only have that ridiculous m218 one).

I guess it's not really any worse than having to reboot your Tandy CoCo until the artifact colors are the right ones.
Post Reply