diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index 34f417434f..4d5208c4c7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -10,6 +10,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { CPU_DEBUG_MODE("cpu_debug_mode"), FASTMEM("cpuopt_fastmem"), FASTMEM_EXCLUSIVES("cpuopt_fastmem_exclusives"), + CORE_SYNC_CORE_SPEED("sync_core_speed"), RENDERER_USE_SPEED_LIMIT("use_speed_limit"), USE_DOCKED_MODE("use_docked_mode"), RENDERER_USE_DISK_SHADER_CACHE("use_disk_shader_cache"), @@ -27,9 +28,8 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { SHOW_INPUT_OVERLAY("show_input_overlay"), TOUCHSCREEN("touchscreen"), SHOW_THERMAL_OVERLAY("show_thermal_overlay"), - ENABLE_FRAME_INTERPOLATION("enable_frame_interpolation"), - ENABLE_FRAME_SKIPPING("enable_frame_skipping"), - CORE_USE_MULTI_CORE("use_multi_core"); + ENABLE_FRAME_INTERPOLATION("enable_frame_interpolation"), + ENABLE_FRAME_SKIPPING("enable_frame_skipping"); external fun isFrameSkippingEnabled(): Boolean external fun isFrameInterpolationEnabled(): Boolean diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 2780b550e7..0868da00a5 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -206,6 +206,25 @@ abstract class SettingsItem( override fun reset() = BooleanSetting.ENABLE_FRAME_SKIPPING.reset() } + val syncCoreSpeedSetting = object : AbstractBooleanSetting { + override val key = BooleanSetting.CORE_SYNC_CORE_SPEED.key + + override fun getBoolean(needsGlobal: Boolean): Boolean { + return BooleanSetting.CORE_SYNC_CORE_SPEED.getBoolean(needsGlobal) + } + + override fun setBoolean(value: Boolean) { + BooleanSetting.CORE_SYNC_CORE_SPEED.setBoolean(value) + } + + override val defaultValue = BooleanSetting.CORE_SYNC_CORE_SPEED.defaultValue + + override fun getValueAsString(needsGlobal: Boolean): String = + BooleanSetting.CORE_SYNC_CORE_SPEED.getValueAsString(needsGlobal) + + override fun reset() = BooleanSetting.CORE_SYNC_CORE_SPEED.reset() + } + put( SwitchSetting( BooleanSetting.ENABLE_FRAME_INTERPOLATION, @@ -230,6 +249,14 @@ abstract class SettingsItem( ) ) + put( + SwitchSetting( + syncCoreSpeedSetting, + titleId = R.string.use_sync_core, + descriptionId = R.string.use_sync_core_description + ) + ) + put( SingleChoiceSetting( IntSetting.REGION_INDEX, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index 1af631ce1a..fe31b4054e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -159,6 +159,7 @@ class SettingsFragmentPresenter( add(StringSetting.DEVICE_NAME.key) add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key) add(ShortSetting.RENDERER_SPEED_LIMIT.key) + add(BooleanSetting.CORE_SYNC_CORE_SPEED.key) add(BooleanSetting.USE_DOCKED_MODE.key) add(IntSetting.REGION_INDEX.key) add(IntSetting.LANGUAGE_INDEX.key) diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 51495df2fc..263acda9fa 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -217,6 +217,10 @@ CPU accuracy %1$s%2$s + + Synchronize Core Speed + Synchronize the core tick speed to the maximum speed percentage to improve performance without altering the games actual speed. + Device name Docked Mode diff --git a/src/common/settings.h b/src/common/settings.h index e0788abda6..9eb04897da 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -210,6 +210,7 @@ struct Values { true, true, &use_speed_limit}; + SwitchableSetting sync_core_speed{linkage, false, "sync_core_speed", Category::Core, Specialization::Default}; // Cpu SwitchableSetting cpu_backend{linkage, diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 1abfa920c4..3d67ab9f5c 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -14,6 +14,7 @@ #include "common/x64/cpu_wait.h" #endif +#include "common/settings.h" #include "common/microprofile.h" #include "core/core_timing.h" #include "core/hardware_properties.h" @@ -184,10 +185,20 @@ void CoreTiming::ResetTicks() { } u64 CoreTiming::GetClockTicks() const { + u64 fres; if (is_multicore) [[likely]] { - return clock->GetCNTPCT(); + fres = clock->GetCNTPCT(); + } else { + fres = Common::WallClock::CPUTickToCNTPCT(cpu_ticks); + } + + if (Settings::values.sync_core_speed.GetValue()) { + const double ticks = static_cast(fres); + const double speed_limit = static_cast(Settings::values.speed_limit.GetValue())*0.01; + return static_cast(ticks/speed_limit); + } else { + return fres; } - return Common::WallClock::CPUTickToCNTPCT(cpu_ticks); } u64 CoreTiming::GetGPUTicks() const { diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp index 0549e8ae44..e80319cddf 100644 --- a/src/yuzu/configuration/shared_translation.cpp +++ b/src/yuzu/configuration/shared_translation.cpp @@ -71,6 +71,10 @@ std::unique_ptr InitializeTranslations(QWidget* parent) { "faster or not.\n200% for a 30 FPS game is 60 FPS, and for a " "60 FPS game it will be 120 FPS.\nDisabling it means unlocking the framerate to the " "maximum your PC can reach.")); + INSERT(Settings, sync_core_speed, tr("Synchronize Core Speed"), + tr("Synchronizes CPU core speed with the game's maximum rendering speed to boost FPS without affecting game speed (animations, physics, etc.).\n" + "Compatibility varies by game; many (especially older ones) may not respond well.\n" + "Can help reduce stuttering at lower framerates.")); // Cpu INSERT(Settings, cpu_accuracy, tr("Accuracy:"),