help me with sprite evaluation

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
help me with sprite evaluation
by on (#151333)
Due my wrong (or old) implementation of sprite evaluation (thing i can note in Bee 52) i just need some help with sprite evaluation mechnism.

First the wiki says:

Code:
During each pixel clock (341 total per scanline), the PPU accesses OAM in the following pattern:
Cycles 1-64: Secondary OAM (32-byte buffer for current sprites on scanline) is initialized to $FF - attempting to read $2004 will return $FF. Internally, the clear operation is implemented by reading from the OAM and writing into the secondary OAM as usual, only a signal is active that makes the read always return $FF.


My doubt is in:

Code:
the clear operation is implemented by reading from the OAM and writing into the secondary OAM as usual, only a signal is active that makes the read always return $FF


As usual how?? What signal is active??
Re: help me with sprite evaluation
by on (#151335)
Hmm... Well, for my best, "signal" means "only reads work, write has no effect" during this period (cycles 1-64). Currently, a Famicom doesn't read $2004, as it never returns the contents of the sprite ram.
Re: help me with sprite evaluation
by on (#151336)
This wiki explanation it really confuses me more and more.

Code:
Cycles 65-256: Sprite evaluation
On odd cycles, data is read from (primary) OAM
On even cycles, data is written to secondary OAM (unless writes are inhibited, in which case it will read the value in secondary OAM instead)
1. Starting at n = 0, read a sprite's Y-coordinate (OAM[n][0], copying it to the next open slot in secondary OAM (unless 8 sprites have been found, in which case the write is ignored).
1a. If Y-coordinate is in range, copy remaining bytes of sprite data (OAM[n][1] thru OAM[n][3]) into secondary OAM.
2. Increment n
2a. If n has overflowed back to zero (all 64 sprites evaluated), go to 4
2b. If less than 8 sprites have been found, go to 1
2c. If exactly 8 sprites have been found, disable writes to secondary OAM. This causes sprites in back to drop out.
3. Starting at m = 0, evaluate OAM[n][m] as a Y-coordinate.
3a. If the value is in range, set the sprite overflow flag in $2002 and read the next 3 entries of OAM (incrementing 'm' after each byte and incrementing 'n' when 'm' overflows); if m = 3, increment n
3b. If the value is not in range, increment n and m (without carry). If n overflows to 0, go to 4; otherwise go to 3
The m increment is a hardware bug - if only n was incremented, the overflow flag would be set whenever more than 8 sprites were present on the same scanline, as expected.
4. Attempt (and fail) to copy OAM[n][0] into the next free slot in secondary OAM, and increment n (repeat until HBLANK is reached)


We have 256 - 65 cc = 192 cc to all this thing happen. It always get me confused.
Re: help me with sprite evaluation
by on (#151337)
2 cycles per sprite plus 6 more per in-range sprite is guaranteed to be less than 192.
Re: help me with sprite evaluation
by on (#151340)
tepples wrote:
2 cycles per sprite plus 6 more per in-range sprite is guaranteed to be less than 192.


EDIT:

So much clear now, so it means that PRIMARY-> OAM[n][1], OAM[n][2] and OAM[n][3] are READ in ODD cycles and SECONDARY-> OAM[n][1], OAM[n][2] and OAM[n][3] are WRITTEN on EVEN cycles? I put it for claryfing things.

The other 2 cycles are for the OAM[n][0] evaluation??
I mean, i have an english missaunderstanding problem here with the Wiki when it says:

Code:
1. Starting at n = 0, read a sprite's Y-coordinate (OAM[n][0], copying it to the next open slot in secondary OAM (unless 8 sprites have been found, in which case the write is ignored).
   1a. If Y-coordinate is in range, copy remaining bytes of sprite data (OAM[n][1] thru OAM[n][3]) into secondary OAM.

Code:
"Copying it to the next open slot"

The "Y" copy can't be made to the SECONDARY buffer becouse it would be ready "to go" in a sprite unit. (Im confused about this)
AND are these the 2 cc you say for sprite Tepples??
Re: help me with sprite evaluation
by on (#151359)
1 cycle to fetch data from sprite RAM,
1 cycle to write data to secondary OAM.

In write mode, evaluate the Y value (+sprite zero hit).
If less than 8 sprites were found:
- if Y value is in range, write data & advance the pointer++;
else, skip the next 3 bytes (OAM+3).

Code:
         /* normal evaluation */
         else
         {
            //transfer data
            oam_secondary[oam_secondary_addr] = oam_read_buffer;
            if(oam_y_in_range)
            {
               oam_secondary_addr++;
               //transfer complete
               if( 0 == (oam_secondary_addr & 3) )
                  oam_y_in_range = 0;
            }
            else //skip the remaining bytes, move forward
               oam_addr += 3;
         }
Re: help me with sprite evaluation
by on (#151367)
OK, thanks for the help, im closer now to get more precise timing.

Blargg's Sprite Timing Test now throws me:

Code:
12)too late when 9th sprite # is way after 8th


I don't know what it means.
Re: help me with sprite evaluation
by on (#151372)
Probably $2002:$20 flag should be set earlier.