Page 1 of 2

Reading $2007

Posted: Sat Apr 02, 2005 9:46 am
by Bregalad
I know that reading any data from the PPU via $2007 (usually needed to read attribute tables for scrooling or pattern tables to have data on the CHR socket), the first data is a glitch and should be discarded. Now, I've a few questions :
- Does this dummy read increment the PPU pointer ? If so, I should substract one from the PPU adress before reading.
- Does $2007 reading increment the PPU pointer at all ? I know any write to $2007 will increase the PPU pointer by 1 or 32, but what about reading ?
Thanks

Posted: Sat Apr 02, 2005 10:49 am
by tepples
Yes, $2007 reads increment the VRAM address.

No, you shouldn't subtract one from the VRAM address on a $2007 read. Instead, a read should 1. return the current contents of the 1-byte read buffer, 2. copy the contents of the memory address into the 1-byte buffer, and finally 3. increment the VRAM address.

Posted: Sat Apr 02, 2005 12:05 pm
by Bregalad
Ah, so you'll read the previous data into this buffer, i.e. what the PPU itself did read during the previous frame (in VBlank).
Thank you.

Posted: Thu Jul 14, 2005 8:45 pm
by doppelganger
Since the first read since power-up is the one that's garbage, wouldn't it just be easier to read $2007 in the startup routine, then proceed with reading $2007 like normal?

Posted: Thu Jul 14, 2005 9:31 pm
by Memblers
Nope, you have to do a garbage read of $2007 any time you change the VRAM address (except by the auto-inc). The garbage read is actually reading what was previously in the buffer, and filling it with the byte at the specified VRAM address for the next read.

Posted: Mon Oct 30, 2006 12:56 pm
by doppelganger
Hmm...that would explain why, not only does super mario bros render the title screen perfectly, but does so every single time the title screen routine gets run regardless of whether it's come from powerdown or not.

Thank goodness this thread was here when I needed it! ;-)

Posted: Mon Oct 30, 2006 1:59 pm
by tepples
You'll find that a lot of CNROM games store much of their data in CHR ROM and read it out into main RAM with the PPU turned off. See Milon's Secret Castle.

Posted: Tue Oct 31, 2006 4:03 am
by blargg
Using the term "garbage read" is misleading since it implies that the buffer is somehow filled regularly with garbage, which is not the case. $2007 reads are buffered, which is best thought of as delaying things rather than returning garbage (except when reading palette RAM where there is no "delay", though the buffer is still invisibly refilled as if there were no palette RAM).

Posted: Tue Oct 31, 2006 6:54 am
by tokumaru
blargg wrote:except when reading palette RAM where there is no "delay"
Really? So reading the palette returns valid values right on the first read? Now that's confusing...

Posted: Tue Oct 31, 2006 7:32 am
by Quietust
tokumaru wrote:
blargg wrote:except when reading palette RAM where there is no "delay"
Really? So reading the palette returns valid values right on the first read? Now that's confusing...
Not really, when you consider how it works. For VRAM accesses, it takes the PPU just barely too long to read the data and return it in time for the CPU, so it needs to delay by 1 read cycle. However, the palette is entirely contained within the PPU itself, so it doesn't need to spend any time loading it and can thus return it immediately.

Posted: Tue Oct 31, 2006 10:23 am
by tepples
blargg wrote:Using the term "garbage read" is misleading
I've read the term "priming read" in similar contexts.

Posted: Tue Oct 31, 2006 1:08 pm
by tokumaru
Quietust wrote:However, the palette is entirely contained within the PPU itself, so it doesn't need to spend any time loading it and can thus return it immediately.
OK. So, external to the PPU are the 2KB of memory used for the name tables and attribute tables, and pattern table RAM possibly present in the cart. Carts can have extra name table and attribute memory also, right? So, all of these have a delay, and the only thing that's actually within the PPU is palette memory?

Yeah, I guess it's not complicated, but from the point of view of the programmer, $2006 and $2007 are used to access the same memory space, and seems weird that parts of it behave differently. Well, live and learn! =)

Posted: Tue Oct 31, 2006 3:14 pm
by kyuusaku
tokumaru wrote:So, all of these have a delay, and the only thing that's actually within the PPU is palette memory?
And OAM. Both could be the same DRAM.

Posted: Tue Oct 31, 2006 5:00 pm
by tokumaru
kyuusaku wrote:And OAM. Both could be the same DRAM.
Oh, yeah. I didn't say anything about OAM because it isn't accessible through $2006/$2007. But since you brought it up, can it be read back? You know, most people don't even use $2003/$2004 anymore, but could these be used to read from OAM?

Posted: Tue Oct 31, 2006 5:24 pm
by Quietust
Of course you can read from OAM! How else could I have reverse-engineered the PPU's sprite fetch behaviour?

The only caveat is that reading $2004 does not increment the address pointer ($2003) - only writing does that.