FCEUX overclocking
Moderator: Moderators
FCEUX overclocking
I'm trying to overclock the emulated NES CPU by adding dummy scanlines, that gives more time for the game to handle events that were causing lag.
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, 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...
Last edited by feos on Sun May 24, 2015 12:51 am, edited 1 time in total.
Re: Freeze and then resume DMC activity
Okay, let's say you wanted to add 262 dummy scanlines before vblank starts, for a nice 2x speed mode.
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.
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.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
- rainwarrior
- Posts: 8758
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Freeze and then resume DMC activity
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.
Re: Freeze and then resume DMC activity
Adding more post-render lines, increasing the master clock frequency, and running the APU on a slower clock (such as CPU/3 or CPU/4 instead of CPU/2) would still probably break Time Lord, Fire Hawk, MiG, and my DPCM Letterbox demo. But unless more homebrew games start using this technique, those might be acceptable collateral damage. Just don't try to autodetect those games by hash to disable overclocking, or you might run into Nintendo's patent on enabling emulation hacks by hashing the ROM.
Re: Freeze and then resume DMC activity
Isn't it a given that changing timing specifications is going to break any kind of programming that relies on the spec being unchanged? Just look at early dos games like Bouncing Babies which become unplayable as CPU speeds increase, with certain manufacturers going as far as adding a "turbo" switch on the PC to flip the clock speed between a compatible one and a fast one.
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.
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.
Re: Freeze and then resume DMC activity
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.
Re: Freeze and then resume DMC activity
Okay, I disabled DMA entirely after scanline 240. And it fixed 1-bit samples! But 7-bit ones are sent by the game manually, and it's even known now that the same 7-bit sample on NES and on Dendy takes different amount of frames! But it runs with similar real-time speed.
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.
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.
- rainwarrior
- Posts: 8758
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Freeze and then resume DMC activity
If you buffer them you'll end up in a deficit. The game will be writing new ones each frame and you'll never catch up.
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.
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.
Re: Freeze and then resume DMC activity
Every 7-bit sample ends somewhere. They're not so heavily used that I never catch up.
Re: Freeze and then resume DMC activity
[opens IDE] How long is your buffer?feos wrote:Every 7-bit sample ends somewhere. They're not so heavily used that I never catch up.
- rainwarrior
- Posts: 8758
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Freeze and then resume DMC activity
Aside from the possibility of infinitely long PCM streams, buffering a backlog means that you're presenting the sound after it's intended. Any way you do it, there will be strange consequences on one side or the other. I don't think there's a trivial way to solve 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.
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.
Re: Freeze and then resume DMC activity
Yep, this is exactly what I decided to do too. So is writing to $4011 the way to know if it's a 7-bit sample? I don't need to work around 1-bit ones at all.
- rainwarrior
- Posts: 8758
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Freeze and then resume DMC activity
Well, some music engines will write $4011 before starting a DPCM sample, or for other purposes, but this would be part of the music playback anyway, probably at the start of the frame. If a $4011 occurs so late in the frame that it's actually into your extra scanlines, I would be incredibly surprised if it was anything but PCM sample playback.
Re: Freeze and then resume DMC activity
I didn't even find on wiki how much does 7-bit sample differ from 1-bit one. It's only said that manual samples fill the counter directly as they please.
- rainwarrior
- Posts: 8758
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Freeze and then resume DMC activity
What are you expecting to find on the wiki about it?
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.
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.