1: Simple question first. After writing to 0x4010 (or 0x400e for that matter), will the next action start rightaway, or will it wait a few cycles, specified in the lsb's, before doing the next action ?
2: Let's say that a sprite DMA transfer starts at (relative) CPU cycle 0, and it ends at cycle 512. The next APU frame sequencer update is expected at cycle 8. DMC updates are expected at cycle 4, and at intervals of 0x036.
What's the behaviour of the APU during sprite DMA ? I can think of the following:
- APU runs in parallel with the CPU (this would be messy if the DMC wanted a DMA too)
- like the CPU, since the APU is built into the CPU, APU is suspended for 513 cycles, and thus the next APU frame sequencer update will happen at cycle 520, and DMC at cycle 516.
- the APU is ignored, so the next frame sequencer update is at cycle 7500 or so.
I can't really give you a definative answer -- after all I can only speculate. So I can't really say for certain that anything I say in this post is accurate, it's just my understanding.
1)
Writes take effect immediately. I think it's safe to assume the DMC has the same kind of frequency count down thing the other channels do, so changing $4010 while the DMC is playing would change the freq reload value immediately (ditto for $400E and noise).
2)
Since the pAPU is part of the CPU, it runs alongside the CPU. When the CPU halted by the PPU (or the DMC or anything else), the pAPU keeps running normally and is unaware of the suspension. I'm no hardware man, but it seems completely logical that the CPU is still running like normal (so the APU runs as normal) -- however memory fetches cannot be done (bus is occupied by PPU?). This would halt the 6502 area of the CPU (since every cycle needs to either read or write a byte from/to addressing space) -- however the APU does not need to make any memory accesses (outside of DMC DMA), so it couldn't care less if memory accesses are being made by the PPU.
Of your 3 choices listed, I'd put all my money on the first. The second would cause noticable audio distortion every frame (where Spr-DMA is done while sound is playing --- which is like EVERY frame in EVERY game). The 3rd option would cause distortion as well, but less noticable -- and could potentially break expected program flow (if, for example, a frame IRQ was not triggered when expected due to this occurance).
In the case where DMC and Sprite DMAs conflict, I can only assume the DMC DMA would have higher priority since it's more time-sensitive, involves a shorter delay, and it would be more noticable if it wasn't completed in time.
Good question. I'll have to add that to the things to test whenever I get around to finishing a final APU reverse-engineer.
I ran some tests of this a while back. Here is the result I reported (in e-mail to someone):
I tried running a DMC sample while constantly writing 0 to $4014 (and verified that the writes were initiating DMA and suspending the CPU), but the DMC's output wasn't affected.
Maybe the DMC's DMA unit accesses memory on odd cycles when the sprite DMA is writing to video RAM, or just waits until the sprite DMA is done. At maximum frequency, the DMC output unit needs a byte every 432 clock cycles, somewhat fewer cycles than the sprite DMA takes, but (in most cases) the sample buffer can keep the output unit happy until DMA unit can refill the buffer when the sprite DMA completes.
But the sample buffer wouldn't help in the case where the output shifter is just about empty when the DMA transfer is initiated. Soon after the sample buffer would be emptied, and then needed full 432 clocks later, before the DMA transfer is done.
Or maybe the DMC fetch has first priority, and OAM DMA has second priority. If so, it would match the priorities seen on one of Nintendo's later systems. Most commonly, the Game Boy Advance's four DMA channels are split up like so:
GBA DMA[0]: Raster effects
GBA DMA[1]: Audio left channel
GBA DMA[2]: Audio right channel
GBA DMA[3]: Memory copies (such as OAM DMA)