OAMDATA $2003 corruption clarification?
Posted: Sun Jan 29, 2023 3:05 pm
The current wiki description for OAMADDR / $2003 seems incomplete or inconsistent, and I'd like to try and clarify it. A few questions:
1. Writes to $2003 "reliably corrupt OAM" on 2C02G.
Do we have a better description of this reliable corruption? Does it overwrite specific bytes? Does it overwrite with specific values? Does it copy an 8 byte line from the current OAM address to the target one, similar to the other well-defined behaviour of leaving $2003 set to something not-zero before rendering?
The suggested workaround is simply writing all 256 bytes, which I feel should really more explicitly suggest using OAMDMA? The timing of decay makes a naive attempt to write all 256 bytes through $2004 prone to intermittent failure.
2. OAMADDR is set to 0 during each of ticks 257–320 (the sprite tile loading interval) of the pre-render and visible scanlines.
I feel we should explicitly clarify that this means that OAMADDR will always be 0 after the conclusion of a rendered frame?
3. The value of OAMADDR when sprite evaluation starts at tick 65 of the visible scanlines will determine where in OAM sprite evaluation starts, and hence which sprite gets treated as sprite 0. The first OAM entry to be checked during sprite evaluation is the one starting at OAM[OAMADDR]. If OAMADDR is unaligned and does not point to the y position (first byte) of an OAM entry, then whatever it points to (tile index, attribute, or x coordinate) will be reinterpreted as a y position, and the following bytes will be similarly reinterpreted. No more sprites will be found once the end of OAM is reached, effectively hiding any sprites before OAM[OAMADDR].
This almost seems to imply a contradiction with point 2. If OAMADDR is being set to 0, how and when does this case come up? Do we have to set OAMADDR in the early portion of the scanline (0-64) to make this happen?
Or is this an incorrect description of the known behaviour 4 below?
4. It is also the case that if OAMADDR is not less than eight when rendering starts, the eight bytes starting at OAMADDR & 0xF8 are copied to the first eight bytes of OAM; it seems likely that this is related.
So, is this a full explanation of the behaviour that 3 attempts to describe, or is there really something special about setting OAMADDR mid-scanline that it's trying to get across?
Is this also a full explanation of the corruption of 1 too? Is it simply a more general behaviour that all writes to OAMADDR, including the implicit one at tick 257 of a scanline, will copy the 8 bytes at the current address line to the target address line? Or is the corruption of 1 something else?
1. Writes to $2003 "reliably corrupt OAM" on 2C02G.
Do we have a better description of this reliable corruption? Does it overwrite specific bytes? Does it overwrite with specific values? Does it copy an 8 byte line from the current OAM address to the target one, similar to the other well-defined behaviour of leaving $2003 set to something not-zero before rendering?
The suggested workaround is simply writing all 256 bytes, which I feel should really more explicitly suggest using OAMDMA? The timing of decay makes a naive attempt to write all 256 bytes through $2004 prone to intermittent failure.
2. OAMADDR is set to 0 during each of ticks 257–320 (the sprite tile loading interval) of the pre-render and visible scanlines.
I feel we should explicitly clarify that this means that OAMADDR will always be 0 after the conclusion of a rendered frame?
3. The value of OAMADDR when sprite evaluation starts at tick 65 of the visible scanlines will determine where in OAM sprite evaluation starts, and hence which sprite gets treated as sprite 0. The first OAM entry to be checked during sprite evaluation is the one starting at OAM[OAMADDR]. If OAMADDR is unaligned and does not point to the y position (first byte) of an OAM entry, then whatever it points to (tile index, attribute, or x coordinate) will be reinterpreted as a y position, and the following bytes will be similarly reinterpreted. No more sprites will be found once the end of OAM is reached, effectively hiding any sprites before OAM[OAMADDR].
This almost seems to imply a contradiction with point 2. If OAMADDR is being set to 0, how and when does this case come up? Do we have to set OAMADDR in the early portion of the scanline (0-64) to make this happen?
Or is this an incorrect description of the known behaviour 4 below?
4. It is also the case that if OAMADDR is not less than eight when rendering starts, the eight bytes starting at OAMADDR & 0xF8 are copied to the first eight bytes of OAM; it seems likely that this is related.
So, is this a full explanation of the behaviour that 3 attempts to describe, or is there really something special about setting OAMADDR mid-scanline that it's trying to get across?
Is this also a full explanation of the corruption of 1 too? Is it simply a more general behaviour that all writes to OAMADDR, including the implicit one at tick 257 of a scanline, will copy the 8 bytes at the current address line to the target address line? Or is the corruption of 1 something else?