First, if you simply add scanlines to the PPU loop, you end up getting an overall slowdown, this is how Dendy was created. Then, to compensate the slowdown, we speed up it again to 60 fps. It causes the FCEUX sound driver to replay the extra samples at 2x speed, because sound channels generate more samples than during a normal NTSC frame. I can prevent it by simply not letting them increment the destination those samples are written to, so all the 4 channels don't append anything to the wave buffer after scanline 240.
But DMC is an exception, it keeps writing its stream no matter what, and if I freeze the destination for it after scanline 240, it skips parts of the stream as the new frame starts, which breaks the sound.
So I need to make it freeze sample stream replay at scanline 240, and resume it from the same place the next frame. From docs it kind of seems possible by messing with Status register and maybe something else, but I need to know how exactly, as writing 0 to DMC bit of $4015 after scanline 240 does nothing good.
From the looks of it, I need to write 0 to that bit, but somehow prevent "bits remaining" becoming zero, so that it's resumed afterwards...
First, you sacrifice compatibility with Time Lord, Mig Soviet Fighter, Fire Hawk, etc, those need accurate frame and DMC timings. Then you sacrifice compatibility with games that auto-detect NTSC/PAL region (Codemasters games). Then you sacrifice streaming PCM sound, that would end up getting played at double speed.
I'd probably just double the number of cycles in square wave, triangle, noise and DMC wave periods, then double the number of cycles for the steps of the frame counter.
Then all sound (except for streaming PCM sound) would be at half frequency, then since you're doubling the speed, you can restore it back to normal frequency.
Suffice to say, this kind of mod is going to break certain games, but the games it won't break will benefit from less slowdown, possibly with dirty scanlines on games that use mapper-based scanline counters.
I tried and... it doesn't change anything! I'm not rebuilding the table, I'm multiplying the value it reads from it by amount of my scanlines divided by 240. So it seems I do need to pause and resume. Only, would it be possible? Won't the game run too far and send samples too fast again? If you imagine NMI as a comma, and numbers as the samples the game is sending, you'll see what's happening.rainwarrior wrote:What if you just rebuilt the DMC frequency table at initialization, based on the overclock? This way you wouldn't need to pause and resume anything, the unit would just take more clocks per sample.
Code: Select all
1 2 3, 4 5 6, 7 8 9, - normally 12345, 45678, 789 , - overclocked
Code: Select all
123 , 456 , 789 ,
Also, the games you guys mentioned don't seem to be broken. It's similar to Dendy, I didn't edit scanlines_per_frame variable that's 262, I edited the PPU loop count that's 240 for NTSC and 290 for Dendy.
I think I have the only way to solve it now: write what the game sends me to some temporary buffer, and then send it to the main audio buffer with NTSC rate.
Unless it's done with an IRQ, PCM samples are dependent on the CPU speed. If you're overclocking, they should play faster. I don't think there's a way around this.
The extra scanlines thing is effectively overclocking the CPU w.r.t. framerate without having to put overclocking consequences on the APU or PPU. The PPU is effectively paused outside of the rendering area. I think pausing the whole APU (not just DMC) is probably a better way to go than my other suggestion about rescaling the DMC frequencies. I suppose you also want to pause any IRQ generating devices during the extra scanlines too, in case they expect to be reset earlier.
Here's an idea for PCM, though, which ties in with the idea of everything but CPU being paused: skip the remaining extra scanlines if you get a $4011 write while everything else is paused. Basically, disable the overclocking of the CPU for any frame where it's playing samples. This will keep the samples coming out at the right speed (and you won't be messing with the APU while it's supposed to be paused), and it will keep the length of the sample synchronized with the frames it's supposed to play on.
DPCM samples are what the hardware supports.
PCM samples are just a software technique. $4011 is just direct access to the DAC, and you can dump anything you want through there.