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

Changing DMC Rate

Changing DMC Rate
by on (#179738)
I've been experimenting with using DMC irqs for video timing, but I can't figure out how to change the sample rate cleanly. The rates of different samples seem to bleed into each other.

Context: These links have a bunch of information that people have figured out:

I am trying to create a variable-length scanline counter. I wanted to extend Bregalad's post here. It only uses 2 samples: one to synchronize with the APU DMC clock, and one for timing. Unfortunately, it has a large gap from 31-64 scanlines, which can require up to 32 scanlines of busy-waiting.

That can be solved by using up to 3 samples. The full method looks like this:
1. Start a sample, length 0, rate $F. Count how long it takes to fire in order to synchronize later
2. Change the length and rate for the first timing sample
3. When that fires, change the length and rate for the second sample
4. When the second irq fires, wait a variable amount to synchronize with NMI

I have this implemented and it is rock solid -- only about +- 4 pixels of jitter, more than enough to fit a raster effect in vblank. However, the samples are not playing at the speed I expect. Here's what I mean by samples bleeding into each other (all times for NTSC):

A sample at rate $F which comes directly after a sample at rate $F will take 432 cycles, exactly as expected.
A sample at rate $F just after one at rate $0 will take over 800 cycles.
A sample at rate $0 just after one at rate $F will take only 2672 cycles, instead of the expected 3424

I can reduce the effect by setting the new $4010 sample rate as soon as possible in each irq handler, but it there a way to eliminate it altogether?