SMB skipping frames

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
dragonwarrior
Posts: 22
Joined: Sat Feb 01, 2025 3:30 pm

SMB skipping frames

Post by dragonwarrior »

I added a short clip showing how it looks like my emulator is skipping frames. In the beginning of the clip, it plays out fine, but I get to a point where the time just goes crazy fast. In some other areas, it's normal again.

I'm not sure what the cause could be, but I'd appreciate any input.
Attachments
SMB.mp4
(2.25 MiB) Downloaded 45 times
User avatar
TakuikaNinja
Posts: 219
Joined: Mon Jan 09, 2023 6:42 pm
Location: New Zealand
Contact:

Re: SMB skipping frames

Post by TakuikaNinja »

Maybe something in your program flow is causing the frame pacing (i.e. waiting before/after presenting the framebuffer to the graphics library/framework) to be skipped?
User avatar
Dwedit
Posts: 5126
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: SMB skipping frames

Post by Dwedit »

This is more about how to do the advancing of time in general.
One problem is that displays are usually around 60 FPS, and the NES is 60.098FPS, so they'll go out of sync eventually. If the monitor is slower, eventually frames will need to be dropped. If the monitor is faster, eventually frames will need to be repeated.

Initially:
You find out what time it is using a very precise timer. That is your reference time for the first frame.
Your next frame is scheduled to happen 1000/60.098ms later.

In general:
All calculation of the next scheduled timestamp is done relative to the scheduled timestamp of the current frame. Not the current time, but the scheduled time.
But if your time is off by more than 4 frames, you'd need to resynchronize.
When you present/swapbuffers a frame with vsync enabled, it will take around a frame worth of time before the code returns.
After you present:
- Is there time remaining before you would reach the scheduled time? You'll need to wait for the scheduled time to happen.
- Did you already reach the scheduled time? You won't need to wait.
- Is current time more than 2 frametimes past the scheduled time? Drop a frame (skip presenting it)
- Are you more than 4 frametimes away from the scheduled time? You're out of sync, maybe someone put their computer to sleep or something. You'll need to resynchronize, meaning scheduled time becomes relative to Now rather than the past scheduled time.

How to wait on Windows:
Use the Waitable Timers API. Before doing anything else, you create the waitable timer, and increase timer precision (the undocumented function NtSetTimerResolution can set timer resolution in units of 100ns)
Each time you want to wait, you set the target timestamp of the timer, then WaitForSingleObject on the timer.

How to wait on Posix/Linux:
Haven't tried this but I think you get the current time (monotonic), then use nanosleep.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
Quietust
Posts: 1983
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: SMB skipping frames

Post by Quietust »

Alternatively, since most NES emulators will eventually need to play audio, you can use the technique of synchronizing your speed to audio playback - since you know exactly how fast the CPU is supposed to run, you can have it generate the correct number of audio samples for each set of CPU cycles and then add them to a playback buffer which gradually empties in the background as the sound gets played through your speakers, and whenever that buffer becomes full you can sleep for a few milliseconds and wait until there's enough room available.

One downside to this technique is that it might not work well with options such as VSync.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
Post Reply