Refactor to use an enum, and remember previous turbo/slow mode locally

Signed-off-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
crueter 2026-02-11 15:49:44 -05:00
parent 03d2bf88a5
commit 5669e064e3
No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
12 changed files with 126 additions and 87 deletions

View File

@ -218,6 +218,9 @@ object NativeLibrary {
*/
external fun setStandardSpeedLimit(enabled: Boolean)
external fun isTurboMode(): Boolean
external fun isSlowMode(): Boolean
/**
* Returns Vulkan driver version / API version / GPU model
*/

View File

@ -139,6 +139,7 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
fun addCustomToggle(
name: Int,
isChecked: Boolean,
isEnabled: Boolean,
container: ViewGroup,
callback: (Boolean) -> Unit
@ -153,13 +154,13 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
titleView.text = YuzuApplication.appContext.getString(name)
switchContainer.visibility = View.VISIBLE
switchView.isChecked = isChecked
switchView.setOnCheckedChangeListener { _, checked ->
callback(checked)
saveSettings()
}
switchView.isChecked = isChecked
switchContainer.setOnClickListener {
switchView.toggle()
}

View File

@ -1059,9 +1059,32 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
lateinit var slowSpeed: MaterialSwitch
lateinit var turboSpeed: MaterialSwitch
turboSpeed = quickSettings.addCustomToggle(
R.string.turbo_speed_limit,
NativeLibrary.isTurboMode(),
BooleanSetting.RENDERER_USE_SPEED_LIMIT.getBoolean(false),
container
) { enabled ->
if (enabled)
slowSpeed.isChecked = false
NativeLibrary.setTurboSpeedLimit(enabled)
}!!
slowSpeed = quickSettings.addCustomToggle(
R.string.slow_speed_limit,
NativeLibrary.isSlowMode(),
BooleanSetting.RENDERER_USE_SPEED_LIMIT.getBoolean(false),
container
) { enabled ->
if (enabled)
turboSpeed.isChecked = false
NativeLibrary.setSlowSpeedLimit(enabled)
}!!
quickSettings.addCustomToggle(
R.string.frame_limit_enable,
BooleanSetting.RENDERER_USE_SPEED_LIMIT.getBoolean(false),
true,
container
) { enabled ->
if (!enabled) {
@ -1084,26 +1107,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
units = "%",
)
turboSpeed = quickSettings.addCustomToggle(
R.string.turbo_speed_limit,
false,
container
) { enabled ->
if (enabled)
slowSpeed.isChecked = false
NativeLibrary.setTurboSpeedLimit(enabled)
}!!
slowSpeed = quickSettings.addCustomToggle(
R.string.slow_speed_limit,
false,
container
) { enabled ->
if (enabled)
turboSpeed.isChecked = false
NativeLibrary.setSlowSpeedLimit(enabled)
}!!
quickSettings.addBooleanSetting(
R.string.use_docked_mode,
container,

View File

@ -371,9 +371,6 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
// Create the render window.
m_window = std::make_unique<EmuWindow_Android>(m_native_window, m_vulkan_library);
// Set up speed limiter
Settings::values.current_speed_limit.SetValue(Settings::values.speed_limit.GetValue());
// Initialize system.
jauto android_keyboard = std::make_unique<Common::Android::SoftwareKeyboard::AndroidKeyboard>();
jauto android_webapplet = std::make_unique<Common::Android::WebBrowser::AndroidWebBrowser>();
@ -1237,34 +1234,36 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_getDebugKnobAt(JNIEnv* env, jobje
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setTurboSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
Settings::values.use_speed_limit.SetValue(true);
auto &cur = Settings::values.current_speed_limit;
auto &nxt = Settings::values.turbo_speed_limit.GetValue();
auto &fallback = Settings::values.speed_limit.GetValue();
if (enabled && cur.GetValue() != nxt)
cur.SetValue(nxt);
else
cur.SetValue(fallback);
if (enabled) {
Settings::values.use_speed_limit.SetValue(true);
Settings::SetSpeedMode(Settings::SpeedMode::Turbo);
} else {
Settings::SetSpeedMode(Settings::SpeedMode::Standard);
}
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setSlowSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
Settings::values.use_speed_limit.SetValue(true);
auto &cur = Settings::values.current_speed_limit;
auto &nxt = Settings::values.slow_speed_limit.GetValue();
auto &fallback = Settings::values.speed_limit.GetValue();
if (enabled && cur.GetValue() != nxt)
cur.SetValue(nxt);
else
cur.SetValue(fallback);
if (enabled) {
Settings::values.use_speed_limit.SetValue(true);
Settings::SetSpeedMode(Settings::SpeedMode::Slow);
} else {
Settings::SetSpeedMode(Settings::SpeedMode::Standard);
}
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setStandardSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
Settings::values.use_speed_limit.SetValue(enabled);
Settings::values.current_speed_limit.SetValue(Settings::values.speed_limit.GetValue());
if (enabled) {
Settings::SetSpeedMode(Settings::SpeedMode::Standard);
}
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isTurboMode(JNIEnv *env, jobject jobj) {
return Settings::values.current_speed_mode.GetValue() == Settings::SpeedMode::Turbo;
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isSlowMode(JNIEnv *env, jobject jobj) {
return Settings::values.current_speed_mode.GetValue() == Settings::SpeedMode::Slow;
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,

View File

@ -379,4 +379,52 @@ void SetConfiguringGlobal(bool is_global) {
configuring_global = is_global;
}
u16 SpeedLimit() {
switch (SpeedMode(values.current_speed_mode)) {
case SpeedMode::Standard:
return values.speed_limit.GetValue();
case SpeedMode::Turbo:
return values.turbo_speed_limit.GetValue();
case SpeedMode::Slow:
return values.slow_speed_limit.GetValue();
default:
UNIMPLEMENTED();
}
return 100;
}
void SetSpeedMode(const SpeedMode& mode) {
values.current_speed_mode.SetValue(mode);
switch (mode) {
case SpeedMode::Turbo:
case SpeedMode::Slow:
values.use_speed_limit.SetValue(true);
break;
case SpeedMode::Standard:
default:
break;
}
}
void ToggleStandardMode() {
values.use_speed_limit.SetValue(!values.use_speed_limit.GetValue());
SetSpeedMode(SpeedMode::Standard);
}
void ToggleTurboMode() {
if (values.current_speed_mode.GetValue() != SpeedMode::Turbo)
SetSpeedMode(SpeedMode::Turbo);
else
SetSpeedMode(SpeedMode::Standard);
}
void ToggleSlowMode() {
if (values.current_speed_mode.GetValue() != SpeedMode::Slow)
SetSpeedMode(SpeedMode::Slow);
else
SetSpeedMode(SpeedMode::Standard);
}
} // namespace Settings

View File

@ -204,6 +204,7 @@ struct Values {
true};
SwitchableSetting<bool> use_speed_limit{
linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, true, true};
SwitchableSetting<u16, true> speed_limit{linkage,
100,
0,
@ -225,10 +226,6 @@ struct Values {
true,
true};
// The currently used speed limit.
// TODO: should this be an enum?
SwitchableSetting<u16> current_speed_limit{linkage, 100, "current_speed_limit", Category::Core, Specialization::Default, false, true};
SwitchableSetting<u16, true> turbo_speed_limit{linkage,
200,
0,
@ -239,6 +236,9 @@ struct Values {
true,
true};
// The currently used speed mode.
Setting<SpeedMode> current_speed_mode{linkage, SpeedMode::Standard, "current_speed_mode", Category::Core, Specialization::Default, false, true};
SwitchableSetting<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core,
Specialization::Default};
@ -839,6 +839,13 @@ bool IsDockedMode();
float Volume();
// speed limit ops
u16 SpeedLimit();
void SetSpeedMode(const SpeedMode &mode);
void ToggleStandardMode();
void ToggleTurboMode();
void ToggleSlowMode();
std::string GetTimeZoneString(TimeZone time_zone);
void LogSettings();

View File

@ -156,6 +156,7 @@ ENUM(TemperatureUnits, Celsius, Fahrenheit)
ENUM(ExtendedDynamicState, Disabled, EDS1, EDS2, EDS3);
ENUM(GpuLogLevel, Off, Errors, Standard, Verbose, All)
ENUM(GameListMode, TreeView, GridView);
ENUM(SpeedMode, Standard, Turbo, Slow);
template <typename Type>
inline std::string_view CanonicalizeEnum(Type id) {

View File

@ -201,7 +201,7 @@ u64 CoreTiming::GetClockTicks() const {
if (Settings::values.sync_core_speed.GetValue()) {
const auto ticks = double(fres);
const auto speed_limit = double(Settings::values.current_speed_limit.GetValue())*0.01;
const auto speed_limit = double(Settings::SpeedLimit())*0.01;
return u64(ticks/speed_limit);
} else {
return fres;

View File

@ -95,7 +95,7 @@ s64 Conductor::GetNextTicks() const {
if (settings.use_speed_limit.GetValue()) {
// Scales the speed based on speed_limit setting on MC. SC is handled by
// SpeedLimiter::DoSpeedLimiting.
speed_scale = 100.f / settings.current_speed_limit.GetValue();
speed_scale = 100.f / Settings::SpeedLimit();
} else {
// Run at unlocked framerate.
speed_scale = 0.01f;

View File

@ -143,7 +143,7 @@ void SpeedLimiter::DoSpeedLimiting(microseconds current_system_time_us) {
auto now = Clock::now();
const double sleep_scale = Settings::values.current_speed_limit.GetValue() / 100.0;
const double sleep_scale = Settings::SpeedLimit() / 100.0;
// Max lag caused by slow frames. Shouldn't be more than the length of a frame at the current
// speed percent or it will clamp too much and prevent this from properly limiting to that

View File

@ -72,7 +72,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
tr("Increases the amount of emulated RAM.\nDoesn't affect performance/stability but may allow HD texture "
"mods to load."));
INSERT(Settings, use_speed_limit, QString(), QString());
INSERT(Settings, current_speed_limit, QString(), QString());
INSERT(Settings, current_speed_mode, QString(), QString());
INSERT(Settings,
speed_limit,
tr("Limit Speed Percent"),

View File

@ -3,6 +3,7 @@
// Qt on macOS doesn't define VMA shit
#include <boost/algorithm/string/split.hpp>
#include "common/settings.h"
#include "common/settings_enums.h"
#include "frontend_common/settings_generator.h"
#include "qt_common/qt_string_lookup.h"
@ -1442,42 +1443,21 @@ void MainWindow::InitializeHotkeys() {
connect_shortcut(QStringLiteral("Audio Volume Up"), &MainWindow::OnIncreaseVolume);
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [this] {
const bool limited = !Settings::values.use_speed_limit.GetValue();
Settings::values.use_speed_limit.SetValue(limited);
Settings::values.current_speed_limit.SetValue(Settings::values.speed_limit.GetValue());
Settings::ToggleStandardMode();
const bool limited = Settings::values.use_speed_limit.GetValue();
m_fpsSuffix = limited ? QString{} : tr("Unlocked");
});
connect_shortcut(QStringLiteral("Toggle Turbo Speed"), [this] {
Settings::values.use_speed_limit.SetValue(true);
auto &cur = Settings::values.current_speed_limit;
auto &nxt = Settings::values.turbo_speed_limit.GetValue();
auto &fallback = Settings::values.speed_limit.GetValue();
if (cur.GetValue() == nxt) {
cur.SetValue(fallback);
m_fpsSuffix = QString{};
} else {
cur.SetValue(nxt);
m_fpsSuffix = tr("Turbo");
}
Settings::ToggleTurboMode();
const bool turbo = Settings::values.current_speed_mode.GetValue() == Settings::SpeedMode::Turbo;
m_fpsSuffix = turbo ? tr("Turbo") : QString{};
});
connect_shortcut(QStringLiteral("Toggle Slow Speed"), [this] {
Settings::values.use_speed_limit.SetValue(true);
auto &cur = Settings::values.current_speed_limit;
auto &nxt = Settings::values.slow_speed_limit.GetValue();
auto &fallback = Settings::values.speed_limit.GetValue();
if (cur.GetValue() == nxt) {
cur.SetValue(fallback);
m_fpsSuffix = QString{};
} else {
cur.SetValue(nxt);
m_fpsSuffix = tr("Slow");
}
Settings::ToggleSlowMode();
const bool slow = Settings::values.current_speed_mode.GetValue() == Settings::SpeedMode::Slow;
m_fpsSuffix = slow ? tr("Slow") : QString{};
});
connect_shortcut(QStringLiteral("Toggle Renderdoc Capture"), [] {
@ -2083,9 +2063,6 @@ void MainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletPa
game_list->SaveInterfaceLayout();
config->SaveAllValues();
// Set up speed limiter
Settings::values.current_speed_limit.SetValue(Settings::values.speed_limit.GetValue());
u64 title_id{0};
last_filename_booted = filename;
@ -4294,7 +4271,7 @@ void MainWindow::UpdateStatusBar() {
if (Settings::values.use_speed_limit.GetValue()) {
emu_speed_label->setText(tr("Speed: %1% / %2%")
.arg(results.emulation_speed * 100.0, 0, 'f', 0)
.arg(Settings::values.current_speed_limit.GetValue()));
.arg(Settings::SpeedLimit()));
} else {
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
}