I was playing around with some timed code, that is acting erratically... which didn't make any sense, until I turned off music updates...fixed it..
Then it occurred to me that maybe DMC playback is the issue, because the screen also shakes (I'm doing midscreen PPU writes) exactly when the DMC sample plays.
Then I looked at the wiki, which says (for DMC)...
"The CPU is stalled for up to 4 CPU cycles" when its buffer is empty.
Am I understanding this correctly? Or am I barking up the wrong tree?
dougeff wrote:
Am I understanding this correctly?
Yes, the DMC unit will stall the CPU every now and then to fetch a new sample byte. How often, depends on the DMC rate (frequency) of the sample that is being played.
DMC DMA can definitely affect the timing of cycle-counted code, because it "steals" cycles from the CPU. You'll either have to use timer or scanline IRQs, or not use DMC at all.
Just for completeness, a list of all ways it can affect the CPU:
- 1. Whenever the DMC reads a new byte the CPU halts for a few cycles.
- 2. If a DMC byte fetch coincides with a read from $4016/4017/2007 (controllers or PPU), that read will be corrupted.
- 3. The DMC can produce an IRQ.
- 4. The DMC bit in $4015 can be polled to find out when a sample stops.
OK, I'm trying to make this game a little better / more interesting...added cool special effect. Let me know what you think. Thanks.
(ROM removed, see official thread for link).
This is the gist of the code, btw...
Code:
ldy scanlineToRepeat
ldx scanlineToRepeat
...
-
lda #0
sta $2006
sty $2005 ;y
sta $2005 ;x = 0
tya
and #$f8
asl a
asl a
sta $2006
jsr Timed100 ;waits a bit
dex ;2
bne -
...
dec scanlineToRepeat
There's a little more to it, but this is the basics.
Even if there's nothing wrong with the code itself, as long as you're playing DMC samples, the CPU will occasionally pause in order to fetch sample bytes from ROM, screwing up the timing of any timed code you might be running. AFAIK, there's no way to compensate for that manually, so you need more reliable ways to keep track of time (e.g. mapper IRQs). I would just think of other effects that don't need such timing precision.
Oh, I gutted the DMC off that song, and won't have any on the final song.
tokumaru wrote:
Even if there's nothing wrong with the code itself, as long as you're playing DMC samples, the CPU will occasionally pause in order to fetch sample bytes from ROM, screwing up the timing of any timed code you might be running. AFAIK, there's no way to compensate for that manually
Knowing the sample rate, and when the sample begins/ends, should be enough to predict when the CPU will stall. You would need different timing for every sample rate (and for once we can be grateful that there's only 16). I don't know how accurate it could be, but surely it's enough to stop the timing error from accumulating over the course of the frame. I think the Years Behind demo might have done something like this.
Memblers wrote:
Knowing the sample rate, and when the sample begins/ends, should be enough to predict when the CPU will stall.
It was my understanding that the stall is a variable number of cycles depending on where it falls, as per
Blargg's post about it. I think there's also a lot of difficulty getting it to start on a specific cycle too.
As far as I know, the DMC channel doesn't even have a consistent startup state for its timers, so it can even vary between power ons. Try playing some Blades of Steel and watching the demo.