This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

DPCM generates extra $4016 read pulse

DPCM generates extra $4016 read pulse
by on (#33494)
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.


Image

Has anyone else seen this before, or can write some good test apps? Audio is one part I don't really understand.

by on (#33497)
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.

by on (#33499)
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.

by on (#33520)
So that's why a friend's NSF player randomly switches to the next track! I've been pulling my hair out trying to track this one down!

by on (#33522)
That explains quite a few bugs in homebrew code, perhaps. Solar Wars had a few "phantom" right-button-presses that I could never figure out.

by on (#33523)
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!

by on (#33537)
Thanks god I don't use DPCM so I guess I'm all right.

by on (#33539)
I wonder if Codemasters games reread the gamepad. A lot of them (e.g. Fire Hawk) use the DPCM channel for timing.

by on (#33549)
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?

by on (#33553)
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?

by on (#33555)
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.

by on (#33559)
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.

dmc_dma_during_read.zip (obsolete; see below for newer tests)

bunnyboy, for your testing, should I make versions that continuously trigger the effect as often as possible?

by on (#33560)
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).

by on (#33561)
$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:

dmc_dma_during_read3.zip

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.

by on (#33562)
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"?

by on (#33563)
If the loop wrote to $2007 every 13 clocks, then a DMC DMA read occurring somewhere during the loop would have a 1 in 13 chance of affecting it. If there are multiple DMA reads during the loop, then you have to do some math to find out what happens. If for example they are every 432 clocks, you must first subtract 4, since each DMA steals 4 CPU clocks normally. So every 428 non-wait-state CPU clocks the DMA will occur. 428/13 = 32 with a remainder of 12. So each time it will occur 12 clocks later than the last, or 1 clock earlier. So it would be sure to hit the critical clock after 13 iterations. Then when it hits, the DMA takes one clock less, so it would jump back an extra clock that time, resulting in it occurring every 12 iterations, or every 5184 CPU clocks. I guess I should write an actual test of this, which writes lots of data to VRAM, then verifies how often there is a glitch.

by on (#33564)
Argh, I'm being extremely sloppy today for some reason. This issue is ONLY affecting reads, not writes. $2007 READ at the critical moment results in 2-3 extra reads; $2007 write is not affected at all. So it seems this bug only impacts code which reads from hardware where the read itself has side-effects. That means PPUSTATUS ($2002), PPUDATA ($2007), SNDCHN ($4015), JOY1 ($4016), and JOY2 ($4017).

Tests with hopefully correct conclusion comments at the top of the source files:

dmc_dma_during_read4.zip

Here's bunnyboy's scope trace for when a $2007 read is affected. The first is unaffected, the second the two different effects. The center waveform of each is the PPU's /RD line to VRAM, NOT the /RD line from the 2A03. The $4016 trace is because we were using a $4016 read to trigger the scope's capture; it had no effect on the test.

Image

by on (#33566)
By the time NES games started using DPCM to the fullest, they no longer had the PRG size limitations that required the NROM/CNROM typical method of stuffing data in CHR and reading it back. I guess that's why we never noticed this until now.

by on (#33570)
But reading $2007 can proof extrememly usefull for example to modify attributes even if you don't have to worry about memory contraints.

Also, I've seen "modern" MMC3 games read stuff from CHRROMs, like Tiny Toons Adventures 2, Earthbound proto or Batman - Return of the Jokey (okay it's not MMC3, but it's "modern" and uses DPCM).

Hey, I think that this glitches explain a few things about why does some games use DPCM only under some circonstances. For instance, Fire Emblem uses DPCM on title screen, enemy phase music and during battle, and for all those time no accurate joypad reading is required. During player phase, DPCM is never used, and so joypad reading is accurate.

EDIT : My theory on Fire Emblem above doesn't make sense as sometimes an alternate player phase music with DPCM plays, and input is requesed on stage start where music with DPCM plays.

by on (#63996)
blargg wrote:
Tests with hopefully correct conclusion comments at the top of the source files:

dmc_dma_during_read4.zip



Has this test moved somewhere else? Is it still available?

by on (#63998)
Ripway closed my old site for some reason, but I have everything that was on it. Here it is on the new, stable parodius site: dmc_dma_during_read4.zip

by on (#64017)
blargg wrote:
Ripway closed my old site for some reason, but I have everything that was on it. Here it is on the new, stable parodius site: dmc_dma_during_read4.zip


Ok I pass dma_2007_read.nes, dma_2007_write.nes, and read_write_2007.nes. But, I can't seem to get dma_4016_read.nes to give me any output. Tracing with my emulator set for a breakpoint on $4016 being anything other than $40 when read by the CPU never triggers. I have tried all of the joypad 1 buttons...confused. I can see it stuck in a loop looking to count how many reads of $4016 happen before it gets a 1. It never gets a 1. If I'm thinking straight, lda $4016 shouldn't cause a dummy read that could be throwing the 1 away. I guess I'll next need to check that the joypad read triggering works, but it looks fairly straightforward in the test ROM code, and I *know* joypad read triggering works; I can play plenty of games...

Off to implement the joypad inspector. 8)

by on (#64018)
Are you remembering to have your joypad emulation code switch to producing all 1's after the shift register empties?

by on (#64030)
ReaperSMS wrote:
Are you remembering to have your joypad emulation code switch to producing all 1's after the shift register empties?


Hmmm. Where is *that* behavior documented? :o Of course that means I'm not...so that will fix it for sure. Thanks!

by on (#64032)
I just summarized this topic on the wiki.
Re: DPCM generates extra $4016 read pulse
by on (#99835)
Hi, I've been trying to reproduce the double-read glitch on my PAL NES (manufactured around 1991, with RP2A07A CPU/APU and RP2C07-0 PPU), but somehow I've failed there: The glitch never occurred. Is it possible that the glitch occurs only in older NES console? Or only in NTSC consoles?

What I've tested is: The above "dmc_dma_during_read4.zip" package - but I don't really understand what the program is meant to do - if it says "Failed" does that mean that glitch has occurred - or that the glitch has failed to occur? And, the tests seems to rely on the "delay 3309+33+time-iter" (in the common.inc file), which looks like hardcoded NTSC DMA delay, so I'd guess that the tests won't work on PAL.

Then I've brewed up my own test program (can be downloaded here viewtopic.php?p=99773#p99773 - "pputest.zip"; contains test for the DMC glitch and some other PPU related tests). The test is quite simple: Reading 2007h and 4016h many thousand times, and hoping that the reads will collide with DMC and do produce the glitch. There might be some risk that DMC occurs only in the gaps between the reads; but I've inserted an extra 1-cycle delay in the first half of each test - so timings should "shift" somehow, and it would very bad luck (if not impossible) if the DMC still fits into gaps.

On my PAL NES, the DMC related results are:
Code:
PPU READ WITH DMC      :OK
JOY READ WITH DMC      :OK
PPU READ WITHOUT DMC   :OK
JOY READ WITHOUT DMC   :OK

With "OK" meaning that no glitch has occurred.

Tepples has run the test on a NTSC NES:
Code:
PPU READ WITH DMC      :FAIL    FAIL    FAIL
JOY READ WITH DMC      :OK      OK      OK
PPU READ WITHOUT DMC   :OK      OK      OK
JOY READ WITHOUT DMC   :OK      OK      OK

Here, the "FAIL" in first line means that the PPU read has collided with DMC, and produced the glitch as expected. I don't know why the JOY read in second line passed OK, maybe I've been doing something wrong there, theoretically the 1st+2nd ones should both fail or both pass.

Anyways, there seems to be different behaviour upon DMC reads on my PAL NES and tepples NTSC NES. The difference might be PAL-vs-NTSC related, or old-vs-new APU chip version related. Or it might be because my test program is crap.
Did anybody else ever notice such differences? And are there are other test programs that could be used to verify this?
Re: DPCM generates extra $4016 read pulse
by on (#99836)
nocash wrote:
be PAL-vs-NTSC related, or old-vs-new APU chip version related. Or it might be because my test program is crap.
Did anybody else ever notice such differences? And are there are other test programs that could be used to verify this?

Yes, others (me included) have verified that PAL NES doesn't have this bug (assuming none of the early ones have other chip revisions...). See viewtopic.php?p=36661#p36661
Re: DPCM generates extra $4016 read pulse
by on (#99843)
Argh, if I'd have known that before then it'd have saved me some hours. Well, then it's double-checked that the DMC glitch doesn't occur on all APUs :-) Thanks for confirming that!
But it was never fixed for newer NTSC APUs, or was it?
Would be also interesting if it occurred on old PAL APUs.

The CPU/APU itself doesn't have a clear date code, but CIC and logic chips on the mainboard have YYWW (year/week) date codes, so one can assume that the APU chip was manufactured around the same date. My DMC-glitch-free PAL console has date codes 9122, 9125, 9133.
Re: DPCM generates extra $4016 read pulse
by on (#99893)
Test it on a toploader, if any system would be fixed it'd be a toploader.