diff --git a/docs/Settings.md b/docs/Settings.md index 4bae71f44e..b46996ecc1 100644 --- a/docs/Settings.md +++ b/docs/Settings.md @@ -43,6 +43,7 @@ This guide will walk you through adding a new boolean toggle setting to Eden's c Firstly add your desired toggle: Example: `src/common/setting.h` + ```cpp SwitchableSetting your_setting_name{linkage, false, "your_setting_name", Category::RendererExtensions}; ``` @@ -67,6 +68,7 @@ Common Categories: Add the toggle to the Qt UI, where you wish for it to appear and place it there. Example: `src/qt_common/config/shared_translation.cpp` + ```cpp INSERT(Settings, your_setting_name, @@ -91,6 +93,7 @@ INSERT(Settings, Add where it should be in the settings. Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt` + ```kts RENDERER_YOUR_SETTING_NAME("your_setting_name"), ``` @@ -106,6 +109,7 @@ RENDERER_YOUR_SETTING_NAME("your_setting_name"), Add the toggle to the Kotlin (Android) UI Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt` + ```kts put( SwitchSetting( @@ -123,6 +127,7 @@ put( Add your setting within the right category. Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt` + ```kts add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key) ``` @@ -137,6 +142,7 @@ add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key) Add your setting and description in the appropriate place. Example: `src/android/app/src/main/res/values/strings.xml` + ```xml Your Setting Display Name Detailed description of what this setting does. Explain any caveats, requirements, or warnings here. @@ -150,6 +156,7 @@ Now the UI part is done find a place in the code for the toggle, And use it to your heart's desire! Example: + ```cpp const bool your_value = Settings::values.your_setting_name.GetValue(); @@ -196,25 +203,31 @@ Common advantages recap: #### Accessing Debug Knobs (dev side) -Use the `Settings::getDebugKnobAt(u8 i)` function to check if a specific bit is set: +Use the `Settings::GetDebugKnobAt(u8 i)` function to check if a specific bit is set: ```cpp //cpp side #include "common/settings.h" +//To use it as a general purpose uint var: +unsigned int debug_knobs = Settings::values.debug_knobs.GetValue(); + // Check if bit 0 is set -bool feature_enabled = Settings::getDebugKnobAt(0); +bool feature_enabled = Settings::GetDebugKnobAt(0); // Check if bit 15 is set -bool another_feature = Settings::getDebugKnobAt(15); +bool another_feature = Settings::GetDebugKnobAt(15); ``` ```kts //kotlin side import org.yuzu.yuzu_emu.features.settings.model.Settings +//To use it as a general purpose uint var +val debug_knobs: Int = UShortSetting.DEBUG_KNOBS.getInt() + // Check if bit x is set -bool feature_enabled = Settings.getDebugKnobAt(x); //x as integer from 0 to 15 +bool feature_enabled = Settings.GetDebugKnobAt(x); //x as integer from 0 to 15 ``` The function returns `true` if the specified bit (0-15) is set in the `debug_knobs` value, `false` otherwise. @@ -247,6 +260,7 @@ There are two main confusions when talking about knobs: Sometimes when an user reports: knobs 1 and 2 gets better performance, dev may get confuse whether he means the knobs 1 and 2 literally, or the 1st and 2nd knobs (knobs 0 and 1). Debug knobs are **zero-based**, which means: + * The first knob is the knob(0) (or knob0 henceforth), and the last one is the 15 (knob15, likewise) * You can talk: "knob0 is enabled/disabled", "In this video i was using only knobs 0 and 2", etc. @@ -259,6 +273,7 @@ Whenever you're instructing tests or reporting results, be precise about whether ALWAYS use the word in PLURAL (knobs), without mentioning which one, to refer to the setting, aka multiple knobs at once: Examples: + - **knobs=0**: no knobs enabled - **knobs=1**: knob0 enabled, others disabled - **knobs=2**: knob1 enabled, others disabled @@ -270,6 +285,7 @@ Examples: Use the word in SINGULAR (knob), or in plural but referring which ones, when meaning multiple knobs at once: Examples: + - **knob0**: knob 0 enabled, others disabled - **knob1**: knob 1 enabled, others disabled - **knobs 0 and 1**: knobs 0 and 1 enabled, others disabled @@ -282,12 +298,12 @@ Examples: ```cpp void SomeFunction() { - if (Settings::getDebugKnobAt(0)) { + if (Settings::GetDebugKnobAt(0)) { LOG_DEBUG(Common, "Debug feature 0 is enabled"); // Additional debug code here } - - if (Settings::getDebugKnobAt(1)) { + + if (Settings::GetDebugKnobAt(1)) { LOG_DEBUG(Common, "Debug feature 1 is enabled"); // Different debug behavior } @@ -299,7 +315,7 @@ void SomeFunction() { ```cpp bool UseOptimizedPath() { // Skip optimization if debug bit 2 is set for testing - return !Settings::getDebugKnobAt(2); + return !Settings::GetDebugKnobAt(2); } ``` @@ -308,13 +324,13 @@ bool UseOptimizedPath() { ```cpp void ExperimentalFeature() { static constexpr u8 EXPERIMENTAL_FEATURE_BIT = 3; - - if (!Settings::getDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) { + + if (!Settings::GetDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) { // Fallback to stable implementation StableImplementation(); return; } - + // Experimental implementation ExperimentalImplementation(); } 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 4610574f21..4b46dd76a2 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 @@ -220,7 +220,7 @@ object NativeLibrary { external fun refreshThreadPolicies() - external fun getDebugKnobAt(index: Int): Boolean + external fun GetDebugKnobAt(index: Int): Boolean /** * Set the current speed limit to the configured turbo speed. diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt index 2b449beaff..fc4df4952d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt @@ -35,8 +35,8 @@ object Settings { fun getPlayerString(player: Int): String = YuzuApplication.appContext.getString(R.string.preferences_player, player) - fun getDebugKnobAt(index: Int): Boolean { - return org.yuzu.yuzu_emu.NativeLibrary.getDebugKnobAt(index) + fun GetDebugKnobAt(index: Int): Boolean { + return org.yuzu.yuzu_emu.NativeLibrary.GetDebugKnobAt(index) } const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch" diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ShortSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ShortSetting.kt index 88c3615bdb..5f1dbe6372 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ShortSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/ShortSetting.kt @@ -11,8 +11,7 @@ import org.yuzu.yuzu_emu.utils.NativeConfig enum class ShortSetting(override val key: String) : AbstractShortSetting { RENDERER_SPEED_LIMIT("speed_limit"), RENDERER_TURBO_SPEED_LIMIT("turbo_speed_limit"), - RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit"), - DEBUG_KNOBS("debug_knobs") + RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit") ; override fun getShort(needsGlobal: Boolean): Short = NativeConfig.getShort(key, needsGlobal) @@ -29,4 +28,4 @@ enum class ShortSetting(override val key: String) : AbstractShortSetting { override fun getValueAsString(needsGlobal: Boolean): String = getShort(needsGlobal).toString() override fun reset() = NativeConfig.setShort(key, defaultValue) -} \ No newline at end of file +} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/UShortSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/UShortSetting.kt new file mode 100644 index 0000000000..7c81e77b0b --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/UShortSetting.kt @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.features.settings.model + +import org.yuzu.yuzu_emu.utils.NativeConfig + +enum class UShortSetting(override val key: String) : AbstractIntSetting { + DEBUG_KNOBS("debug_knobs") + ; + + override fun getInt(needsGlobal: Boolean): Int = + NativeConfig.getUnsignedShort(key, needsGlobal) + + override fun setInt(value: Int) { + if (NativeConfig.isPerGameConfigLoaded()) { + global = false + } + NativeConfig.setUnsignedShort(key, value) + } + + override val defaultValue: Int by lazy { NativeConfig.getDefaultToString(key).toInt() } + + override fun getValueAsString(needsGlobal: Boolean): String = getInt(needsGlobal).toString() + + override fun reset() = NativeConfig.setUnsignedShort(key, defaultValue) +} 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 c05539c306..6d46b50051 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 @@ -20,6 +20,7 @@ import org.yuzu.yuzu_emu.features.settings.model.IntSetting import org.yuzu.yuzu_emu.features.settings.model.LongSetting import org.yuzu.yuzu_emu.features.settings.model.ShortSetting import org.yuzu.yuzu_emu.features.settings.model.StringSetting +import org.yuzu.yuzu_emu.features.settings.model.UShortSetting import org.yuzu.yuzu_emu.network.NetDataValidators import org.yuzu.yuzu_emu.utils.LosslessScalingHelper import org.yuzu.yuzu_emu.utils.NativeConfig @@ -1034,7 +1035,7 @@ abstract class SettingsItem( ) put( SpinBoxSetting( - ShortSetting.DEBUG_KNOBS, + UShortSetting.DEBUG_KNOBS, titleId = R.string.debug_knobs, descriptionId = R.string.debug_knobs_description, valueHint = R.string.debug_knobs_hint, 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 108861491a..8e4984efe1 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 @@ -25,6 +25,7 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag import org.yuzu.yuzu_emu.features.settings.model.ShortSetting import org.yuzu.yuzu_emu.features.settings.model.StringSetting +import org.yuzu.yuzu_emu.features.settings.model.UShortSetting import org.yuzu.yuzu_emu.features.settings.model.view.* import org.yuzu.yuzu_emu.utils.InputHandler import org.yuzu.yuzu_emu.utils.LosslessScalingHelper @@ -1326,7 +1327,7 @@ class SettingsFragmentPresenter( add(HeaderSetting(R.string.general)) - add(ShortSetting.DEBUG_KNOBS.key) + add(UShortSetting.DEBUG_KNOBS.key) add(StringSetting.PROGRAM_ARGS.key) if (!NativeConfig.isPerGameConfigLoaded()) { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt index d1b5b1373d..10c8998d5c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt @@ -80,6 +80,12 @@ object NativeConfig { @Synchronized external fun setShort(key: String, value: Short) + @Synchronized + external fun getUnsignedShort(key: String, needsGlobal: Boolean): Int + + @Synchronized + external fun setUnsignedShort(key: String, value: Int) + @Synchronized external fun getInt(key: String, needsGlobal: Boolean): Int diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 4d0c39f5c7..ee521cdb05 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -1245,8 +1245,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_refreshThreadPolicies(JNIEnv* env, jo Common::RefreshThreadPolicies(); } -jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_getDebugKnobAt(JNIEnv* env, jobject jobj, jint index) { - return static_cast(Settings::getDebugKnobAt(static_cast(index))); +jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_GetDebugKnobAt(JNIEnv* env, jobject jobj, jint index) { + return static_cast(Settings::GetDebugKnobAt(static_cast(index))); } void Java_org_yuzu_yuzu_1emu_NativeLibrary_setTurboSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) { diff --git a/src/android/app/src/main/jni/native_config.cpp b/src/android/app/src/main/jni/native_config.cpp index 647fdbb997..09a79ce4d7 100644 --- a/src/android/app/src/main/jni/native_config.cpp +++ b/src/android/app/src/main/jni/native_config.cpp @@ -130,6 +130,25 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setShort(JNIEnv* env, jobject ob setting->SetValue(value); } +jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getUnsignedShort(JNIEnv* env, jobject obj, + jstring jkey, + jboolean needGlobal) { + auto setting = getSetting(env, jkey); + if (setting == nullptr) { + return -1; + } + return static_cast(setting->GetValue(static_cast(needGlobal))); +} + +void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setUnsignedShort(JNIEnv* env, jobject obj, + jstring jkey, jint value) { + auto setting = getSetting(env, jkey); + if (setting == nullptr) { + return; + } + setting->SetValue(static_cast(value)); +} + jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getInt(JNIEnv* env, jobject obj, jstring jkey, jboolean needGlobal) { auto setting = getSetting(env, jkey); diff --git a/src/common/settings.cpp b/src/common/settings.cpp index e2c5b532ac..01ed3f8b1f 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -146,7 +146,7 @@ void LogSettings() { #undef LOG_PATH } -bool getDebugKnobAt(u8 i) { +bool GetDebugKnobAt(u8 i) { return (values.debug_knobs.GetValue() & (1 << (i & 0xF))) != 0; } diff --git a/src/common/settings.h b/src/common/settings.h index 7ac4b11173..075b63f272 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -904,7 +904,7 @@ struct Values { 0, 65535, "debug_knobs", - Category::Debugging, + Category::System, Specialization::Countable, true, true};