Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.
Here's another bit of weirdness that appears to only happen on real hardware, not any emulators. When some code is using DPCM for sample playback an extra pulse is generated on the controller read line. That messes up the controller reading routine by shifting the output. When the last read is done all the buttons have already been sent so it gets a false trigger on the right button. The same thing seems to be happening on the Yobo and FC Twin clones, haven't tested NEX or RetroDuo yet.
The pulse is about 3x as wide as the normal read ones, and appears to only happen shortly after the write to $4016. It doesn't always happen and not always the same period after the write. Logic analyzer capture below. The added pulse is between C and D.
Has anyone else seen this before, or can write some good test apps? Audio is one part I don't really understand.
I wonder if this is the reason why SMB3 and other games read the controller data multiple times until they get two consecutive reads which match.
The DPCM causes a DMA every so often, which is 3-4 CPU cycles long. One cycle is needed to read the sample date; the other cycles are used for synchronization and/or internal operations. Since a memory access occurs on every cycle, there will be some dummy reads. If the CPU recently accessed $4016, that address will still be on the bus when the DMA occurs, so it's certainly possible for one or more dummy accesses at $4016 to take place.
"Last version was better," says Floyd. "More bugs. Bugs make game fun."
dvdmth wrote:I wonder if this is the reason why SMB3 and other games read the controller data multiple times until they get two consecutive reads which match.
I seem to remember that Tetris also reads the controller port twice, despite that it doesn't use DPCM.
Thanks to bunnyboy on IRC - he just linked me to this thread. I spent the last hour or so going crazy, testing devcarts and my Powerpak, as well as numerous emulators, trying to figure out this problem. In some strange coincidence I just came across this problem for the first time today!
dvdmth wrote:The DPCM causes a DMA every so often, which is 3-4 CPU cycles long. One cycle is needed to read the sample date; the other cycles are used for synchronization and/or internal operations. Since a memory access occurs on every cycle, there will be some dummy reads. If the CPU recently accessed $4016, that address will still be on the bus when the DMA occurs, so it's certainly possible for one or more dummy accesses at $4016 to take place.
Except the long pulse comes before the $4016 read, and after many other instructions passed from the previous read, so its not left over bus capacitance? Does the DMA interrupt the currently executing instruction, so the $4016 address would have been calculated but not used yet?
DMA can (and does) interrupt CPU operations in the middle of an instruction. In fact, accurate SNES emulation is impossible without supporting it, which is why BSNES executes all instructions one cycle at a time (and other SNES emulators use hacks to work around the issue).
EDIT - I just thought of something. What about $2007 accesses? Surely, this problem would affect other serial I/O registers as well. Yet, if $2007 were also affected, why would we not have seen it by now? I would think that a dummy $2007 read would screw up the VADDR counter, which would cause data fed to VRAM to be shifted over...
When this "long pulse" occurs, is it always next to a normal $4016 access, or can it happen elsewhere? Does it happen if you change the location of DPCM sample data?
"Last version was better," says Floyd. "More bugs. Bugs make game fun."
Maybe its actually a feature, for reading from the expansion port? $4017 is also affected but I don't have an easy way to check other regs like $2007. If someone can write a test app that accurately places the interrupt then I can run it on real hardware and record results. I think I have only seen the long pulse within the controller reading routine, but my logic analyzer trigger may have not been set right to catch it other places.
I threw together a couple of tests that have DMC DMA occur during $4016 read and $2007 read. Both are affected. $2007 has some weird effects for a double read, even when causing it "normally" via LDA $20F7,X with X=$10. Full ca65 source included.
OK, so reading $4016 and $2007 is unreliable during DMC playback...
What about $2007 writes?
And if $2007 writes are affected, how in the world can VRAM updates be reliably done while a sample is playing? (And why is it that games using the channel haven't suffered from this?)
You can simulate a $2007 read/write combo on consecutive cycles with the STA $2007,X with X = 0 (the STA opcode always has a dummy read). A double write following a read can be done with INC $2007, and a double read followed by a double write can be done with INC $2007,X (again, X = 0).
"Last version was better," says Floyd. "More bugs. Bugs make game fun."
$2007 writes are also affected. For $2007 read/write, two or three extra reads are inserted before the actual read/write. The number depends on the CPU-PPU synchronization at reset. $4016 reads always seem to have one extra read inserted. I also added a test that verifies that a $2007 read just before a write (using STA $2007,X) works normally, rewrote the tests to use a shell that sets up the DMC, and added some CRCs for easy verification of output. NES ROMs + full ca65 source:
blargg wrote:$2007 writes are also affected. [But] Since the DMC DMA has to occur on exactly the right clock for this problem to occur, it would probably be very rare in any affected games.
For a wave at rate $F (1 sample per 54 NTSC cycles, or 33144 Hz; 1 byte every 54*4 = 432 cycles), wouldn't this glitch happen on average once every 432 writes? There are over twice that many writes when a nametable gets copied into VRAM. Or do I misunderstand "exactly the right clock"?