I've read about "garbage reads" (sometimes specific to PPU stuff, other times specific to joypad stuff) over the years. The terse explanation I've seen is that there's "crap on the bus" or something like that, which is why for certain things you supposedly discard the first read from some registers, etc...
I'm pretty sure I remember seeing this sort of behaviour on the original Apple II+, but it was always thoroughly documented in whatever docs you were reading (usually official technical manuals from Apple, sometimes other people's source).
I was hoping someone could take the time to explain to me what the deal is. :-)
P.S. -- No, I'm not getting back into NES development. These are just things that I've read about time and time again, and was hoping someone could explain them.
In emulators, usually it's common to implement delayed reads by having the last read copied to a latch variable. When you do the read, return the latch value, then read the memory into the latch variable.
When the CPU reads from memory, it puts the request on the bus control lines, then reads whatever's on the data bus at the time. When reading from unmapped memory, the CPU gets whatever happens to be on the data bus at the time. Some devices don't output a full 8 bits, so the other bits likewise get whatever is on the bus at the time. The data lines on the bus tend to act like they have capacitors connected to them, so that they store whatever the last voltage was when they were being driven. The capacitance is very small, but MOS device inputs usually don't draw much power, so they don't drain it to zero volts that quickly. What happens is that the data bus tends to hold the last logic level it was driven with. When the CPU reads from an unmapped area or device that doesn't drive some lines, it gets the last byte that was read on the bus, which is usually that of the high byte of the address, since that's what the CPU had just read.
I was recently reading about the ARM processor architecture, and apparently it internally uses this "charging the bus" to reduce transistor count. Apparently it "charges" the bus with logic 1 (positive voltage) during one clock, then something outputs a value on the next clock by either leaving the line charged (1) or draining it to zero volts (0). Just something related where this effect is used for a practical purpose.
Hmmm, perhaps you are referring to having to do an extra read before you get useful data? Like with the PPU's read port at $2007, where it has a one-byte buffer. In that case, I'm assuming it's to give some flexibility as to when the actual read occurs. When you read from it, you immediately get what's in the buffer, then the PPU can refill it at its leisure. The data you get isn't garbage, just not what you'd expect if you thought there was no intermediate buffer. The DMC uses something similar.
Speaking of Apple: Apple IIGS Hardware Reference states that the interface to the Apple IIGS's sound chip delays data read from sample RAM by one byte, and this is just like the NES PPU.
I hereby deem this thread about listing everything that needs a dummy read to prime it up.
The TI82/83/83+'s LCD controller requires a dummy read before reading a series of bytes.
Thanks guys. blargg's explanation makes the most sense to me (tepple's coming in at a close second, since I was an old IIGS guy), sans the EE-like stuff. :-) I think I get it.
Examples of reading $2007 are given (not that I'd know why someone would really want to read from the PPU), but in another recent thread (can't find it right now) someone mentioned that you had to do this for joypad reads as well. That said:
How exactly does a programmer know when to do a dummy read, and on what registers?
koitsu wrote:
(not that I'd know why someone would really want to read from the PPU)
Some games with limited PRG-ROM store data in CHR-ROM, so they must use $2006/$2007 to retrieve it. Also, in CHR-RAM games, a programmer might want to read-modify-write some tiles (although it would be better to keep a copy of such tiles in regular RAM to avoid the reading step). You could also use CHR-RAM for some extra RAM if you can spare a few tiles and that RAM isn't accessed very frequently.
Quote:
someone mentioned that you had to do this for joypad reads as well.
I believe that the issue with joypad reads is that while DPCM samples are playing, the NES fetching DPCM data could trigger some ghost reads of the joypad data, corrupting a full joypad read made by the program. This is very different from reading $2007. Unless you are talking about something else?
Quote:
How exactly does a programmer know when to do a dummy read, and on what registers?
I think this has to be tested and documented. We know for a fact that $2007 reads are delayed because of tests made on actual hardware.
Mario Bros (not Super) reads from PPU name tables to do collision map testing. Before implementing PPU reading in my emulator, Mario would fall to the bottom of the screen all the time. It was resolved when I added PPU reading. I don't think it's the only game to do such things.
tokumaru wrote:
Quote:
someone mentioned that you had to do this for joypad reads as well.
I believe that the issue with joypad reads is that while DPCM samples are playing, the NES fetching DPCM data could trigger some ghost reads of the joypad data, corrupting a full joypad read made by the program. This is very different from reading $2007. Unless you are talking about something else?
The controllers don't need dummy reads. But DPCM can double-clock $2007 reads just like it can double-clock $4016-$4017 reads, causing the program to skip a byte when it reads VRAM. That's one reason why I chose
not to store a side-scroller's environment destruction log in an otherwise unused part of sprite VRAM.
I wonder how many games use DMC, and store data in CHR ROM which is read while the music is playing.
Dwedit wrote:
I wonder how many games use DMC, and store data in CHR ROM which is read while the music is playing.
I bet not many, since the double-clock issue was probably known at the time, as some games appear to be aware of it when reading the controllers.
koitsu wrote:
Examples of reading $2007 are given (not that I'd know why someone would really want to read from the PPU)
Tecmo Super Bowl reads from the PPU when you select certain menus that have a dropdown box. It was only really necessay on a few dynamic screens, but they chose to use it for some static screens as well. Probably to avoid having to redraw the entire screen?
Here's the process of reading from $2007, broken down into sub-steps. VRAM initially contains $AA, $BB, $CC, starting at address $0000.
Code:
PPUADDR Buffer 2A03 Action
----------------------------------------------------------
$0001 $99 2A03 tries to read from $2007
$0001 $99 -> $99 2A03 gets whatever was in buffer
$0001 -> $BB PPU reads from VRAM at $0001
$0002 $BB PPU increments address
...
$0002 $BB 2A03 tries to read from $2007
$0002 $BB -> $BB 2A03 gets buffer contents (which were read from $0001 earlier)
$0002 -> $CC PPU reads from VRAM at $0002
$0003 $CC PPU increments address