Fix automatic dynamic frame skipping
The previously used algorithm was too aggressive. This fixes the issue by using the last second data and using a more gentle adjustment curve to prevent huge changes in frame skipping.
This commit is contained in:
parent
d1733c4505
commit
f1d3f631d2
|
@ -76,7 +76,7 @@ extern void systemPossibleCartridgeRumble(bool);
|
|||
extern void updateRumbleFrame();
|
||||
extern bool systemCanChangeSoundQuality();
|
||||
extern void systemShowSpeed(int);
|
||||
extern void system10Frames(int);
|
||||
extern void system10Frames();
|
||||
extern void systemFrame();
|
||||
extern void systemGbBorderOn();
|
||||
extern void Sm60FPS_Init();
|
||||
|
|
|
@ -5016,7 +5016,7 @@ void gbEmulate(int ticksToStop)
|
|||
gbSoundTick(soundTicks);
|
||||
|
||||
if ((gbFrameCount % 10) == 0)
|
||||
system10Frames(60);
|
||||
system10Frames();
|
||||
|
||||
if (gbFrameCount >= 60) {
|
||||
uint32_t currentTime = systemGetClock();
|
||||
|
@ -5224,7 +5224,7 @@ void gbEmulate(int ticksToStop)
|
|||
gbSoundTick(soundTicks);
|
||||
|
||||
if ((gbFrameCount % 10) == 0)
|
||||
system10Frames(60);
|
||||
system10Frames();
|
||||
|
||||
if (gbFrameCount >= 60) {
|
||||
uint32_t currentTime = systemGetClock();
|
||||
|
|
|
@ -3859,7 +3859,7 @@ void CPULoop(int ticks)
|
|||
systemFrame();
|
||||
|
||||
if ((count % 10) == 0) {
|
||||
system10Frames(60);
|
||||
system10Frames();
|
||||
}
|
||||
if (count == 60) {
|
||||
uint32_t time = systemGetClock();
|
||||
|
|
|
@ -1896,7 +1896,7 @@ void systemShowSpeed(int)
|
|||
{
|
||||
}
|
||||
|
||||
void system10Frames(int)
|
||||
void system10Frames()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -2091,7 +2091,7 @@ void systemFrame()
|
|||
{
|
||||
}
|
||||
|
||||
void system10Frames(int rate)
|
||||
void system10Frames()
|
||||
{
|
||||
uint32_t time = systemGetClock();
|
||||
if (!wasPaused && autoFrameSkip) {
|
||||
|
@ -2099,7 +2099,7 @@ void system10Frames(int rate)
|
|||
int speed = 100;
|
||||
|
||||
if (diff)
|
||||
speed = (1000000 / rate) / diff;
|
||||
speed = (1000000 / 60) / diff;
|
||||
|
||||
if (speed >= 98) {
|
||||
frameskipadjust++;
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
#include "../common/SoundSDL.h"
|
||||
#include "config/game-control.h"
|
||||
#include "config/option-proxy.h"
|
||||
#include "wxvbam.h"
|
||||
#include "SDL.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/generic/prntdlgg.h>
|
||||
#include <wx/print.h>
|
||||
#include <wx/printdlg.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#include "../common/SoundSDL.h"
|
||||
#include "config/game-control.h"
|
||||
#include "config/option-proxy.h"
|
||||
#include "wxvbam.h"
|
||||
|
||||
// These should probably be in vbamcore
|
||||
int systemVerbose;
|
||||
|
@ -469,43 +472,55 @@ void systemShowSpeed(int speed)
|
|||
|
||||
int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
void system10Frames(int rate)
|
||||
{
|
||||
void system10Frames() {
|
||||
GameArea* panel = wxGetApp().frame->GetPanel();
|
||||
int fs = frameSkip;
|
||||
|
||||
if (fs < 0) {
|
||||
// I don't know why this algorithm isn't in common somewhere
|
||||
// as is, I copied it from SDL
|
||||
// We keep a rolling mean of the last second and use this value to
|
||||
// adjust the systemFrameSkip value dynamically.
|
||||
|
||||
// Target time in ms for 10 frames at 60 FPS.
|
||||
constexpr int kTarget = 10 * 1000 / 60;
|
||||
|
||||
static uint32_t prevclock = 0;
|
||||
static int speedadj = 0;
|
||||
uint32_t t = systemGetClock();
|
||||
static int last_second[6] = {kTarget, kTarget, kTarget,
|
||||
kTarget, kTarget, kTarget};
|
||||
static size_t last_index = 0;
|
||||
|
||||
if (!panel->was_paused && prevclock && (t - prevclock) != (uint32_t)(10000 / rate)) {
|
||||
int speed = t == prevclock ? 100 * 10000 / rate - (t - prevclock) : 100;
|
||||
const uint32_t timestamp = systemGetClock();
|
||||
|
||||
if (!panel->was_paused && prevclock) {
|
||||
last_second[last_index] = systemGetClock() - prevclock;
|
||||
last_index = (last_index + 1) % 6;
|
||||
|
||||
int average = 0;
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
average += last_second[i];
|
||||
}
|
||||
average /= 6;
|
||||
|
||||
const int speed = (kTarget * 100) / average;
|
||||
|
||||
// why 98??
|
||||
if (speed >= 98)
|
||||
speedadj++;
|
||||
else if (speed < 80)
|
||||
speedadj -= (90 - speed) / 5;
|
||||
speedadj -= (90 - speed) / 10;
|
||||
else
|
||||
speedadj--;
|
||||
|
||||
if (speedadj >= 3) {
|
||||
speedadj = 0;
|
||||
|
||||
if (systemFrameSkip > 0)
|
||||
systemFrameSkip--;
|
||||
systemFrameSkip = std::max(systemFrameSkip - 1, 0);
|
||||
} else if (speedadj <= -2) {
|
||||
speedadj += 2;
|
||||
|
||||
if (systemFrameSkip < 9)
|
||||
systemFrameSkip++;
|
||||
systemFrameSkip = std::min(systemFrameSkip + 1, 9);
|
||||
}
|
||||
}
|
||||
|
||||
prevclock = t;
|
||||
prevclock = timestamp;
|
||||
panel->was_paused = false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue