FCEUX overclocking

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
FCEUX overclocking
by on (#147756)
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...
Re: Freeze and then resume DMC activity
by on (#147768)
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.
Re: Freeze and then resume DMC activity
by on (#147771)
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
by on (#147817)
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
by on (#147845)
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.
Re: Freeze and then resume DMC activity
by on (#147858)
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.

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.
Code:
1 2 3, 4 5 6, 7 8 9, - normally
12345, 45678, 789  , - overclocked

It sends more samples due to having more time per frame for that, then after NMI it jumps back and clips, distorting everything. And it does look like the game forces certain samples to go exactly first after NMI, like here it's always 1, 4, and 7. If it's possible to make it send
Code:
123 , 456 , 789  ,

then I win.

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
by on (#147895)
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.
Re: Freeze and then resume DMC activity
by on (#147901)
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.
Re: Freeze and then resume DMC activity
by on (#147904)
Every 7-bit sample ends somewhere. They're not so heavily used that I never catch up.
Re: Freeze and then resume DMC activity
by on (#147917)
feos wrote:
Every 7-bit sample ends somewhere. They're not so heavily used that I never catch up.

[opens IDE] How long is your buffer?
Re: Freeze and then resume DMC activity
by on (#147919)
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.
Re: Freeze and then resume DMC activity
by on (#147974)
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.
Re: Freeze and then resume DMC activity
by on (#147976)
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
by on (#147992)
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.
Re: Freeze and then resume DMC activity
by on (#147994)
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.
Re: Freeze and then resume DMC activity
by on (#148007)
Can your emulator play the Rick Rolled! demo?
Re: Freeze and then resume DMC activity
by on (#148041)
tepples wrote:
Can your emulator play the Rick Rolled! demo?

It's now optional :)
Config -> Timing.

Also, I couldn't set it up for new PPU at all, so I blocked overclocking for it.
Re: Freeze and then resume DMC activity
by on (#148066)
I've set 999 extra scanlines.
Tepples's overclock test rom shows 1264 lines/frame ;)
Re: Freeze and then resume DMC activity
by on (#148096)
7-bit samples still can't be properly played at high overclocking. I can only limit PPU loops before they start, checking if 7-bit is already playing. If I check it during PPU loop itself and break it, there are clips.

So it has to be checked only before the loop, and then it's up to user to set proper value for extra scanlines. BTDD samples play okay at 90 maximum, but TMNT3 needs 200 in 2-1.
Re: FCEUX overclocking
by on (#148105)
Works really well! Armadillo is a lot more playable once you remove the slowdown that plagues that game.
Re: Freeze and then resume DMC activity
by on (#154953)
Drag wrote:
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.


I imagine few NES games don't wait for vertical blank at the end of every frame. The only case I can think of where you might not do it is when you're writing PCM audio to the DPCM delta counter, and few games did that.
Re: FCEUX overclocking
by on (#154961)
If by "few" you mean "quite a few", I'll agree. Off the top of my head, I can think of Skate or Die 2, The Three Stooges, all Wheel of Fortune games, Joshua, Big Bird's Hide and Speak, Countdown, SCAT, Blades of Steel, Action 52 menu, Mito Koumon 1 and 2, and I think the US version of Bases Loaded. I wrote decompression tools for many of these several years ago. And when I used to hang out on Pocket Heaven years ago, I gained kind of a reputation for reminding the PocketNES developers that Big Bird's Hide and Speak still didn't work.
Re: FCEUX overclocking
by on (#154985)
Considering the huge library of NES games, that really isn't a lot, and most people aren't interested in most of those games. I'm not saying they're not worth supporting if possible, but I think most people really won't mind if a minor emulator feature isn't compatible with those games.

It's also only relevant when PCM audio is being played. At other times the game will probably wait for vblank like normal.

Hypothetically you could add an option to disable overclocking for frames where $4011 is written to directly, although in a few games this will be triggered at inappropriate times, such as the percussion in FF3's music. But the player probably won't mind if these games aren't overclocked.
Re: FCEUX overclocking
by on (#155000)
furrykef wrote:
Hypothetically you could add an option to disable overclocking for frames where $4011 is written to directly, although in a few games this will be triggered at inappropriate times, such as the percussion in FF3's music. But the player probably won't mind if these games aren't overclocked.

Yeah, hypothetically.
Re: FCEUX overclocking
by on (#155003)
I guess an emulator could detect more than 10 writes to $4011 in a frame and disable the extra post-render lines for that frame.