Methods for (re)starting of DMC playback?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Methods for (re)starting of DMC playback?
by on (#57641)
So I've been working on my DMC implementation. I think it is fairly complete and seems to be working pretty well, but I have this nasty little bug that I can't figure out.

When I play bomberman I hear the explosions. When I play Kung Fu I hear the grunts/laughs. But when I play Duck Hunt I hear 1 "arf!" and that's it - no more. When you first start the game the dog actually barks 3 times in a row, but I only ever hear 1 bark.

On the very first bark, if I watch registers $4010-$4013 and $4015, I see the DMC Enable flag (bit 4 of $4015) get set to 1. This causes the DMC to start playback as the the Wiki says it should. But after this initial bit set the DMC Enable is never cleared and set again to cause playback to (re)start.

The only DMC-related registers which are written to following the first bark are $4012 (sample address) and the $4010 frequency index bits. Is writing different values to these registers supposed to (re)start playback somehow? If so, there is no mention of it in any DMC RE'ing documents that I could find. I think I must be missing some critical information about the DCM.... :(

Also, I can see in register $4010 that the DMC Loop flag and DMC Interrupt Enable flag are _not_ set. So this is not a looping problem and its not an interrupt problem.

The only way I know of that the DMC can be manually (re)started (from looking at the documentation I have) is by changing bit 4 of $4015 from 0 to 1. Is there some other way?

Also, if anyone knows if the 3 barks is actually a single "track" of 3 barks or if it is simply 1 bark repeated 3 times that might help me a little bit in my debugging... I am currently assuming it is the same bark "data" repeated 3 times (since it would require the least memory space) but that might be a bad assumption.

Thanks in advance!

Jonathon :)

by on (#57642)
I can't say for sure because I didn't actually check, so take this with a grain of salt.

If you've ruled out looping the only other thing I can think of is that you're not stopping the DMC at the end of the sample.

The DMC stops itself (ie: it clears $4015.4) when the sample is finished (specifically, iirc it's actually when the last byte of data is fetched). The game can restart the sample by writing 1 to $4015.4 again. It does not have to write zero to $4015.4 if the sample has already stopped.
oh man
by on (#57643)
Quote:
The DMC stops itself (ie: it clears $4015.4) when the sample is finished...


Oh my gosh, I am totally not doing this!! Will fix now and get back to you!

THANKS SO MUCH!!
clarification
by on (#57644)
I haven't finished implemented the fix yet, but can you tell me if I'm still supposed to clear the DMC enable bit in $4015 if the Loop flag in $4010 is set?

The reason I ask is because, according to the Wiki and Blargg's apu_ref.txt doc, the interrupt flag should not be asserted when playback completes if the loop flag is set. So I'm wondering if there is a similar condition for clearing the DMC enable bit when playback completes.

Thanks!!

by on (#57645)
Disch is the man! That fixed it! I hear barks and quacks like I should now! :)

In my own defense I rechecked the DMC documentation and I still don't see anywhere that tells you to clear bit 4 of $4015 when playback is done. If someone can point me to someplace that states this I'll be happy to eat my words. :) Actually I'll be very happy since it must be some DMC documentation that I don't currently have that I would like to get my hands on. :) Hopefully, someone doesn't point me to a document that I already have...that would be funny.

I'd still like to know (from my previous post) if I should still clear $4015.4 if the Loop flag is set. Right now I am clearing the bit regardless of the loop flag's value.

Thanks again Disch! :)

by on (#57656)
It's covered in the APU status register page. You might keep in mind that $4015 is really two separate registers. There's the control register, which does things when written to. There's the status register, which gives you the current values of things when read. In neither case is there an 8-bit byte that you can write to and read from.

On that page, it states that reading bit 4 reflects whether the DMC's bytes remaining counter is non-zero. A write of 0 to bit 4 sets the bytes remaining to 0, and a write of 1 to bit 4 when bytes remaining is 0 restarts the DMC sample. If I read that correctly, a write of 1 to bit 4 when the bytes remaining is non-zero has no effect. Don't assume anything beyond what you read, like that there's an internal "last value written to bit 4" which is compared with the current value to see whether it's different, or anything like this.

by on (#57658)
blargg's apu ref also says the same thing:

Code:
    ---d nt21   DMC, noise, triangle, square 2, square 1

If d is set and the DMC's DMA reader has no more sample bytes to fetch, the DMC
sample is restarted. If d is clear then the DMA reader's sample bytes remaining
is set to 0.


So yeah I worded it incorrectly in my previous post. It has to do with how many bytes are remaining in the sample.

So therefore, if it's looping, the bytes remaining is never zero because:

Code:
The bytes counter is decremented;
if it becomes zero and the loop flag is set, the sample is restarted (see
above), otherwise if the bytes counter becomes zero and the interrupt enabled
flag is set, the interrupt flag is set.
haha
by on (#57660)
Haha, you know, as I was falling asleep last night I was thinking, "hmmm, I wonder if the answer is on the APU status register page instead of the DMC module page." And yep, there it is just like you said. LOL.

Thanks so much for your help guys! You answered all my questions!! :-D

I will be posting some new video clips on my site soon to demonstrate my DMC working.

Pz!

Jonathon