diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt index 32e987aca3..e49f466462 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt @@ -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 */ diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt index ff4fd6031b..400257e8d9 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt @@ -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() } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index 2b79e562d9..e8739e2d23 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -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, diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index a6dccdab63..2e50bb1069 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -371,9 +371,6 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string // Create the render window. m_window = std::make_unique(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(); jauto android_webapplet = std::make_unique(); @@ -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, diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 5d8a0e41f6..c952567e63 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -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 diff --git a/src/common/settings.h b/src/common/settings.h index c8c36937ba..6d37881e81 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -204,6 +204,7 @@ struct Values { true}; SwitchableSetting use_speed_limit{ linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, true, true}; + SwitchableSetting 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 current_speed_limit{linkage, 100, "current_speed_limit", Category::Core, Specialization::Default, false, true}; - SwitchableSetting turbo_speed_limit{linkage, 200, 0, @@ -239,6 +236,9 @@ struct Values { true, true}; + // The currently used speed mode. + Setting current_speed_mode{linkage, SpeedMode::Standard, "current_speed_mode", Category::Core, Specialization::Default, false, true}; + SwitchableSetting 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(); diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 33c553dc3c..1414f176f8 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -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 inline std::string_view CanonicalizeEnum(Type id) { diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 08b6f1c6c9..6f45a270db 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -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; diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp index 422e97bcbe..801a135dd7 100644 --- a/src/core/hle/service/vi/conductor.cpp +++ b/src/core/hle/service/vi/conductor.cpp @@ -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; diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 6a0fedfb01..1ca3fe488c 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp @@ -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 diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index cde73ac919..12bf0c2aca 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -72,7 +72,7 @@ std::unique_ptr 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"), diff --git a/src/yuzu/main_window.cpp b/src/yuzu/main_window.cpp index ee1ad598f4..0c6f6f04d0 100644 --- a/src/yuzu/main_window.cpp +++ b/src/yuzu/main_window.cpp @@ -3,6 +3,7 @@ // Qt on macOS doesn't define VMA shit #include +#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)); }