From 79a47bed440a72a050162c3ada57342decb5dd55 Mon Sep 17 00:00:00 2001
From: Pavel Barabanov <pavelbarabanov94@gmail.com>
Date: Fri, 11 Apr 2025 18:52:04 +0300
Subject: [PATCH] Add sync core speed

---
 .../features/settings/model/BooleanSetting.kt |  6 ++---
 .../settings/model/view/SettingsItem.kt       | 27 +++++++++++++++++++
 .../settings/ui/SettingsFragmentPresenter.kt  |  1 +
 .../app/src/main/res/values/strings.xml       |  4 +++
 src/common/settings.h                         |  1 +
 src/core/core_timing.cpp                      | 15 +++++++++--
 src/yuzu/configuration/shared_translation.cpp |  4 +++
 7 files changed, 53 insertions(+), 5 deletions(-)

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 @@
     <string name="cpu_accuracy">CPU accuracy</string>
     <string name="value_with_units">%1$s%2$s</string>
 
+    <!-- Use Sync Core -->
+     <string name="use_sync_core">Synchronize Core Speed</string>
+     <string name="use_sync_core_description">Synchronize the core tick speed to the maximum speed percentage to improve performance without altering the games actual speed.</string>
+
     <!-- System settings strings -->
     <string name="device_name">Device name</string>
     <string name="use_docked_mode">Docked Mode</string>
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<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core, Specialization::Default};
 
     // Cpu
     SwitchableSetting<CpuBackend, true> 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<double>(fres);
+         const double speed_limit = static_cast<double>(Settings::values.speed_limit.GetValue())*0.01;
+         return static_cast<u64>(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<TranslationMap> 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:"),