It is currently Sun Dec 17, 2017 4:38 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Fri Apr 28, 2017 7:19 am 
Offline

Joined: Wed May 04, 2016 12:43 am
Posts: 8
Hi,

I'm currently trying to wrap my brain around the PPU sprite evaluation behaviour reading the details here: http://wiki.nesdev.com/w/index.php/PPU_ ... evaluation

However, I don't understand how cycles 65-256 are performed. The evaluation is done on all 64 OAMs meaning it would take (256-64)/64 = 3 cycles per sprite evaluation. (If it should cover all cycles)
The wiki states that odd cycles are read operations from the OAM, and even are writes to secondary OAM. However, there are two loops happening within this time.
First is the evaluation to find out what gets copied to the secondary OAM, and then there's the other loop for the (broken) overflow flag update.
How is this done? Are the loops done in parallel or sequentially? Does anyone have a more detailed description on how this is done per cycle?

-Eicar


Top
 Profile  
 
PostPosted: Fri Apr 28, 2017 7:38 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19354
Location: NE Indiana, USA (NTSC)
Eicar wrote:
I don't understand how cycles 65-256 are performed. The evaluation is done on all 64 OAMs meaning it would take (256-64)/64 = 3 cycles per sprite evaluation.

Each access takes 2 cycles, and there are one access per sprite and three additional accesses per in-range sprite.

Quote:
The wiki states that odd cycles are read operations from the OAM, and even are writes to secondary OAM. However, there are two loops happening within this time.
First is the evaluation to find out what gets copied to the secondary OAM, and then there's the other loop for the (broken) overflow flag update.
How is this done? Are the loops done in parallel or sequentially?

It's a state machine. For each cycle of the pixel loop, the loop to evaluate sprites for the next line runs one step. So it's done in parallel with the background and sprite rendering.

Quote:
Does anyone have a more detailed description on how this is done per cycle?

What other programming languages do you know? If you know C or C++, the following may make sense:
Code:
size_t soam_index, i;
for (soam_index = 0; soam_index < 32; ++soam_index) {
  rest_1_cycle();  // 1 cycle
  secondary_oam[soam_index] = 0xFF; // 1 cycle
}

for (i = 0, soam_index = 0; i < 256 && soam_index < 32; i += 4) {
  unsigned char y = oam[i];  // 1 cycle
  if (soam_index < 32) { // 1 cycle
    secondary_oam[soam_index] = y;
    if (y_in_range(y)) {
      unsigned char tmp = oam[i + 1];  // 1 cycle
      secondary_oam[++soam_index] = tmp;  // 1 cycle
      tmp = oam[i + 2];  // 1 cycle
      secondary_oam[++soam_index] = tmp;  // 1 cycle
      tmp = oam[i + 3];  // 1 cycle
      secondary_oam[++soam_index] = tmp;  // 1 cycle
      ++soam_index;
    }
  }
}

// Broken overflow flag stuff omitted; this stuff can be
// addressed later when getting Codemasters games working


Top
 Profile  
 
PostPosted: Sat Apr 29, 2017 7:44 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1393
It takes 2 cycles to process a sprite that's not in range, and 8 cycles to process a sprite that is in range (of which there can be up to 9 - 8 to display, and 1 to trigger overflow).

Thus, sprite evaluation for a single scanline can take anywhere from 128 to 182 cycles out of the 192 cycles available - the remaining time is spent rescanning the early sprites and ignoring them as if they were out of range.

_________________
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.


Top
 Profile  
 
PostPosted: Mon May 01, 2017 11:52 am 
Offline

Joined: Wed May 04, 2016 12:43 am
Posts: 8
Thanks for the reply guys, that's certainly appreciated!

Still it's not all clear to me....

1. I guess 128 to 182 cycles is only accurate when the OAMADDR ($2003) is zero at the beginning of the pre-render scanline? Does this mean that the OAMADDR is latched at the very beginning
of the pre-render scanline, and that this latched value is used for all scanlines? (So that any accidental changes to OAMADDR during rendering will not affect the evaluation?)
2. http://wiki.nesdev.com/w/index.php/PPU_ ... evaluation claims under point 2.1 that n starts with zero. However, doesn't n start with the content of OAMADDR ?
3. If so, then all sprites on lower offset than OAMADDR will never be evaluated? (and never displayed?)
4. http://wiki.nesdev.com/w/index.php/PPU_ ... evaluation under point 2.2.2c: Should there be a "go to 3" at the end of this line?

-Eicar


Top
 Profile  
 
PostPosted: Mon May 01, 2017 11:57 am 
Online

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6538
Location: Seattle
OAMADDR is reset to zero at the beginning of rendering and at the end of evaluation of each scanline of sprites. The special note there about "if OAMADDR is not zero when evaluation starts" is basically only relevant if you turn on rendering at specific times in the middle of the scanline.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group