Config: Store the alternative speeds in percent

The settings screen showed them in percent but they were stored as frame
rates out of 60, so the screen kept converted copies and wrote them back. Now
they're stored in percent under new ini keys (AltSpeedPercent,
AltSpeedPercent2, AnalogAltSpeedPercent), migrated from the old frame rate
keys like the audio volumes were, and converted to a frame rate where the
timing needs one.

Low percentages no longer round to a 0 fps limit, which meant unlimited.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-22 15:28:18 +02:00
1 parent ff3d184b43
commit 71b38e58e6
6 files changed
+54 -34

No files matched your search

+24 -3
View File
@@ -715,6 +715,23 @@ static const ConfigSetting gestureControlSettings[] = {
ConfigSetting("AnalogGestureSensibility", SETTING(g_Config.gestureControls[0], fAnalogGestureSensitivity), 1.0f, CfgFlag::PER_GAME),
};
// The alternative speeds used to be stored as frame rates, out of 60.
static int LegacyFpsLimitToPercent(int fps) {
return fps < 0 ? -1 : (fps * 100 + 30) / 60;
}
static int DefaultAltSpeedPercent1() {
return LegacyFpsLimitToPercent(g_Config.iLegacyFpsLimit1);
}
static int DefaultAltSpeedPercent2() {
return LegacyFpsLimitToPercent(g_Config.iLegacyFpsLimit2);
}
static int DefaultAnalogAltSpeedPercent() {
return LegacyFpsLimitToPercent(g_Config.iLegacyAnalogFpsLimit);
}
static const ConfigSetting graphicsSettings[] = {
ConfigSetting("iShowStatusFlags", SETTING(g_Config, iShowStatusFlags), 0, CfgFlag::PER_GAME),
ConfigSetting("GraphicsBackend", SETTING(g_Config, iGPUBackend), &DefaultGPUBackend, &GPUBackendTranslator::To, &GPUBackendTranslator::From, CfgFlag::DEFAULT | CfgFlag::REPORT),
@@ -744,9 +761,13 @@ static const ConfigSetting graphicsSettings[] = {
ConfigSetting("AutoFrameSkip", SETTING(g_Config, bAutoFrameSkip), IsVREnabled(), CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("StereoRendering", SETTING(g_Config, bStereoRendering), false, CfgFlag::PER_GAME),
ConfigSetting("StereoToMonoShader", SETTING(g_Config, sStereoToMonoShader), "RedBlue", CfgFlag::PER_GAME),
ConfigSetting("FrameRate", SETTING(g_Config, iFpsLimit1), 0, CfgFlag::PER_GAME),
ConfigSetting("FrameRate2", SETTING(g_Config, iFpsLimit2), -1, CfgFlag::PER_GAME),
ConfigSetting("AnalogFrameRate", SETTING(g_Config, iAnalogFpsLimit), 240, CfgFlag::PER_GAME),
// Read before the new settings, which use them as defaults.
ConfigSetting("FrameRate", SETTING(g_Config, iLegacyFpsLimit1), 0, CfgFlag::PER_GAME | CfgFlag::DONT_SAVE),
ConfigSetting("FrameRate2", SETTING(g_Config, iLegacyFpsLimit2), -1, CfgFlag::PER_GAME | CfgFlag::DONT_SAVE),
ConfigSetting("AnalogFrameRate", SETTING(g_Config, iLegacyAnalogFpsLimit), 240, CfgFlag::PER_GAME | CfgFlag::DONT_SAVE),
ConfigSetting("AltSpeedPercent", SETTING(g_Config, iAltSpeedPercent1), &DefaultAltSpeedPercent1, CfgFlag::PER_GAME),
ConfigSetting("AltSpeedPercent2", SETTING(g_Config, iAltSpeedPercent2), &DefaultAltSpeedPercent2, CfgFlag::PER_GAME),
ConfigSetting("AnalogAltSpeedPercent", SETTING(g_Config, iAnalogAltSpeedPercent), &DefaultAnalogAltSpeedPercent, CfgFlag::PER_GAME),
#if PPSSPP_PLATFORM(WINDOWS)
ConfigSetting("RestartRequired", SETTING(g_Config, bRestartRequired), false, CfgFlag::DONT_SAVE),
#endif
+17 -3
View File
@@ -360,9 +360,14 @@ public:
int iTexScalingType; // 0 = xBRZ, 1 = Hybrid
bool bTexDeposterize;
bool bTexHardwareScaling;
int iFpsLimit1;
int iFpsLimit2;
int iAnalogFpsLimit;
// In percent of normal speed. 0 means unlimited, and negative (not for analog) disabled.
int iAltSpeedPercent1;
int iAltSpeedPercent2;
int iAnalogAltSpeedPercent;
// The old frame rate based settings. Only read, to migrate them.
int iLegacyFpsLimit1;
int iLegacyFpsLimit2;
int iLegacyAnalogFpsLimit;
int iMaxRecent;
int iCurrentStateSlot;
int iRewindSnapshotInterval;
@@ -836,6 +841,15 @@ private:
std::string CreateRandMAC();
std::string DefaultProAdhocServer();
// The frame rate limit for an alternative speed. Unlimited (0) and disabled (negative) stay as they are.
inline int AltSpeedPercentToFps(int percent) {
if (percent <= 0) {
return percent;
}
int fps = (percent * 60 + 50) / 100;
return fps < 1 ? 1 : fps;
}
// TODO: Find a better place for this.
extern http::RequestManager g_DownloadManager;
extern Config g_Config;
+2 -2
View File
@@ -424,9 +424,9 @@ static int FrameTimingLimit() {
return 0;
// Can't slow down in hardcore mode.
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
return fixRate(g_Config.iFpsLimit1);
return fixRate(AltSpeedPercentToFps(g_Config.iAltSpeedPercent1));
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
return fixRate(g_Config.iFpsLimit2);
return fixRate(AltSpeedPercentToFps(g_Config.iAltSpeedPercent2));
if (PSP_CoreParameter().fpsLimit == FPSLimit::ANALOG)
return fixRate(PSP_CoreParameter().analogFpsLimit);
if (PSP_CoreParameter().fpsLimit == FPSLimit::DEBUGGER)
+8 -8
View File
@@ -697,14 +697,14 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) {
// TODO: We should replace the "fpsLimit" system with a speed factor.
static void ShowFpsLimitNotice() {
int fpsLimit = 60;
int percent = 100;
switch (PSP_CoreParameter().fpsLimit) {
case FPSLimit::CUSTOM1:
fpsLimit = g_Config.iFpsLimit1;
percent = g_Config.iAltSpeedPercent1;
break;
case FPSLimit::CUSTOM2:
fpsLimit = g_Config.iFpsLimit2;
percent = g_Config.iAltSpeedPercent2;
break;
default:
break;
@@ -713,7 +713,7 @@ static void ShowFpsLimitNotice() {
// Now display it.
char temp[51];
snprintf(temp, sizeof(temp), "%d%%", (int)((float)fpsLimit / 60.0f * 100.0f));
snprintf(temp, sizeof(temp), "%d%%", percent);
g_OSD.Show(OSDType::STATUS_ICON, temp, "", "I_FAST_FORWARD", 1.5f, "altspeed");
g_OSD.SetFlags("altspeed", OSDMessageFlags::Transparent);
}
@@ -994,9 +994,9 @@ void EmuScreen::ProcessVKey(VirtKey virtKey, bool down) {
if (down) {
if (!NetworkWarnUserIfOnlineAndCantSpeed()) {
// Cycle through enabled speeds.
if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL && g_Config.iFpsLimit1 >= 0) {
if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL && g_Config.iAltSpeedPercent1 >= 0) {
PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM1;
} else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 && g_Config.iFpsLimit2 >= 0) {
} else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 && g_Config.iAltSpeedPercent2 >= 0) {
PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM2;
} else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 || PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) {
PSP_CoreParameter().fpsLimit = FPSLimit::NORMAL;
@@ -1145,7 +1145,7 @@ void EmuScreen::OnVKeyAnalog(VirtKey virtualKeyCode, float value) {
if (limitMode != FPSLimit::NORMAL && limitMode != FPSLimit::ANALOG)
return;
// Don't even try if the limit is invalid.
if (g_Config.iAnalogFpsLimit <= 0)
if (g_Config.iAnalogAltSpeedPercent <= 0)
return;
// Apply a small deadzone (against the resting position.)
@@ -1153,7 +1153,7 @@ void EmuScreen::OnVKeyAnalog(VirtKey virtualKeyCode, float value) {
// If target is above 60, value is how much to speed up over 60. Otherwise, it's how much slower.
// So normalize the target.
int target = g_Config.iAnalogFpsLimit - 60;
int target = AltSpeedPercentToFps(g_Config.iAnalogAltSpeedPercent) - 60;
PSP_CoreParameter().analogFpsLimit = 60 + (int)(target * value);
// If we've reset back to normal, turn it off.
+3 -15
View File
@@ -131,9 +131,6 @@ GameSettingsScreen::GameSettingsScreen(const Path &gamePath, std::string gameID,
void GameSettingsScreen::ReadConfigTemporaries() {
// Written back on exit, so it must be read even if the System tab is never opened.
enableReports_ = Reporting::IsEnabled();
iAlternateSpeedPercent1_ = g_Config.iFpsLimit1 < 0 ? -1 : (g_Config.iFpsLimit1 * 100) / 60;
iAlternateSpeedPercent2_ = g_Config.iFpsLimit2 < 0 ? -1 : (g_Config.iFpsLimit2 * 100) / 60;
iAlternateSpeedPercentAnalog_ = (g_Config.iAnalogFpsLimit * 100) / 60;
}
GameSettingsScreen::~GameSettingsScreen() {
@@ -467,28 +464,19 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
graphicsSettings->Add(new ItemHeader(gr->T("Frame Rate Control")));
PopupSliderChoice *altSpeed1 = graphicsSettings->Add(new PopupSliderChoice(&iAlternateSpeedPercent1_, 0, 1000, UI::NO_DEFAULT_INT, gr->T("Alternative Speed", "Alternative speed"), 5, screenManager(), gr->T("%, 0:unlimited")));
PopupSliderChoice *altSpeed1 = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iAltSpeedPercent1, 0, 1000, UI::NO_DEFAULT_INT, gr->T("Alternative Speed", "Alternative speed"), 5, screenManager(), gr->T("%, 0:unlimited")));
altSpeed1->SetFormat("%i%%");
altSpeed1->SetZeroLabel(gr->T("Unlimited"));
altSpeed1->SetNegativeDisable(gr->T("Disabled"));
altSpeed1->OnChange.Add([this](UI::EventParams &) {
g_Config.iFpsLimit1 = iAlternateSpeedPercent1_ < 0 ? -1 : (iAlternateSpeedPercent1_ * 60) / 100;
});
PopupSliderChoice *altSpeed2 = graphicsSettings->Add(new PopupSliderChoice(&iAlternateSpeedPercent2_, 0, 1000, UI::NO_DEFAULT_INT, gr->T("Alternative Speed 2", "Alternative speed 2 (in %, 0 = unlimited)"), 5, screenManager(), gr->T("%, 0:unlimited")));
PopupSliderChoice *altSpeed2 = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iAltSpeedPercent2, 0, 1000, UI::NO_DEFAULT_INT, gr->T("Alternative Speed 2", "Alternative speed 2 (in %, 0 = unlimited)"), 5, screenManager(), gr->T("%, 0:unlimited")));
altSpeed2->SetFormat("%i%%");
altSpeed2->SetZeroLabel(gr->T("Unlimited"));
altSpeed2->SetNegativeDisable(gr->T("Disabled"));
altSpeed2->OnChange.Add([this](UI::EventParams &) {
g_Config.iFpsLimit2 = iAlternateSpeedPercent2_ < 0 ? -1 : (iAlternateSpeedPercent2_ * 60) / 100;
});
if (analogSpeedMapped_) {
PopupSliderChoice *analogSpeed = graphicsSettings->Add(new PopupSliderChoice(&iAlternateSpeedPercentAnalog_, 1, 1000, UI::NO_DEFAULT_INT, gr->T("Analog alternative speed", "Analog alternative speed (in %)"), 5, screenManager(), "%"));
PopupSliderChoice *analogSpeed = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iAnalogAltSpeedPercent, 1, 1000, UI::NO_DEFAULT_INT, gr->T("Analog alternative speed", "Analog alternative speed (in %)"), 5, screenManager(), "%"));
analogSpeed->SetFormat("%i%%");
analogSpeed->OnChange.Add([this](UI::EventParams &) {
g_Config.iAnalogFpsLimit = (iAlternateSpeedPercentAnalog_ * 60) / 100;
});
}
graphicsSettings->Add(new ItemHeader(gr->T("Speed Hacks", "Speed Hacks (can cause rendering errors!)")));
-3
View File
@@ -89,9 +89,6 @@ private:
void ReadConfigTemporaries();
// Temporaries to convert setting types, cache enabled, etc.
int iAlternateSpeedPercent1_ = 0;
int iAlternateSpeedPercent2_ = 0;
int iAlternateSpeedPercentAnalog_ = 0;
int prevInflightFrames_ = -1;
bool enableReports_ = false;
bool analogSpeedMapped_ = false;