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 void updateRumbleFrame();
|
||||||
extern bool systemCanChangeSoundQuality();
|
extern bool systemCanChangeSoundQuality();
|
||||||
extern void systemShowSpeed(int);
|
extern void systemShowSpeed(int);
|
||||||
extern void system10Frames(int);
|
extern void system10Frames();
|
||||||
extern void systemFrame();
|
extern void systemFrame();
|
||||||
extern void systemGbBorderOn();
|
extern void systemGbBorderOn();
|
||||||
extern void Sm60FPS_Init();
|
extern void Sm60FPS_Init();
|
||||||
|
|
|
@ -5016,7 +5016,7 @@ void gbEmulate(int ticksToStop)
|
||||||
gbSoundTick(soundTicks);
|
gbSoundTick(soundTicks);
|
||||||
|
|
||||||
if ((gbFrameCount % 10) == 0)
|
if ((gbFrameCount % 10) == 0)
|
||||||
system10Frames(60);
|
system10Frames();
|
||||||
|
|
||||||
if (gbFrameCount >= 60) {
|
if (gbFrameCount >= 60) {
|
||||||
uint32_t currentTime = systemGetClock();
|
uint32_t currentTime = systemGetClock();
|
||||||
|
@ -5224,7 +5224,7 @@ void gbEmulate(int ticksToStop)
|
||||||
gbSoundTick(soundTicks);
|
gbSoundTick(soundTicks);
|
||||||
|
|
||||||
if ((gbFrameCount % 10) == 0)
|
if ((gbFrameCount % 10) == 0)
|
||||||
system10Frames(60);
|
system10Frames();
|
||||||
|
|
||||||
if (gbFrameCount >= 60) {
|
if (gbFrameCount >= 60) {
|
||||||
uint32_t currentTime = systemGetClock();
|
uint32_t currentTime = systemGetClock();
|
||||||
|
|
|
@ -3859,7 +3859,7 @@ void CPULoop(int ticks)
|
||||||
systemFrame();
|
systemFrame();
|
||||||
|
|
||||||
if ((count % 10) == 0) {
|
if ((count % 10) == 0) {
|
||||||
system10Frames(60);
|
system10Frames();
|
||||||
}
|
}
|
||||||
if (count == 60) {
|
if (count == 60) {
|
||||||
uint32_t time = systemGetClock();
|
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();
|
uint32_t time = systemGetClock();
|
||||||
if (!wasPaused && autoFrameSkip) {
|
if (!wasPaused && autoFrameSkip) {
|
||||||
|
@ -2099,7 +2099,7 @@ void system10Frames(int rate)
|
||||||
int speed = 100;
|
int speed = 100;
|
||||||
|
|
||||||
if (diff)
|
if (diff)
|
||||||
speed = (1000000 / rate) / diff;
|
speed = (1000000 / 60) / diff;
|
||||||
|
|
||||||
if (speed >= 98) {
|
if (speed >= 98) {
|
||||||
frameskipadjust++;
|
frameskipadjust++;
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
#include "../common/SoundSDL.h"
|
#include <algorithm>
|
||||||
#include "config/game-control.h"
|
|
||||||
#include "config/option-proxy.h"
|
|
||||||
#include "wxvbam.h"
|
|
||||||
#include "SDL.h"
|
|
||||||
#include <wx/ffile.h>
|
#include <wx/ffile.h>
|
||||||
#include <wx/generic/prntdlgg.h>
|
#include <wx/generic/prntdlgg.h>
|
||||||
#include <wx/print.h>
|
#include <wx/print.h>
|
||||||
#include <wx/printdlg.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
|
// These should probably be in vbamcore
|
||||||
int systemVerbose;
|
int systemVerbose;
|
||||||
|
@ -469,43 +472,55 @@ void systemShowSpeed(int speed)
|
||||||
|
|
||||||
int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||||
|
|
||||||
void system10Frames(int rate)
|
void system10Frames() {
|
||||||
{
|
|
||||||
GameArea* panel = wxGetApp().frame->GetPanel();
|
GameArea* panel = wxGetApp().frame->GetPanel();
|
||||||
int fs = frameSkip;
|
int fs = frameSkip;
|
||||||
|
|
||||||
if (fs < 0) {
|
if (fs < 0) {
|
||||||
// I don't know why this algorithm isn't in common somewhere
|
// We keep a rolling mean of the last second and use this value to
|
||||||
// as is, I copied it from SDL
|
// 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 uint32_t prevclock = 0;
|
||||||
static int speedadj = 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)) {
|
const uint32_t timestamp = systemGetClock();
|
||||||
int speed = t == prevclock ? 100 * 10000 / rate - (t - prevclock) : 100;
|
|
||||||
|
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??
|
// why 98??
|
||||||
if (speed >= 98)
|
if (speed >= 98)
|
||||||
speedadj++;
|
speedadj++;
|
||||||
else if (speed < 80)
|
else if (speed < 80)
|
||||||
speedadj -= (90 - speed) / 5;
|
speedadj -= (90 - speed) / 10;
|
||||||
else
|
else
|
||||||
speedadj--;
|
speedadj--;
|
||||||
|
|
||||||
if (speedadj >= 3) {
|
if (speedadj >= 3) {
|
||||||
speedadj = 0;
|
speedadj = 0;
|
||||||
|
systemFrameSkip = std::max(systemFrameSkip - 1, 0);
|
||||||
if (systemFrameSkip > 0)
|
|
||||||
systemFrameSkip--;
|
|
||||||
} else if (speedadj <= -2) {
|
} else if (speedadj <= -2) {
|
||||||
speedadj += 2;
|
speedadj += 2;
|
||||||
|
systemFrameSkip = std::min(systemFrameSkip + 1, 9);
|
||||||
if (systemFrameSkip < 9)
|
|
||||||
systemFrameSkip++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prevclock = t;
|
prevclock = timestamp;
|
||||||
panel->was_paused = false;
|
panel->was_paused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue