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.
How reliable is $2003?
Moderator: Moderators
Re: How reliable is $2003?
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).
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.
P.S. If you don't get this note, let me know and I'll write you another.
Re: How reliable is $2003?
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.
* 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.
Re: How reliable is $2003?
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.
Re: How reliable is $2003?
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.
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.
Re: How reliable is $2003?
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.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.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
P.S. If you don't get this note, let me know and I'll write you another.
Re: How reliable is $2003?
Oh crap, I totally overlooked the fact that writing 0 to OAMADDR after the DMA could also cause corruption.lidnariq wrote:Er... that's not what I said at all.
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.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.
Re: How reliable is $2003?
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.
I guess it's not really any worse than having to reboot your Tandy CoCo until the artifact colors are the right ones.