diff options
| author | 2023-11-24 22:59:55 -0500 | |
|---|---|---|
| committer | 2023-11-24 22:59:55 -0500 | |
| commit | 5a182f4e7ccfac696cd54542089c880d002f5cc9 (patch) | |
| tree | e1bcd72f38f4f57ff6b915022268b0feb86a7937 | |
| parent | Merge pull request #12140 from liamwhite/qcr-unreachable (diff) | |
| parent | frontend_common: Don't specify default value for screenshot_path (diff) | |
| download | yuzu-5a182f4e7ccfac696cd54542089c880d002f5cc9.tar.gz yuzu-5a182f4e7ccfac696cd54542089c880d002f5cc9.tar.xz yuzu-5a182f4e7ccfac696cd54542089c880d002f5cc9.zip | |
Merge pull request #11889 from t895/ini-lib
configuration: Unify config handling across frontends
69 files changed, 2696 insertions, 3541 deletions
diff --git a/.gitmodules b/.gitmodules index b72a2ec8c..45dd0d259 100644 --- a/.gitmodules +++ b/.gitmodules | |||
| @@ -4,9 +4,6 @@ | |||
| 4 | [submodule "enet"] | 4 | [submodule "enet"] |
| 5 | path = externals/enet | 5 | path = externals/enet |
| 6 | url = https://github.com/lsalzman/enet.git | 6 | url = https://github.com/lsalzman/enet.git |
| 7 | [submodule "inih"] | ||
| 8 | path = externals/inih/inih | ||
| 9 | url = https://github.com/benhoyt/inih.git | ||
| 10 | [submodule "cubeb"] | 7 | [submodule "cubeb"] |
| 11 | path = externals/cubeb | 8 | path = externals/cubeb |
| 12 | url = https://github.com/mozilla/cubeb.git | 9 | url = https://github.com/mozilla/cubeb.git |
| @@ -61,3 +58,6 @@ | |||
| 61 | [submodule "breakpad"] | 58 | [submodule "breakpad"] |
| 62 | path = externals/breakpad | 59 | path = externals/breakpad |
| 63 | url = https://github.com/yuzu-emu/breakpad.git | 60 | url = https://github.com/yuzu-emu/breakpad.git |
| 61 | [submodule "simpleini"] | ||
| 62 | path = externals/simpleini | ||
| 63 | url = https://github.com/brofield/simpleini.git | ||
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c35e0946..e5cac8fe9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -285,7 +285,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) | |||
| 285 | find_package(Boost 1.79.0 REQUIRED context) | 285 | find_package(Boost 1.79.0 REQUIRED context) |
| 286 | find_package(enet 1.3 MODULE) | 286 | find_package(enet 1.3 MODULE) |
| 287 | find_package(fmt 9 REQUIRED) | 287 | find_package(fmt 9 REQUIRED) |
| 288 | find_package(inih 52 MODULE COMPONENTS INIReader) | ||
| 289 | find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle) | 288 | find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle) |
| 290 | find_package(lz4 REQUIRED) | 289 | find_package(lz4 REQUIRED) |
| 291 | find_package(nlohmann_json 3.8 REQUIRED) | 290 | find_package(nlohmann_json 3.8 REQUIRED) |
diff --git a/CMakeModules/Findinih.cmake b/CMakeModules/Findinih.cmake deleted file mode 100644 index 791befebd..000000000 --- a/CMakeModules/Findinih.cmake +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | # SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf> | ||
| 2 | # | ||
| 3 | # SPDX-License-Identifier: GPL-3.0-or-later | ||
| 4 | |||
| 5 | find_package(PkgConfig QUIET) | ||
| 6 | pkg_search_module(INIH QUIET IMPORTED_TARGET inih) | ||
| 7 | if (INIReader IN_LIST inih_FIND_COMPONENTS) | ||
| 8 | pkg_search_module(INIREADER QUIET IMPORTED_TARGET INIReader) | ||
| 9 | if (INIREADER_FOUND) | ||
| 10 | set(inih_INIReader_FOUND TRUE) | ||
| 11 | endif() | ||
| 12 | endif() | ||
| 13 | |||
| 14 | include(FindPackageHandleStandardArgs) | ||
| 15 | find_package_handle_standard_args(inih | ||
| 16 | REQUIRED_VARS INIH_LINK_LIBRARIES | ||
| 17 | VERSION_VAR INIH_VERSION | ||
| 18 | HANDLE_COMPONENTS | ||
| 19 | ) | ||
| 20 | |||
| 21 | if (inih_FOUND AND NOT TARGET inih::inih) | ||
| 22 | add_library(inih::inih ALIAS PkgConfig::INIH) | ||
| 23 | endif() | ||
| 24 | |||
| 25 | if (inih_FOUND AND inih_INIReader_FOUND AND NOT TARGET inih::INIReader) | ||
| 26 | add_library(inih::INIReader ALIAS PkgConfig::INIREADER) | ||
| 27 | endif() | ||
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index be8b0b5e8..515e3f2a4 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt | |||
| @@ -34,11 +34,6 @@ endif() | |||
| 34 | # Glad | 34 | # Glad |
| 35 | add_subdirectory(glad) | 35 | add_subdirectory(glad) |
| 36 | 36 | ||
| 37 | # inih | ||
| 38 | if (NOT TARGET inih::INIReader) | ||
| 39 | add_subdirectory(inih) | ||
| 40 | endif() | ||
| 41 | |||
| 42 | # mbedtls | 37 | # mbedtls |
| 43 | add_subdirectory(mbedtls) | 38 | add_subdirectory(mbedtls) |
| 44 | target_include_directories(mbedtls PUBLIC ./mbedtls/include) | 39 | target_include_directories(mbedtls PUBLIC ./mbedtls/include) |
| @@ -295,3 +290,6 @@ if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client) | |||
| 295 | target_link_libraries(dump_syms PRIVATE libbreakpad_client ZLIB::ZLIB) | 290 | target_link_libraries(dump_syms PRIVATE libbreakpad_client ZLIB::ZLIB) |
| 296 | endif() | 291 | endif() |
| 297 | endif() | 292 | endif() |
| 293 | |||
| 294 | # SimpleIni | ||
| 295 | add_subdirectory(simpleini) | ||
diff --git a/externals/inih/CMakeLists.txt b/externals/inih/CMakeLists.txt deleted file mode 100644 index ebb60a976..000000000 --- a/externals/inih/CMakeLists.txt +++ /dev/null | |||
| @@ -1,13 +0,0 @@ | |||
| 1 | # SPDX-FileCopyrightText: 2014 Gui Andrade <admin@archshift.com> | ||
| 2 | # SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | add_library(inih | ||
| 5 | inih/ini.c | ||
| 6 | inih/ini.h | ||
| 7 | inih/cpp/INIReader.cpp | ||
| 8 | inih/cpp/INIReader.h | ||
| 9 | ) | ||
| 10 | |||
| 11 | create_target_directory_groups(inih) | ||
| 12 | target_include_directories(inih INTERFACE inih/cpp) | ||
| 13 | add_library(inih::INIReader ALIAS inih) | ||
diff --git a/externals/inih/inih b/externals/inih/inih deleted file mode 160000 | |||
| Subproject 9cecf0643da0846e77f64d10a126d9f48b9e05e | |||
diff --git a/externals/simpleini b/externals/simpleini new file mode 160000 | |||
| Subproject 382ddbb4b92c0b26aa1b32cefba2002119a5b1f | |||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d2ca4904a..e04d2418b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt | |||
| @@ -187,6 +187,7 @@ add_subdirectory(audio_core) | |||
| 187 | add_subdirectory(video_core) | 187 | add_subdirectory(video_core) |
| 188 | add_subdirectory(network) | 188 | add_subdirectory(network) |
| 189 | add_subdirectory(input_common) | 189 | add_subdirectory(input_common) |
| 190 | add_subdirectory(frontend_common) | ||
| 190 | add_subdirectory(shader_recompiler) | 191 | add_subdirectory(shader_recompiler) |
| 191 | 192 | ||
| 192 | if (YUZU_ROOM) | 193 | if (YUZU_ROOM) |
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index 021b070e0..5721327e7 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts | |||
| @@ -219,7 +219,6 @@ dependencies { | |||
| 219 | implementation("io.coil-kt:coil:2.2.2") | 219 | implementation("io.coil-kt:coil:2.2.2") |
| 220 | implementation("androidx.core:core-splashscreen:1.0.1") | 220 | implementation("androidx.core:core-splashscreen:1.0.1") |
| 221 | implementation("androidx.window:window:1.2.0-beta03") | 221 | implementation("androidx.window:window:1.2.0-beta03") |
| 222 | implementation("org.ini4j:ini4j:0.5.4") | ||
| 223 | implementation("androidx.constraintlayout:constraintlayout:2.1.4") | 222 | implementation("androidx.constraintlayout:constraintlayout:2.1.4") |
| 224 | implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") | 223 | implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") |
| 225 | implementation("androidx.navigation:navigation-fragment-ktx:2.7.4") | 224 | implementation("androidx.navigation:navigation-fragment-ktx:2.7.4") |
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 9ebd6c732..f2ba2504c 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 | |||
| @@ -230,8 +230,6 @@ object NativeLibrary { | |||
| 230 | */ | 230 | */ |
| 231 | external fun onTouchReleased(finger_id: Int) | 231 | external fun onTouchReleased(finger_id: Int) |
| 232 | 232 | ||
| 233 | external fun reloadSettings() | ||
| 234 | |||
| 235 | external fun initGameIni(gameID: String?) | 233 | external fun initGameIni(gameID: String?) |
| 236 | 234 | ||
| 237 | external fun setAppDirectory(directory: String) | 235 | external fun setAppDirectory(directory: String) |
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 2bf0e1b0d..d005c656e 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 | |||
| @@ -7,7 +7,7 @@ import android.text.TextUtils | |||
| 7 | import android.widget.Toast | 7 | import android.widget.Toast |
| 8 | import org.yuzu.yuzu_emu.R | 8 | import org.yuzu.yuzu_emu.R |
| 9 | import org.yuzu.yuzu_emu.YuzuApplication | 9 | import org.yuzu.yuzu_emu.YuzuApplication |
| 10 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 10 | import org.yuzu.yuzu_emu.utils.NativeConfig |
| 11 | 11 | ||
| 12 | object Settings { | 12 | object Settings { |
| 13 | private val context get() = YuzuApplication.appContext | 13 | private val context get() = YuzuApplication.appContext |
| @@ -19,7 +19,7 @@ object Settings { | |||
| 19 | context.getString(R.string.ini_saved), | 19 | context.getString(R.string.ini_saved), |
| 20 | Toast.LENGTH_SHORT | 20 | Toast.LENGTH_SHORT |
| 21 | ).show() | 21 | ).show() |
| 22 | SettingsFile.saveFile(SettingsFile.FILE_NAME_CONFIG) | 22 | NativeConfig.saveSettings() |
| 23 | } else { | 23 | } else { |
| 24 | // TODO: Save custom game settings | 24 | // TODO: Save custom game settings |
| 25 | Toast.makeText( | 25 | Toast.makeText( |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt index c73edd50e..48bdbdd75 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt | |||
| @@ -21,7 +21,6 @@ import androidx.navigation.navArgs | |||
| 21 | import com.google.android.material.color.MaterialColors | 21 | import com.google.android.material.color.MaterialColors |
| 22 | import kotlinx.coroutines.flow.collectLatest | 22 | import kotlinx.coroutines.flow.collectLatest |
| 23 | import kotlinx.coroutines.launch | 23 | import kotlinx.coroutines.launch |
| 24 | import org.yuzu.yuzu_emu.NativeLibrary | ||
| 25 | import java.io.IOException | 24 | import java.io.IOException |
| 26 | import org.yuzu.yuzu_emu.R | 25 | import org.yuzu.yuzu_emu.R |
| 27 | import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding | 26 | import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding |
| @@ -165,11 +164,12 @@ class SettingsActivity : AppCompatActivity() { | |||
| 165 | settingsViewModel.shouldSave = false | 164 | settingsViewModel.shouldSave = false |
| 166 | 165 | ||
| 167 | // Delete settings file because the user may have changed values that do not exist in the UI | 166 | // Delete settings file because the user may have changed values that do not exist in the UI |
| 167 | NativeConfig.unloadConfig() | ||
| 168 | val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG) | 168 | val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG) |
| 169 | if (!settingsFile.delete()) { | 169 | if (!settingsFile.delete()) { |
| 170 | throw IOException("Failed to delete $settingsFile") | 170 | throw IOException("Failed to delete $settingsFile") |
| 171 | } | 171 | } |
| 172 | NativeLibrary.reloadSettings() | 172 | NativeConfig.initializeConfig() |
| 173 | 173 | ||
| 174 | Toast.makeText( | 174 | Toast.makeText( |
| 175 | applicationContext, | 175 | applicationContext, |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt index 2b04d666a..3ae5b4653 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt | |||
| @@ -3,15 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.features.settings.utils | 4 | package org.yuzu.yuzu_emu.features.settings.utils |
| 5 | 5 | ||
| 6 | import android.widget.Toast | ||
| 7 | import java.io.* | 6 | import java.io.* |
| 8 | import org.ini4j.Wini | ||
| 9 | import org.yuzu.yuzu_emu.R | ||
| 10 | import org.yuzu.yuzu_emu.YuzuApplication | ||
| 11 | import org.yuzu.yuzu_emu.features.settings.model.* | ||
| 12 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization | 7 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization |
| 13 | import org.yuzu.yuzu_emu.utils.Log | ||
| 14 | import org.yuzu.yuzu_emu.utils.NativeConfig | ||
| 15 | 8 | ||
| 16 | /** | 9 | /** |
| 17 | * Contains static methods for interacting with .ini files in which settings are stored. | 10 | * Contains static methods for interacting with .ini files in which settings are stored. |
| @@ -19,41 +12,6 @@ import org.yuzu.yuzu_emu.utils.NativeConfig | |||
| 19 | object SettingsFile { | 12 | object SettingsFile { |
| 20 | const val FILE_NAME_CONFIG = "config" | 13 | const val FILE_NAME_CONFIG = "config" |
| 21 | 14 | ||
| 22 | /** | ||
| 23 | * Saves a Settings HashMap to a given .ini file on disk. If unsuccessful, outputs an error | ||
| 24 | * telling why it failed. | ||
| 25 | * | ||
| 26 | * @param fileName The target filename without a path or extension. | ||
| 27 | */ | ||
| 28 | fun saveFile(fileName: String) { | ||
| 29 | val ini = getSettingsFile(fileName) | ||
| 30 | try { | ||
| 31 | val wini = Wini(ini) | ||
| 32 | for (specificCategory in Settings.Category.values()) { | ||
| 33 | val categoryHeader = NativeConfig.getConfigHeader(specificCategory.ordinal) | ||
| 34 | for (setting in Settings.settingsList) { | ||
| 35 | if (setting.key!!.isEmpty()) continue | ||
| 36 | |||
| 37 | val settingCategoryHeader = | ||
| 38 | NativeConfig.getConfigHeader(setting.category.ordinal) | ||
| 39 | val iniSetting: String? = wini.get(categoryHeader, setting.key) | ||
| 40 | if (iniSetting != null || settingCategoryHeader == categoryHeader) { | ||
| 41 | wini.put(settingCategoryHeader, setting.key, setting.valueAsString) | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
| 45 | wini.store() | ||
| 46 | } catch (e: IOException) { | ||
| 47 | Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.message) | ||
| 48 | val context = YuzuApplication.appContext | ||
| 49 | Toast.makeText( | ||
| 50 | context, | ||
| 51 | context.getString(R.string.error_saving, fileName, e.message), | ||
| 52 | Toast.LENGTH_SHORT | ||
| 53 | ).show() | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | fun getSettingsFile(fileName: String): File = | 15 | fun getSettingsFile(fileName: String): File = |
| 58 | File(DirectoryInitialization.userDirectory + "/config/" + fileName + ".ini") | 16 | File(DirectoryInitialization.userDirectory + "/config/" + fileName + ".ini") |
| 59 | } | 17 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index ace5dddea..bd2f4cd25 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt | |||
| @@ -625,6 +625,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 625 | } | 625 | } |
| 626 | 626 | ||
| 627 | // Clear existing user data | 627 | // Clear existing user data |
| 628 | NativeConfig.unloadConfig() | ||
| 628 | File(DirectoryInitialization.userDirectory!!).deleteRecursively() | 629 | File(DirectoryInitialization.userDirectory!!).deleteRecursively() |
| 629 | 630 | ||
| 630 | // Copy archive to internal storage | 631 | // Copy archive to internal storage |
| @@ -643,6 +644,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 643 | 644 | ||
| 644 | // Reinitialize relevant data | 645 | // Reinitialize relevant data |
| 645 | NativeLibrary.initializeSystem(true) | 646 | NativeLibrary.initializeSystem(true) |
| 647 | NativeConfig.initializeConfig() | ||
| 646 | gamesViewModel.reloadGames(false) | 648 | gamesViewModel.reloadGames(false) |
| 647 | 649 | ||
| 648 | return@newInstance getString(R.string.user_data_import_success) | 650 | return@newInstance getString(R.string.user_data_import_success) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt index 5e9a1176a..21270fc84 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt | |||
| @@ -16,6 +16,7 @@ object DirectoryInitialization { | |||
| 16 | if (!areDirectoriesReady) { | 16 | if (!areDirectoriesReady) { |
| 17 | initializeInternalStorage() | 17 | initializeInternalStorage() |
| 18 | NativeLibrary.initializeSystem(false) | 18 | NativeLibrary.initializeSystem(false) |
| 19 | NativeConfig.initializeConfig() | ||
| 19 | areDirectoriesReady = true | 20 | areDirectoriesReady = true |
| 20 | } | 21 | } |
| 21 | } | 22 | } |
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 9425f8b99..87e579fa7 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 | |||
| @@ -4,6 +4,30 @@ | |||
| 4 | package org.yuzu.yuzu_emu.utils | 4 | package org.yuzu.yuzu_emu.utils |
| 5 | 5 | ||
| 6 | object NativeConfig { | 6 | object NativeConfig { |
| 7 | /** | ||
| 8 | * Creates a Config object and opens the emulation config. | ||
| 9 | */ | ||
| 10 | @Synchronized | ||
| 11 | external fun initializeConfig() | ||
| 12 | |||
| 13 | /** | ||
| 14 | * Destroys the stored config object. This automatically saves the existing config. | ||
| 15 | */ | ||
| 16 | @Synchronized | ||
| 17 | external fun unloadConfig() | ||
| 18 | |||
| 19 | /** | ||
| 20 | * Reads values saved to the config file and saves them. | ||
| 21 | */ | ||
| 22 | @Synchronized | ||
| 23 | external fun reloadSettings() | ||
| 24 | |||
| 25 | /** | ||
| 26 | * Saves settings values in memory to disk. | ||
| 27 | */ | ||
| 28 | @Synchronized | ||
| 29 | external fun saveSettings() | ||
| 30 | |||
| 7 | external fun getBoolean(key: String, getDefault: Boolean): Boolean | 31 | external fun getBoolean(key: String, getDefault: Boolean): Boolean |
| 8 | external fun setBoolean(key: String, value: Boolean) | 32 | external fun setBoolean(key: String, value: Boolean) |
| 9 | 33 | ||
diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index 88a570f68..2acc93da8 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt | |||
| @@ -6,9 +6,6 @@ add_library(yuzu-android SHARED | |||
| 6 | android_common/android_common.h | 6 | android_common/android_common.h |
| 7 | applets/software_keyboard.cpp | 7 | applets/software_keyboard.cpp |
| 8 | applets/software_keyboard.h | 8 | applets/software_keyboard.h |
| 9 | config.cpp | ||
| 10 | config.h | ||
| 11 | default_ini.h | ||
| 12 | emu_window/emu_window.cpp | 9 | emu_window/emu_window.cpp |
| 13 | emu_window/emu_window.h | 10 | emu_window/emu_window.h |
| 14 | id_cache.cpp | 11 | id_cache.cpp |
| @@ -16,15 +13,17 @@ add_library(yuzu-android SHARED | |||
| 16 | native.cpp | 13 | native.cpp |
| 17 | native.h | 14 | native.h |
| 18 | native_config.cpp | 15 | native_config.cpp |
| 19 | uisettings.cpp | 16 | android_settings.cpp |
| 20 | game_metadata.cpp | 17 | game_metadata.cpp |
| 21 | native_log.cpp | 18 | native_log.cpp |
| 19 | android_config.cpp | ||
| 20 | android_config.h | ||
| 22 | ) | 21 | ) |
| 23 | 22 | ||
| 24 | set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) | 23 | set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) |
| 25 | 24 | ||
| 26 | target_link_libraries(yuzu-android PRIVATE audio_core common core input_common) | 25 | target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common) |
| 27 | target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics log) | 26 | target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log) |
| 28 | if (ARCHITECTURE_arm64) | 27 | if (ARCHITECTURE_arm64) |
| 29 | target_link_libraries(yuzu-android PRIVATE adrenotools) | 28 | target_link_libraries(yuzu-android PRIVATE adrenotools) |
| 30 | endif() | 29 | endif() |
diff --git a/src/android/app/src/main/jni/android_config.cpp b/src/android/app/src/main/jni/android_config.cpp new file mode 100644 index 000000000..3041c25c9 --- /dev/null +++ b/src/android/app/src/main/jni/android_config.cpp | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "android_config.h" | ||
| 5 | #include "android_settings.h" | ||
| 6 | #include "common/settings_setting.h" | ||
| 7 | |||
| 8 | AndroidConfig::AndroidConfig(const std::string& config_name, ConfigType config_type) | ||
| 9 | : Config(config_type) { | ||
| 10 | Initialize(config_name); | ||
| 11 | if (config_type != ConfigType::InputProfile) { | ||
| 12 | ReadAndroidValues(); | ||
| 13 | SaveAndroidValues(); | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | AndroidConfig::~AndroidConfig() { | ||
| 18 | if (global) { | ||
| 19 | AndroidConfig::SaveAllValues(); | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | void AndroidConfig::ReloadAllValues() { | ||
| 24 | Reload(); | ||
| 25 | ReadAndroidValues(); | ||
| 26 | SaveAndroidValues(); | ||
| 27 | } | ||
| 28 | |||
| 29 | void AndroidConfig::SaveAllValues() { | ||
| 30 | Save(); | ||
| 31 | SaveAndroidValues(); | ||
| 32 | } | ||
| 33 | |||
| 34 | void AndroidConfig::ReadAndroidValues() { | ||
| 35 | if (global) { | ||
| 36 | ReadAndroidUIValues(); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | void AndroidConfig::ReadAndroidUIValues() { | ||
| 41 | BeginGroup(Settings::TranslateCategory(Settings::Category::Android)); | ||
| 42 | |||
| 43 | ReadCategory(Settings::Category::Android); | ||
| 44 | |||
| 45 | EndGroup(); | ||
| 46 | } | ||
| 47 | |||
| 48 | void AndroidConfig::SaveAndroidValues() { | ||
| 49 | if (global) { | ||
| 50 | SaveAndroidUIValues(); | ||
| 51 | } | ||
| 52 | |||
| 53 | WriteToIni(); | ||
| 54 | } | ||
| 55 | |||
| 56 | void AndroidConfig::SaveAndroidUIValues() { | ||
| 57 | BeginGroup(Settings::TranslateCategory(Settings::Category::Android)); | ||
| 58 | |||
| 59 | WriteCategory(Settings::Category::Android); | ||
| 60 | |||
| 61 | EndGroup(); | ||
| 62 | } | ||
| 63 | |||
| 64 | std::vector<Settings::BasicSetting*>& AndroidConfig::FindRelevantList(Settings::Category category) { | ||
| 65 | auto& map = Settings::values.linkage.by_category; | ||
| 66 | if (map.contains(category)) { | ||
| 67 | return Settings::values.linkage.by_category[category]; | ||
| 68 | } | ||
| 69 | return AndroidSettings::values.linkage.by_category[category]; | ||
| 70 | } | ||
diff --git a/src/android/app/src/main/jni/android_config.h b/src/android/app/src/main/jni/android_config.h new file mode 100644 index 000000000..e679392fd --- /dev/null +++ b/src/android/app/src/main/jni/android_config.h | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "frontend_common/config.h" | ||
| 7 | |||
| 8 | class AndroidConfig final : public Config { | ||
| 9 | public: | ||
| 10 | explicit AndroidConfig(const std::string& config_name = "config", | ||
| 11 | ConfigType config_type = ConfigType::GlobalConfig); | ||
| 12 | ~AndroidConfig() override; | ||
| 13 | |||
| 14 | void ReloadAllValues() override; | ||
| 15 | void SaveAllValues() override; | ||
| 16 | |||
| 17 | protected: | ||
| 18 | void ReadAndroidValues(); | ||
| 19 | void ReadAndroidUIValues(); | ||
| 20 | void ReadHidbusValues() override {} | ||
| 21 | void ReadDebugControlValues() override {} | ||
| 22 | void ReadPathValues() override {} | ||
| 23 | void ReadShortcutValues() override {} | ||
| 24 | void ReadUIValues() override {} | ||
| 25 | void ReadUIGamelistValues() override {} | ||
| 26 | void ReadUILayoutValues() override {} | ||
| 27 | void ReadMultiplayerValues() override {} | ||
| 28 | |||
| 29 | void SaveAndroidValues(); | ||
| 30 | void SaveAndroidUIValues(); | ||
| 31 | void SaveHidbusValues() override {} | ||
| 32 | void SaveDebugControlValues() override {} | ||
| 33 | void SavePathValues() override {} | ||
| 34 | void SaveShortcutValues() override {} | ||
| 35 | void SaveUIValues() override {} | ||
| 36 | void SaveUIGamelistValues() override {} | ||
| 37 | void SaveUILayoutValues() override {} | ||
| 38 | void SaveMultiplayerValues() override {} | ||
| 39 | |||
| 40 | std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override; | ||
| 41 | }; | ||
diff --git a/src/android/app/src/main/jni/uisettings.cpp b/src/android/app/src/main/jni/android_settings.cpp index f2f0bad50..16023a6b0 100644 --- a/src/android/app/src/main/jni/uisettings.cpp +++ b/src/android/app/src/main/jni/android_settings.cpp | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "uisettings.h" | 4 | #include "android_settings.h" |
| 5 | 5 | ||
| 6 | namespace AndroidSettings { | 6 | namespace AndroidSettings { |
| 7 | 7 | ||
diff --git a/src/android/app/src/main/jni/uisettings.h b/src/android/app/src/main/jni/android_settings.h index 37bc33918..37bc33918 100644 --- a/src/android/app/src/main/jni/uisettings.h +++ b/src/android/app/src/main/jni/android_settings.h | |||
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp deleted file mode 100644 index 81120ab0f..000000000 --- a/src/android/app/src/main/jni/config.cpp +++ /dev/null | |||
| @@ -1,330 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <memory> | ||
| 5 | #include <optional> | ||
| 6 | #include <sstream> | ||
| 7 | |||
| 8 | #include <INIReader.h> | ||
| 9 | #include "common/fs/file.h" | ||
| 10 | #include "common/fs/fs.h" | ||
| 11 | #include "common/fs/path_util.h" | ||
| 12 | #include "common/logging/log.h" | ||
| 13 | #include "common/settings.h" | ||
| 14 | #include "common/settings_enums.h" | ||
| 15 | #include "core/hle/service/acc/profile_manager.h" | ||
| 16 | #include "input_common/main.h" | ||
| 17 | #include "jni/config.h" | ||
| 18 | #include "jni/default_ini.h" | ||
| 19 | #include "uisettings.h" | ||
| 20 | |||
| 21 | namespace FS = Common::FS; | ||
| 22 | |||
| 23 | Config::Config(const std::string& config_name, ConfigType config_type) | ||
| 24 | : type(config_type), global{config_type == ConfigType::GlobalConfig} { | ||
| 25 | Initialize(config_name); | ||
| 26 | } | ||
| 27 | |||
| 28 | Config::~Config() = default; | ||
| 29 | |||
| 30 | bool Config::LoadINI(const std::string& default_contents, bool retry) { | ||
| 31 | void(FS::CreateParentDir(config_loc)); | ||
| 32 | config = std::make_unique<INIReader>(FS::PathToUTF8String(config_loc)); | ||
| 33 | const auto config_loc_str = FS::PathToUTF8String(config_loc); | ||
| 34 | if (config->ParseError() < 0) { | ||
| 35 | if (retry) { | ||
| 36 | LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", | ||
| 37 | config_loc_str); | ||
| 38 | |||
| 39 | void(FS::CreateParentDir(config_loc)); | ||
| 40 | void(FS::WriteStringToFile(config_loc, FS::FileType::TextFile, default_contents)); | ||
| 41 | |||
| 42 | config = std::make_unique<INIReader>(config_loc_str); | ||
| 43 | |||
| 44 | return LoadINI(default_contents, false); | ||
| 45 | } | ||
| 46 | LOG_ERROR(Config, "Failed."); | ||
| 47 | return false; | ||
| 48 | } | ||
| 49 | LOG_INFO(Config, "Successfully loaded {}", config_loc_str); | ||
| 50 | return true; | ||
| 51 | } | ||
| 52 | |||
| 53 | template <> | ||
| 54 | void Config::ReadSetting(const std::string& group, Settings::Setting<std::string>& setting) { | ||
| 55 | std::string setting_value = config->Get(group, setting.GetLabel(), setting.GetDefault()); | ||
| 56 | if (setting_value.empty()) { | ||
| 57 | setting_value = setting.GetDefault(); | ||
| 58 | } | ||
| 59 | setting = std::move(setting_value); | ||
| 60 | } | ||
| 61 | |||
| 62 | template <> | ||
| 63 | void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) { | ||
| 64 | setting = config->GetBoolean(group, setting.GetLabel(), setting.GetDefault()); | ||
| 65 | } | ||
| 66 | |||
| 67 | template <typename Type, bool ranged> | ||
| 68 | void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) { | ||
| 69 | setting = static_cast<Type>( | ||
| 70 | config->GetInteger(group, setting.GetLabel(), static_cast<long>(setting.GetDefault()))); | ||
| 71 | } | ||
| 72 | |||
| 73 | void Config::ReadValues() { | ||
| 74 | ReadSetting("ControlsGeneral", Settings::values.mouse_enabled); | ||
| 75 | ReadSetting("ControlsGeneral", Settings::values.touch_device); | ||
| 76 | ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled); | ||
| 77 | ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled); | ||
| 78 | ReadSetting("ControlsGeneral", Settings::values.vibration_enabled); | ||
| 79 | ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations); | ||
| 80 | ReadSetting("ControlsGeneral", Settings::values.motion_enabled); | ||
| 81 | Settings::values.touchscreen.enabled = | ||
| 82 | config->GetBoolean("ControlsGeneral", "touch_enabled", true); | ||
| 83 | Settings::values.touchscreen.rotation_angle = | ||
| 84 | config->GetInteger("ControlsGeneral", "touch_angle", 0); | ||
| 85 | Settings::values.touchscreen.diameter_x = | ||
| 86 | config->GetInteger("ControlsGeneral", "touch_diameter_x", 15); | ||
| 87 | Settings::values.touchscreen.diameter_y = | ||
| 88 | config->GetInteger("ControlsGeneral", "touch_diameter_y", 15); | ||
| 89 | |||
| 90 | int num_touch_from_button_maps = | ||
| 91 | config->GetInteger("ControlsGeneral", "touch_from_button_map", 0); | ||
| 92 | if (num_touch_from_button_maps > 0) { | ||
| 93 | for (int i = 0; i < num_touch_from_button_maps; ++i) { | ||
| 94 | Settings::TouchFromButtonMap map; | ||
| 95 | map.name = config->Get("ControlsGeneral", | ||
| 96 | std::string("touch_from_button_maps_") + std::to_string(i) + | ||
| 97 | std::string("_name"), | ||
| 98 | "default"); | ||
| 99 | const int num_touch_maps = config->GetInteger( | ||
| 100 | "ControlsGeneral", | ||
| 101 | std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"), | ||
| 102 | 0); | ||
| 103 | map.buttons.reserve(num_touch_maps); | ||
| 104 | |||
| 105 | for (int j = 0; j < num_touch_maps; ++j) { | ||
| 106 | std::string touch_mapping = | ||
| 107 | config->Get("ControlsGeneral", | ||
| 108 | std::string("touch_from_button_maps_") + std::to_string(i) + | ||
| 109 | std::string("_bind_") + std::to_string(j), | ||
| 110 | ""); | ||
| 111 | map.buttons.emplace_back(std::move(touch_mapping)); | ||
| 112 | } | ||
| 113 | |||
| 114 | Settings::values.touch_from_button_maps.emplace_back(std::move(map)); | ||
| 115 | } | ||
| 116 | } else { | ||
| 117 | Settings::values.touch_from_button_maps.emplace_back( | ||
| 118 | Settings::TouchFromButtonMap{"default", {}}); | ||
| 119 | num_touch_from_button_maps = 1; | ||
| 120 | } | ||
| 121 | Settings::values.touch_from_button_map_index = std::clamp( | ||
| 122 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); | ||
| 123 | |||
| 124 | ReadSetting("ControlsGeneral", Settings::values.udp_input_servers); | ||
| 125 | |||
| 126 | // Data Storage | ||
| 127 | ReadSetting("Data Storage", Settings::values.use_virtual_sd); | ||
| 128 | FS::SetYuzuPath(FS::YuzuPath::NANDDir, | ||
| 129 | config->Get("Data Storage", "nand_directory", | ||
| 130 | FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); | ||
| 131 | FS::SetYuzuPath(FS::YuzuPath::SDMCDir, | ||
| 132 | config->Get("Data Storage", "sdmc_directory", | ||
| 133 | FS::GetYuzuPathString(FS::YuzuPath::SDMCDir))); | ||
| 134 | FS::SetYuzuPath(FS::YuzuPath::LoadDir, | ||
| 135 | config->Get("Data Storage", "load_directory", | ||
| 136 | FS::GetYuzuPathString(FS::YuzuPath::LoadDir))); | ||
| 137 | FS::SetYuzuPath(FS::YuzuPath::DumpDir, | ||
| 138 | config->Get("Data Storage", "dump_directory", | ||
| 139 | FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); | ||
| 140 | ReadSetting("Data Storage", Settings::values.gamecard_inserted); | ||
| 141 | ReadSetting("Data Storage", Settings::values.gamecard_current_game); | ||
| 142 | ReadSetting("Data Storage", Settings::values.gamecard_path); | ||
| 143 | |||
| 144 | // System | ||
| 145 | ReadSetting("System", Settings::values.current_user); | ||
| 146 | Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0, | ||
| 147 | Service::Account::MAX_USERS - 1); | ||
| 148 | |||
| 149 | // Disable docked mode by default on Android | ||
| 150 | Settings::values.use_docked_mode.SetValue(config->GetBoolean("System", "use_docked_mode", false) | ||
| 151 | ? Settings::ConsoleMode::Docked | ||
| 152 | : Settings::ConsoleMode::Handheld); | ||
| 153 | |||
| 154 | const auto rng_seed_enabled = config->GetBoolean("System", "rng_seed_enabled", false); | ||
| 155 | if (rng_seed_enabled) { | ||
| 156 | Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0)); | ||
| 157 | } else { | ||
| 158 | Settings::values.rng_seed.SetValue(0); | ||
| 159 | } | ||
| 160 | Settings::values.rng_seed_enabled.SetValue(rng_seed_enabled); | ||
| 161 | |||
| 162 | const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false); | ||
| 163 | if (custom_rtc_enabled) { | ||
| 164 | Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0); | ||
| 165 | } else { | ||
| 166 | Settings::values.custom_rtc = 0; | ||
| 167 | } | ||
| 168 | Settings::values.custom_rtc_enabled = custom_rtc_enabled; | ||
| 169 | |||
| 170 | ReadSetting("System", Settings::values.language_index); | ||
| 171 | ReadSetting("System", Settings::values.region_index); | ||
| 172 | ReadSetting("System", Settings::values.time_zone_index); | ||
| 173 | ReadSetting("System", Settings::values.sound_index); | ||
| 174 | |||
| 175 | // Core | ||
| 176 | ReadSetting("Core", Settings::values.use_multi_core); | ||
| 177 | ReadSetting("Core", Settings::values.memory_layout_mode); | ||
| 178 | |||
| 179 | // Cpu | ||
| 180 | ReadSetting("Cpu", Settings::values.cpu_accuracy); | ||
| 181 | ReadSetting("Cpu", Settings::values.cpu_debug_mode); | ||
| 182 | ReadSetting("Cpu", Settings::values.cpuopt_page_tables); | ||
| 183 | ReadSetting("Cpu", Settings::values.cpuopt_block_linking); | ||
| 184 | ReadSetting("Cpu", Settings::values.cpuopt_return_stack_buffer); | ||
| 185 | ReadSetting("Cpu", Settings::values.cpuopt_fast_dispatcher); | ||
| 186 | ReadSetting("Cpu", Settings::values.cpuopt_context_elimination); | ||
| 187 | ReadSetting("Cpu", Settings::values.cpuopt_const_prop); | ||
| 188 | ReadSetting("Cpu", Settings::values.cpuopt_misc_ir); | ||
| 189 | ReadSetting("Cpu", Settings::values.cpuopt_reduce_misalign_checks); | ||
| 190 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem); | ||
| 191 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives); | ||
| 192 | ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); | ||
| 193 | ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts); | ||
| 194 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma); | ||
| 195 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error); | ||
| 196 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); | ||
| 197 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_inaccurate_nan); | ||
| 198 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_fastmem_check); | ||
| 199 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_global_monitor); | ||
| 200 | |||
| 201 | // Renderer | ||
| 202 | ReadSetting("Renderer", Settings::values.renderer_backend); | ||
| 203 | ReadSetting("Renderer", Settings::values.renderer_debug); | ||
| 204 | ReadSetting("Renderer", Settings::values.renderer_shader_feedback); | ||
| 205 | ReadSetting("Renderer", Settings::values.enable_nsight_aftermath); | ||
| 206 | ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks); | ||
| 207 | ReadSetting("Renderer", Settings::values.vulkan_device); | ||
| 208 | |||
| 209 | ReadSetting("Renderer", Settings::values.resolution_setup); | ||
| 210 | ReadSetting("Renderer", Settings::values.scaling_filter); | ||
| 211 | ReadSetting("Renderer", Settings::values.fsr_sharpening_slider); | ||
| 212 | ReadSetting("Renderer", Settings::values.anti_aliasing); | ||
| 213 | ReadSetting("Renderer", Settings::values.fullscreen_mode); | ||
| 214 | ReadSetting("Renderer", Settings::values.aspect_ratio); | ||
| 215 | ReadSetting("Renderer", Settings::values.max_anisotropy); | ||
| 216 | ReadSetting("Renderer", Settings::values.use_speed_limit); | ||
| 217 | ReadSetting("Renderer", Settings::values.speed_limit); | ||
| 218 | ReadSetting("Renderer", Settings::values.use_disk_shader_cache); | ||
| 219 | ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation); | ||
| 220 | ReadSetting("Renderer", Settings::values.vsync_mode); | ||
| 221 | ReadSetting("Renderer", Settings::values.shader_backend); | ||
| 222 | ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); | ||
| 223 | ReadSetting("Renderer", Settings::values.nvdec_emulation); | ||
| 224 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); | ||
| 225 | ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); | ||
| 226 | |||
| 227 | ReadSetting("Renderer", Settings::values.bg_red); | ||
| 228 | ReadSetting("Renderer", Settings::values.bg_green); | ||
| 229 | ReadSetting("Renderer", Settings::values.bg_blue); | ||
| 230 | |||
| 231 | // Use GPU accuracy normal by default on Android | ||
| 232 | Settings::values.gpu_accuracy = static_cast<Settings::GpuAccuracy>(config->GetInteger( | ||
| 233 | "Renderer", "gpu_accuracy", static_cast<u32>(Settings::GpuAccuracy::Normal))); | ||
| 234 | |||
| 235 | // Use GPU default anisotropic filtering on Android | ||
| 236 | Settings::values.max_anisotropy = | ||
| 237 | static_cast<Settings::AnisotropyMode>(config->GetInteger("Renderer", "max_anisotropy", 1)); | ||
| 238 | |||
| 239 | // Disable ASTC compute by default on Android | ||
| 240 | Settings::values.accelerate_astc.SetValue( | ||
| 241 | config->GetBoolean("Renderer", "accelerate_astc", false) ? Settings::AstcDecodeMode::Gpu | ||
| 242 | : Settings::AstcDecodeMode::Cpu); | ||
| 243 | |||
| 244 | // Enable asynchronous presentation by default on Android | ||
| 245 | Settings::values.async_presentation = | ||
| 246 | config->GetBoolean("Renderer", "async_presentation", true); | ||
| 247 | |||
| 248 | // Disable force_max_clock by default on Android | ||
| 249 | Settings::values.renderer_force_max_clock = | ||
| 250 | config->GetBoolean("Renderer", "force_max_clock", false); | ||
| 251 | |||
| 252 | // Disable use_reactive_flushing by default on Android | ||
| 253 | Settings::values.use_reactive_flushing = | ||
| 254 | config->GetBoolean("Renderer", "use_reactive_flushing", false); | ||
| 255 | |||
| 256 | // Audio | ||
| 257 | ReadSetting("Audio", Settings::values.sink_id); | ||
| 258 | ReadSetting("Audio", Settings::values.audio_output_device_id); | ||
| 259 | ReadSetting("Audio", Settings::values.volume); | ||
| 260 | |||
| 261 | // Miscellaneous | ||
| 262 | // log_filter has a different default here than from common | ||
| 263 | Settings::values.log_filter = "*:Info"; | ||
| 264 | ReadSetting("Miscellaneous", Settings::values.use_dev_keys); | ||
| 265 | |||
| 266 | // Debugging | ||
| 267 | Settings::values.record_frame_times = | ||
| 268 | config->GetBoolean("Debugging", "record_frame_times", false); | ||
| 269 | ReadSetting("Debugging", Settings::values.dump_exefs); | ||
| 270 | ReadSetting("Debugging", Settings::values.dump_nso); | ||
| 271 | ReadSetting("Debugging", Settings::values.enable_fs_access_log); | ||
| 272 | ReadSetting("Debugging", Settings::values.reporting_services); | ||
| 273 | ReadSetting("Debugging", Settings::values.quest_flag); | ||
| 274 | ReadSetting("Debugging", Settings::values.use_debug_asserts); | ||
| 275 | ReadSetting("Debugging", Settings::values.use_auto_stub); | ||
| 276 | ReadSetting("Debugging", Settings::values.disable_macro_jit); | ||
| 277 | ReadSetting("Debugging", Settings::values.disable_macro_hle); | ||
| 278 | ReadSetting("Debugging", Settings::values.use_gdbstub); | ||
| 279 | ReadSetting("Debugging", Settings::values.gdbstub_port); | ||
| 280 | |||
| 281 | const auto title_list = config->Get("AddOns", "title_ids", ""); | ||
| 282 | std::stringstream ss(title_list); | ||
| 283 | std::string line; | ||
| 284 | while (std::getline(ss, line, '|')) { | ||
| 285 | const auto title_id = std::strtoul(line.c_str(), nullptr, 16); | ||
| 286 | const auto disabled_list = config->Get("AddOns", "disabled_" + line, ""); | ||
| 287 | |||
| 288 | std::stringstream inner_ss(disabled_list); | ||
| 289 | std::string inner_line; | ||
| 290 | std::vector<std::string> out; | ||
| 291 | while (std::getline(inner_ss, inner_line, '|')) { | ||
| 292 | out.push_back(inner_line); | ||
| 293 | } | ||
| 294 | |||
| 295 | Settings::values.disabled_addons.insert_or_assign(title_id, out); | ||
| 296 | } | ||
| 297 | |||
| 298 | // Web Service | ||
| 299 | ReadSetting("WebService", Settings::values.enable_telemetry); | ||
| 300 | ReadSetting("WebService", Settings::values.web_api_url); | ||
| 301 | ReadSetting("WebService", Settings::values.yuzu_username); | ||
| 302 | ReadSetting("WebService", Settings::values.yuzu_token); | ||
| 303 | |||
| 304 | // Network | ||
| 305 | ReadSetting("Network", Settings::values.network_interface); | ||
| 306 | |||
| 307 | // Android | ||
| 308 | ReadSetting("Android", AndroidSettings::values.picture_in_picture); | ||
| 309 | ReadSetting("Android", AndroidSettings::values.screen_layout); | ||
| 310 | } | ||
| 311 | |||
| 312 | void Config::Initialize(const std::string& config_name) { | ||
| 313 | const auto fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir); | ||
| 314 | const auto config_file = fmt::format("{}.ini", config_name); | ||
| 315 | |||
| 316 | switch (type) { | ||
| 317 | case ConfigType::GlobalConfig: | ||
| 318 | config_loc = FS::PathToUTF8String(fs_config_loc / config_file); | ||
| 319 | break; | ||
| 320 | case ConfigType::PerGameConfig: | ||
| 321 | config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file)); | ||
| 322 | break; | ||
| 323 | case ConfigType::InputProfile: | ||
| 324 | config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file); | ||
| 325 | LoadINI(DefaultINI::android_config_file); | ||
| 326 | return; | ||
| 327 | } | ||
| 328 | LoadINI(DefaultINI::android_config_file); | ||
| 329 | ReadValues(); | ||
| 330 | } | ||
diff --git a/src/android/app/src/main/jni/config.h b/src/android/app/src/main/jni/config.h deleted file mode 100644 index e1e8f47ed..000000000 --- a/src/android/app/src/main/jni/config.h +++ /dev/null | |||
| @@ -1,47 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <filesystem> | ||
| 7 | #include <memory> | ||
| 8 | #include <optional> | ||
| 9 | #include <string> | ||
| 10 | |||
| 11 | #include "common/settings.h" | ||
| 12 | |||
| 13 | class INIReader; | ||
| 14 | |||
| 15 | class Config { | ||
| 16 | bool LoadINI(const std::string& default_contents = "", bool retry = true); | ||
| 17 | |||
| 18 | public: | ||
| 19 | enum class ConfigType { | ||
| 20 | GlobalConfig, | ||
| 21 | PerGameConfig, | ||
| 22 | InputProfile, | ||
| 23 | }; | ||
| 24 | |||
| 25 | explicit Config(const std::string& config_name = "config", | ||
| 26 | ConfigType config_type = ConfigType::GlobalConfig); | ||
| 27 | ~Config(); | ||
| 28 | |||
| 29 | void Initialize(const std::string& config_name); | ||
| 30 | |||
| 31 | private: | ||
| 32 | /** | ||
| 33 | * Applies a value read from the config to a Setting. | ||
| 34 | * | ||
| 35 | * @param group The name of the INI group | ||
| 36 | * @param setting The yuzu setting to modify | ||
| 37 | */ | ||
| 38 | template <typename Type, bool ranged> | ||
| 39 | void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting); | ||
| 40 | |||
| 41 | void ReadValues(); | ||
| 42 | |||
| 43 | const ConfigType type; | ||
| 44 | std::unique_ptr<INIReader> config; | ||
| 45 | std::string config_loc; | ||
| 46 | const bool global; | ||
| 47 | }; | ||
diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h deleted file mode 100644 index d81422a74..000000000 --- a/src/android/app/src/main/jni/default_ini.h +++ /dev/null | |||
| @@ -1,511 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | namespace DefaultINI { | ||
| 7 | |||
| 8 | const char* android_config_file = R"( | ||
| 9 | |||
| 10 | [ControlsP0] | ||
| 11 | # The input devices and parameters for each Switch native input | ||
| 12 | # The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ... | ||
| 13 | # It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..." | ||
| 14 | # Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values | ||
| 15 | |||
| 16 | # Indicates if this player should be connected at boot | ||
| 17 | connected= | ||
| 18 | |||
| 19 | # for button input, the following devices are available: | ||
| 20 | # - "keyboard" (default) for keyboard input. Required parameters: | ||
| 21 | # - "code": the code of the key to bind | ||
| 22 | # - "sdl" for joystick input using SDL. Required parameters: | ||
| 23 | # - "guid": SDL identification GUID of the joystick | ||
| 24 | # - "port": the index of the joystick to bind | ||
| 25 | # - "button"(optional): the index of the button to bind | ||
| 26 | # - "hat"(optional): the index of the hat to bind as direction buttons | ||
| 27 | # - "axis"(optional): the index of the axis to bind | ||
| 28 | # - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right" | ||
| 29 | # - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is | ||
| 30 | # triggered if the axis value crosses | ||
| 31 | # - "direction"(only used for axis): "+" means the button is triggered when the axis value | ||
| 32 | # is greater than the threshold; "-" means the button is triggered when the axis value | ||
| 33 | # is smaller than the threshold | ||
| 34 | button_a= | ||
| 35 | button_b= | ||
| 36 | button_x= | ||
| 37 | button_y= | ||
| 38 | button_lstick= | ||
| 39 | button_rstick= | ||
| 40 | button_l= | ||
| 41 | button_r= | ||
| 42 | button_zl= | ||
| 43 | button_zr= | ||
| 44 | button_plus= | ||
| 45 | button_minus= | ||
| 46 | button_dleft= | ||
| 47 | button_dup= | ||
| 48 | button_dright= | ||
| 49 | button_ddown= | ||
| 50 | button_lstick_left= | ||
| 51 | button_lstick_up= | ||
| 52 | button_lstick_right= | ||
| 53 | button_lstick_down= | ||
| 54 | button_sl= | ||
| 55 | button_sr= | ||
| 56 | button_home= | ||
| 57 | button_screenshot= | ||
| 58 | |||
| 59 | # for analog input, the following devices are available: | ||
| 60 | # - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters: | ||
| 61 | # - "up", "down", "left", "right": sub-devices for each direction. | ||
| 62 | # Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00" | ||
| 63 | # - "modifier": sub-devices as a modifier. | ||
| 64 | # - "modifier_scale": a float number representing the applied modifier scale to the analog input. | ||
| 65 | # Must be in range of 0.0-1.0. Defaults to 0.5 | ||
| 66 | # - "sdl" for joystick input using SDL. Required parameters: | ||
| 67 | # - "guid": SDL identification GUID of the joystick | ||
| 68 | # - "port": the index of the joystick to bind | ||
| 69 | # - "axis_x": the index of the axis to bind as x-axis (default to 0) | ||
| 70 | # - "axis_y": the index of the axis to bind as y-axis (default to 1) | ||
| 71 | lstick= | ||
| 72 | rstick= | ||
| 73 | |||
| 74 | # for motion input, the following devices are available: | ||
| 75 | # - "keyboard" (default) for emulating random motion input from buttons. Required parameters: | ||
| 76 | # - "code": the code of the key to bind | ||
| 77 | # - "sdl" for motion input using SDL. Required parameters: | ||
| 78 | # - "guid": SDL identification GUID of the joystick | ||
| 79 | # - "port": the index of the joystick to bind | ||
| 80 | # - "motion": the index of the motion sensor to bind | ||
| 81 | # - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters: | ||
| 82 | # - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001" | ||
| 83 | # - "port": the port of the cemu hook server | ||
| 84 | # - "pad": the index of the joystick | ||
| 85 | # - "motion": the index of the motion sensor of the joystick to bind | ||
| 86 | motionleft= | ||
| 87 | motionright= | ||
| 88 | |||
| 89 | [ControlsGeneral] | ||
| 90 | # To use the debug_pad, prepend `debug_pad_` before each button setting above. | ||
| 91 | # i.e. debug_pad_button_a= | ||
| 92 | |||
| 93 | # Enable debug pad inputs to the guest | ||
| 94 | # 0 (default): Disabled, 1: Enabled | ||
| 95 | debug_pad_enabled = | ||
| 96 | |||
| 97 | # Whether to enable or disable vibration | ||
| 98 | # 0: Disabled, 1 (default): Enabled | ||
| 99 | vibration_enabled= | ||
| 100 | |||
| 101 | # Whether to enable or disable accurate vibrations | ||
| 102 | # 0 (default): Disabled, 1: Enabled | ||
| 103 | enable_accurate_vibrations= | ||
| 104 | |||
| 105 | # Enables controller motion inputs | ||
| 106 | # 0: Disabled, 1 (default): Enabled | ||
| 107 | motion_enabled = | ||
| 108 | |||
| 109 | # Defines the udp device's touch screen coordinate system for cemuhookudp devices | ||
| 110 | # - "min_x", "min_y", "max_x", "max_y" | ||
| 111 | touch_device= | ||
| 112 | |||
| 113 | # for mapping buttons to touch inputs. | ||
| 114 | #touch_from_button_map=1 | ||
| 115 | #touch_from_button_maps_0_name=default | ||
| 116 | #touch_from_button_maps_0_count=2 | ||
| 117 | #touch_from_button_maps_0_bind_0=foo | ||
| 118 | #touch_from_button_maps_0_bind_1=bar | ||
| 119 | # etc. | ||
| 120 | |||
| 121 | # List of Cemuhook UDP servers, delimited by ','. | ||
| 122 | # Default: 127.0.0.1:26760 | ||
| 123 | # Example: 127.0.0.1:26760,123.4.5.67:26761 | ||
| 124 | udp_input_servers = | ||
| 125 | |||
| 126 | # Enable controlling an axis via a mouse input. | ||
| 127 | # 0 (default): Off, 1: On | ||
| 128 | mouse_panning = | ||
| 129 | |||
| 130 | # Set mouse sensitivity. | ||
| 131 | # Default: 1.0 | ||
| 132 | mouse_panning_sensitivity = | ||
| 133 | |||
| 134 | # Emulate an analog control stick from keyboard inputs. | ||
| 135 | # 0 (default): Disabled, 1: Enabled | ||
| 136 | emulate_analog_keyboard = | ||
| 137 | |||
| 138 | # Enable mouse inputs to the guest | ||
| 139 | # 0 (default): Disabled, 1: Enabled | ||
| 140 | mouse_enabled = | ||
| 141 | |||
| 142 | # Enable keyboard inputs to the guest | ||
| 143 | # 0 (default): Disabled, 1: Enabled | ||
| 144 | keyboard_enabled = | ||
| 145 | |||
| 146 | [Core] | ||
| 147 | # Whether to use multi-core for CPU emulation | ||
| 148 | # 0: Disabled, 1 (default): Enabled | ||
| 149 | use_multi_core = | ||
| 150 | |||
| 151 | # Enable unsafe extended guest system memory layout (8GB DRAM) | ||
| 152 | # 0 (default): Disabled, 1: Enabled | ||
| 153 | use_unsafe_extended_memory_layout = | ||
| 154 | |||
| 155 | [Cpu] | ||
| 156 | # Adjusts various optimizations. | ||
| 157 | # Auto-select mode enables choice unsafe optimizations. | ||
| 158 | # Accurate enables only safe optimizations. | ||
| 159 | # Unsafe allows any unsafe optimizations. | ||
| 160 | # 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations | ||
| 161 | cpu_accuracy = | ||
| 162 | |||
| 163 | # Allow disabling safe optimizations. | ||
| 164 | # 0 (default): Disabled, 1: Enabled | ||
| 165 | cpu_debug_mode = | ||
| 166 | |||
| 167 | # Enable inline page tables optimization (faster guest memory access) | ||
| 168 | # 0: Disabled, 1 (default): Enabled | ||
| 169 | cpuopt_page_tables = | ||
| 170 | |||
| 171 | # Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps) | ||
| 172 | # 0: Disabled, 1 (default): Enabled | ||
| 173 | cpuopt_block_linking = | ||
| 174 | |||
| 175 | # Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns) | ||
| 176 | # 0: Disabled, 1 (default): Enabled | ||
| 177 | cpuopt_return_stack_buffer = | ||
| 178 | |||
| 179 | # Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture) | ||
| 180 | # 0: Disabled, 1 (default): Enabled | ||
| 181 | cpuopt_fast_dispatcher = | ||
| 182 | |||
| 183 | # Enable context elimination CPU Optimization (reduce host memory use for guest context) | ||
| 184 | # 0: Disabled, 1 (default): Enabled | ||
| 185 | cpuopt_context_elimination = | ||
| 186 | |||
| 187 | # Enable constant propagation CPU optimization (basic IR optimization) | ||
| 188 | # 0: Disabled, 1 (default): Enabled | ||
| 189 | cpuopt_const_prop = | ||
| 190 | |||
| 191 | # Enable miscellaneous CPU optimizations (basic IR optimization) | ||
| 192 | # 0: Disabled, 1 (default): Enabled | ||
| 193 | cpuopt_misc_ir = | ||
| 194 | |||
| 195 | # Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access) | ||
| 196 | # 0: Disabled, 1 (default): Enabled | ||
| 197 | cpuopt_reduce_misalign_checks = | ||
| 198 | |||
| 199 | # Enable Host MMU Emulation (faster guest memory access) | ||
| 200 | # 0: Disabled, 1 (default): Enabled | ||
| 201 | cpuopt_fastmem = | ||
| 202 | |||
| 203 | # Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access) | ||
| 204 | # 0: Disabled, 1 (default): Enabled | ||
| 205 | cpuopt_fastmem_exclusives = | ||
| 206 | |||
| 207 | # Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access) | ||
| 208 | # 0: Disabled, 1 (default): Enabled | ||
| 209 | cpuopt_recompile_exclusives = | ||
| 210 | |||
| 211 | # Enable optimization to ignore invalid memory accesses (faster guest memory access) | ||
| 212 | # 0: Disabled, 1 (default): Enabled | ||
| 213 | cpuopt_ignore_memory_aborts = | ||
| 214 | |||
| 215 | # Enable unfuse FMA (improve performance on CPUs without FMA) | ||
| 216 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 217 | # 0: Disabled, 1 (default): Enabled | ||
| 218 | cpuopt_unsafe_unfuse_fma = | ||
| 219 | |||
| 220 | # Enable faster FRSQRTE and FRECPE | ||
| 221 | # Only enabled if cpu_accuracy is set to Unsafe. | ||
| 222 | # 0: Disabled, 1 (default): Enabled | ||
| 223 | cpuopt_unsafe_reduce_fp_error = | ||
| 224 | |||
| 225 | # Enable faster ASIMD instructions (32 bits only) | ||
| 226 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 227 | # 0: Disabled, 1 (default): Enabled | ||
| 228 | cpuopt_unsafe_ignore_standard_fpcr = | ||
| 229 | |||
| 230 | # Enable inaccurate NaN handling | ||
| 231 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 232 | # 0: Disabled, 1 (default): Enabled | ||
| 233 | cpuopt_unsafe_inaccurate_nan = | ||
| 234 | |||
| 235 | # Disable address space checks (64 bits only) | ||
| 236 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 237 | # 0: Disabled, 1 (default): Enabled | ||
| 238 | cpuopt_unsafe_fastmem_check = | ||
| 239 | |||
| 240 | # Enable faster exclusive instructions | ||
| 241 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 242 | # 0: Disabled, 1 (default): Enabled | ||
| 243 | cpuopt_unsafe_ignore_global_monitor = | ||
| 244 | |||
| 245 | [Renderer] | ||
| 246 | # Which backend API to use. | ||
| 247 | # 0: OpenGL (unsupported), 1 (default): Vulkan, 2: Null | ||
| 248 | backend = | ||
| 249 | |||
| 250 | # Whether to enable asynchronous presentation (Vulkan only) | ||
| 251 | # 0: Off, 1 (default): On | ||
| 252 | async_presentation = | ||
| 253 | |||
| 254 | # Forces the GPU to run at the maximum possible clocks (thermal constraints will still be applied). | ||
| 255 | # 0 (default): Disabled, 1: Enabled | ||
| 256 | force_max_clock = | ||
| 257 | |||
| 258 | # Enable graphics API debugging mode. | ||
| 259 | # 0 (default): Disabled, 1: Enabled | ||
| 260 | debug = | ||
| 261 | |||
| 262 | # Enable shader feedback. | ||
| 263 | # 0 (default): Disabled, 1: Enabled | ||
| 264 | renderer_shader_feedback = | ||
| 265 | |||
| 266 | # Enable Nsight Aftermath crash dumps | ||
| 267 | # 0 (default): Disabled, 1: Enabled | ||
| 268 | nsight_aftermath = | ||
| 269 | |||
| 270 | # Disable shader loop safety checks, executing the shader without loop logic changes | ||
| 271 | # 0 (default): Disabled, 1: Enabled | ||
| 272 | disable_shader_loop_safety_checks = | ||
| 273 | |||
| 274 | # Which Vulkan physical device to use (defaults to 0) | ||
| 275 | vulkan_device = | ||
| 276 | |||
| 277 | # 0: 0.5x (360p/540p) [EXPERIMENTAL] | ||
| 278 | # 1: 0.75x (540p/810p) [EXPERIMENTAL] | ||
| 279 | # 2 (default): 1x (720p/1080p) | ||
| 280 | # 3: 2x (1440p/2160p) | ||
| 281 | # 4: 3x (2160p/3240p) | ||
| 282 | # 5: 4x (2880p/4320p) | ||
| 283 | # 6: 5x (3600p/5400p) | ||
| 284 | # 7: 6x (4320p/6480p) | ||
| 285 | resolution_setup = | ||
| 286 | |||
| 287 | # Pixel filter to use when up- or down-sampling rendered frames. | ||
| 288 | # 0: Nearest Neighbor | ||
| 289 | # 1 (default): Bilinear | ||
| 290 | # 2: Bicubic | ||
| 291 | # 3: Gaussian | ||
| 292 | # 4: ScaleForce | ||
| 293 | # 5: AMD FidelityFX™️ Super Resolution [Vulkan Only] | ||
| 294 | scaling_filter = | ||
| 295 | |||
| 296 | # Anti-Aliasing (AA) | ||
| 297 | # 0 (default): None, 1: FXAA | ||
| 298 | anti_aliasing = | ||
| 299 | |||
| 300 | # Whether to use fullscreen or borderless window mode | ||
| 301 | # 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen | ||
| 302 | fullscreen_mode = | ||
| 303 | |||
| 304 | # Aspect ratio | ||
| 305 | # 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Force 16:10, 4: Stretch to Window | ||
| 306 | aspect_ratio = | ||
| 307 | |||
| 308 | # Anisotropic filtering | ||
| 309 | # 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x | ||
| 310 | max_anisotropy = | ||
| 311 | |||
| 312 | # Whether to enable VSync or not. | ||
| 313 | # OpenGL: Values other than 0 enable VSync | ||
| 314 | # Vulkan: FIFO is selected if the requested mode is not supported by the driver. | ||
| 315 | # FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate. | ||
| 316 | # FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down. | ||
| 317 | # Mailbox can have lower latency than FIFO and does not tear but may drop frames. | ||
| 318 | # Immediate (no synchronization) just presents whatever is available and can exhibit tearing. | ||
| 319 | # 0: Immediate (Off), 1 (Default): Mailbox (On), 2: FIFO, 3: FIFO Relaxed | ||
| 320 | use_vsync = | ||
| 321 | |||
| 322 | # Selects the OpenGL shader backend. NV_gpu_program5 is required for GLASM. If NV_gpu_program5 is | ||
| 323 | # not available and GLASM is selected, GLSL will be used. | ||
| 324 | # 0: GLSL, 1 (default): GLASM, 2: SPIR-V | ||
| 325 | shader_backend = | ||
| 326 | |||
| 327 | # Whether to allow asynchronous shader building. | ||
| 328 | # 0 (default): Off, 1: On | ||
| 329 | use_asynchronous_shaders = | ||
| 330 | |||
| 331 | # Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory. | ||
| 332 | # 0 (default): Off, 1: On | ||
| 333 | use_reactive_flushing = | ||
| 334 | |||
| 335 | # NVDEC emulation. | ||
| 336 | # 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding | ||
| 337 | nvdec_emulation = | ||
| 338 | |||
| 339 | # Accelerate ASTC texture decoding. | ||
| 340 | # 0 (default): Off, 1: On | ||
| 341 | accelerate_astc = | ||
| 342 | |||
| 343 | # Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value | ||
| 344 | # 0: Off, 1: On (default) | ||
| 345 | use_speed_limit = | ||
| 346 | |||
| 347 | # Limits the speed of the game to run no faster than this value as a percentage of target speed | ||
| 348 | # 1 - 9999: Speed limit as a percentage of target game speed. 100 (default) | ||
| 349 | speed_limit = | ||
| 350 | |||
| 351 | # Whether to use disk based shader cache | ||
| 352 | # 0: Off, 1 (default): On | ||
| 353 | use_disk_shader_cache = | ||
| 354 | |||
| 355 | # Which gpu accuracy level to use | ||
| 356 | # 0 (default): Normal, 1: High, 2: Extreme (Very slow) | ||
| 357 | gpu_accuracy = | ||
| 358 | |||
| 359 | # Whether to use asynchronous GPU emulation | ||
| 360 | # 0 : Off (slow), 1 (default): On (fast) | ||
| 361 | use_asynchronous_gpu_emulation = | ||
| 362 | |||
| 363 | # Inform the guest that GPU operations completed more quickly than they did. | ||
| 364 | # 0: Off, 1 (default): On | ||
| 365 | use_fast_gpu_time = | ||
| 366 | |||
| 367 | # Force unmodified buffers to be flushed, which can cost performance. | ||
| 368 | # 0: Off (default), 1: On | ||
| 369 | use_pessimistic_flushes = | ||
| 370 | |||
| 371 | # Whether to use garbage collection or not for GPU caches. | ||
| 372 | # 0 (default): Off, 1: On | ||
| 373 | use_caches_gc = | ||
| 374 | |||
| 375 | # The clear color for the renderer. What shows up on the sides of the bottom screen. | ||
| 376 | # Must be in range of 0-255. Defaults to 0 for all. | ||
| 377 | bg_red = | ||
| 378 | bg_blue = | ||
| 379 | bg_green = | ||
| 380 | |||
| 381 | [Audio] | ||
| 382 | # Which audio output engine to use. | ||
| 383 | # auto (default): Auto-select | ||
| 384 | # cubeb: Cubeb audio engine (if available) | ||
| 385 | # sdl2: SDL2 audio engine (if available) | ||
| 386 | # null: No audio output | ||
| 387 | output_engine = | ||
| 388 | |||
| 389 | # Which audio device to use. | ||
| 390 | # auto (default): Auto-select | ||
| 391 | output_device = | ||
| 392 | |||
| 393 | # Output volume. | ||
| 394 | # 100 (default): 100%, 0; mute | ||
| 395 | volume = | ||
| 396 | |||
| 397 | [Data Storage] | ||
| 398 | # Whether to create a virtual SD card. | ||
| 399 | # 1: Yes, 0 (default): No | ||
| 400 | use_virtual_sd = | ||
| 401 | |||
| 402 | # Whether or not to enable gamecard emulation | ||
| 403 | # 1: Yes, 0 (default): No | ||
| 404 | gamecard_inserted = | ||
| 405 | |||
| 406 | # Whether or not the gamecard should be emulated as the current game | ||
| 407 | # If 'gamecard_inserted' is 0 this setting is irrelevant | ||
| 408 | # 1: Yes, 0 (default): No | ||
| 409 | gamecard_current_game = | ||
| 410 | |||
| 411 | # Path to an XCI file to use as the gamecard | ||
| 412 | # If 'gamecard_inserted' is 0 this setting is irrelevant | ||
| 413 | # If 'gamecard_current_game' is 1 this setting is irrelevant | ||
| 414 | gamecard_path = | ||
| 415 | |||
| 416 | [System] | ||
| 417 | # Whether the system is docked | ||
| 418 | # 1 (default): Yes, 0: No | ||
| 419 | use_docked_mode = | ||
| 420 | |||
| 421 | # Sets the seed for the RNG generator built into the switch | ||
| 422 | # rng_seed will be ignored and randomly generated if rng_seed_enabled is false | ||
| 423 | rng_seed_enabled = | ||
| 424 | rng_seed = | ||
| 425 | |||
| 426 | # Sets the current time (in seconds since 12:00 AM Jan 1, 1970) that will be used by the time service | ||
| 427 | # This will auto-increment, with the time set being the time the game is started | ||
| 428 | # This override will only occur if custom_rtc_enabled is true, otherwise the current time is used | ||
| 429 | custom_rtc_enabled = | ||
| 430 | custom_rtc = | ||
| 431 | |||
| 432 | # Sets the systems language index | ||
| 433 | # 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese, | ||
| 434 | # 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French, | ||
| 435 | # 14: Latin American Spanish, 15: Simplified Chinese, 16: Traditional Chinese, 17: Brazilian Portuguese | ||
| 436 | language_index = | ||
| 437 | |||
| 438 | # The system region that yuzu will use during emulation | ||
| 439 | # -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan | ||
| 440 | region_index = | ||
| 441 | |||
| 442 | # The system time zone that yuzu will use during emulation | ||
| 443 | # 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone | ||
| 444 | time_zone_index = | ||
| 445 | |||
| 446 | # Sets the sound output mode. | ||
| 447 | # 0: Mono, 1 (default): Stereo, 2: Surround | ||
| 448 | sound_index = | ||
| 449 | |||
| 450 | [Miscellaneous] | ||
| 451 | # A filter which removes logs below a certain logging level. | ||
| 452 | # Examples: *:Debug Kernel.SVC:Trace Service.*:Critical | ||
| 453 | log_filter = *:Trace | ||
| 454 | |||
| 455 | # Use developer keys | ||
| 456 | # 0 (default): Disabled, 1: Enabled | ||
| 457 | use_dev_keys = | ||
| 458 | |||
| 459 | [Debugging] | ||
| 460 | # Record frame time data, can be found in the log directory. Boolean value | ||
| 461 | record_frame_times = | ||
| 462 | # Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them | ||
| 463 | dump_exefs=false | ||
| 464 | # Determines whether or not yuzu will dump all NSOs it attempts to load while loading them | ||
| 465 | dump_nso=false | ||
| 466 | # Determines whether or not yuzu will save the filesystem access log. | ||
| 467 | enable_fs_access_log=false | ||
| 468 | # Enables verbose reporting services | ||
| 469 | reporting_services = | ||
| 470 | # Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode | ||
| 471 | # false: Retail/Normal Mode (default), true: Kiosk Mode | ||
| 472 | quest_flag = | ||
| 473 | # Determines whether debug asserts should be enabled, which will throw an exception on asserts. | ||
| 474 | # false: Disabled (default), true: Enabled | ||
| 475 | use_debug_asserts = | ||
| 476 | # Determines whether unimplemented HLE service calls should be automatically stubbed. | ||
| 477 | # false: Disabled (default), true: Enabled | ||
| 478 | use_auto_stub = | ||
| 479 | # Enables/Disables the macro JIT compiler | ||
| 480 | disable_macro_jit=false | ||
| 481 | # Determines whether to enable the GDB stub and wait for the debugger to attach before running. | ||
| 482 | # false: Disabled (default), true: Enabled | ||
| 483 | use_gdbstub=false | ||
| 484 | # The port to use for the GDB server, if it is enabled. | ||
| 485 | gdbstub_port=6543 | ||
| 486 | |||
| 487 | [WebService] | ||
| 488 | # Whether or not to enable telemetry | ||
| 489 | # 0: No, 1 (default): Yes | ||
| 490 | enable_telemetry = | ||
| 491 | # URL for Web API | ||
| 492 | web_api_url = https://api.yuzu-emu.org | ||
| 493 | # Username and token for yuzu Web Service | ||
| 494 | # See https://profile.yuzu-emu.org/ for more info | ||
| 495 | yuzu_username = | ||
| 496 | yuzu_token = | ||
| 497 | |||
| 498 | [Network] | ||
| 499 | # Name of the network interface device to use with yuzu LAN play. | ||
| 500 | # e.g. On *nix: 'enp7s0', 'wlp6s0u1u3u3', 'lo' | ||
| 501 | # e.g. On Windows: 'Ethernet', 'Wi-Fi' | ||
| 502 | network_interface = | ||
| 503 | |||
| 504 | [AddOns] | ||
| 505 | # Used to disable add-ons | ||
| 506 | # List of title IDs of games that will have add-ons disabled (separated by '|'): | ||
| 507 | title_ids = | ||
| 508 | # For each title ID, have a key/value pair called `disabled_<title_id>` equal to the names of the add-ons to disable (sep. by '|') | ||
| 509 | # e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey | ||
| 510 | )"; | ||
| 511 | } // namespace DefaultINI | ||
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 64663b084..617288ae4 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp | |||
| @@ -52,8 +52,8 @@ | |||
| 52 | #include "core/hle/service/am/applets/applets.h" | 52 | #include "core/hle/service/am/applets/applets.h" |
| 53 | #include "core/hle/service/filesystem/filesystem.h" | 53 | #include "core/hle/service/filesystem/filesystem.h" |
| 54 | #include "core/loader/loader.h" | 54 | #include "core/loader/loader.h" |
| 55 | #include "frontend_common/config.h" | ||
| 55 | #include "jni/android_common/android_common.h" | 56 | #include "jni/android_common/android_common.h" |
| 56 | #include "jni/config.h" | ||
| 57 | #include "jni/id_cache.h" | 57 | #include "jni/id_cache.h" |
| 58 | #include "jni/native.h" | 58 | #include "jni/native.h" |
| 59 | #include "video_core/renderer_base.h" | 59 | #include "video_core/renderer_base.h" |
| @@ -664,8 +664,6 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased(JNIEnv* env, jclass c | |||
| 664 | 664 | ||
| 665 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz, | 665 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz, |
| 666 | jboolean reload) { | 666 | jboolean reload) { |
| 667 | // Create the default config.ini. | ||
| 668 | Config{}; | ||
| 669 | // Initialize the emulated system. | 667 | // Initialize the emulated system. |
| 670 | if (!reload) { | 668 | if (!reload) { |
| 671 | EmulationSession::GetInstance().System().Initialize(); | 669 | EmulationSession::GetInstance().System().Initialize(); |
| @@ -680,17 +678,6 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass cl | |||
| 680 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2Ljava_lang_String_2Z( | 678 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2Ljava_lang_String_2Z( |
| 681 | JNIEnv* env, jclass clazz, jstring j_file, jstring j_savestate, jboolean j_delete_savestate) {} | 679 | JNIEnv* env, jclass clazz, jstring j_file, jstring j_savestate, jboolean j_delete_savestate) {} |
| 682 | 680 | ||
| 683 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadSettings(JNIEnv* env, jclass clazz) { | ||
| 684 | Config{}; | ||
| 685 | } | ||
| 686 | |||
| 687 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_initGameIni(JNIEnv* env, jclass clazz, | ||
| 688 | jstring j_game_id) { | ||
| 689 | std::string_view game_id = env->GetStringUTFChars(j_game_id, 0); | ||
| 690 | |||
| 691 | env->ReleaseStringUTFChars(j_game_id, game_id.data()); | ||
| 692 | } | ||
| 693 | |||
| 694 | jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jclass clazz) { | 681 | jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jclass clazz) { |
| 695 | jdoubleArray j_stats = env->NewDoubleArray(4); | 682 | jdoubleArray j_stats = env->NewDoubleArray(4); |
| 696 | 683 | ||
diff --git a/src/android/app/src/main/jni/native_config.cpp b/src/android/app/src/main/jni/native_config.cpp index 8a704960c..8e81816e5 100644 --- a/src/android/app/src/main/jni/native_config.cpp +++ b/src/android/app/src/main/jni/native_config.cpp | |||
| @@ -5,11 +5,14 @@ | |||
| 5 | 5 | ||
| 6 | #include <jni.h> | 6 | #include <jni.h> |
| 7 | 7 | ||
| 8 | #include "android_config.h" | ||
| 9 | #include "android_settings.h" | ||
| 8 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 9 | #include "common/settings.h" | 11 | #include "common/settings.h" |
| 12 | #include "frontend_common/config.h" | ||
| 10 | #include "jni/android_common/android_common.h" | 13 | #include "jni/android_common/android_common.h" |
| 11 | #include "jni/config.h" | 14 | |
| 12 | #include "uisettings.h" | 15 | std::unique_ptr<AndroidConfig> config; |
| 13 | 16 | ||
| 14 | template <typename T> | 17 | template <typename T> |
| 15 | Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) { | 18 | Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) { |
| @@ -28,6 +31,22 @@ Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) { | |||
| 28 | 31 | ||
| 29 | extern "C" { | 32 | extern "C" { |
| 30 | 33 | ||
| 34 | void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_initializeConfig(JNIEnv* env, jobject obj) { | ||
| 35 | config = std::make_unique<AndroidConfig>(); | ||
| 36 | } | ||
| 37 | |||
| 38 | void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_unloadConfig(JNIEnv* env, jobject obj) { | ||
| 39 | config.reset(); | ||
| 40 | } | ||
| 41 | |||
| 42 | void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_reloadSettings(JNIEnv* env, jobject obj) { | ||
| 43 | config->AndroidConfig::ReloadAllValues(); | ||
| 44 | } | ||
| 45 | |||
| 46 | void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_saveSettings(JNIEnv* env, jobject obj) { | ||
| 47 | config->AndroidConfig::SaveAllValues(); | ||
| 48 | } | ||
| 49 | |||
| 31 | jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getBoolean(JNIEnv* env, jobject obj, | 50 | jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getBoolean(JNIEnv* env, jobject obj, |
| 32 | jstring jkey, jboolean getDefault) { | 51 | jstring jkey, jboolean getDefault) { |
| 33 | auto setting = getSetting<bool>(env, jkey); | 52 | auto setting = getSetting<bool>(env, jkey); |
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 51717be06..a10131eb2 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -206,9 +206,9 @@ const char* TranslateCategory(Category category) { | |||
| 206 | case Category::UiAudio: | 206 | case Category::UiAudio: |
| 207 | return "UiAudio"; | 207 | return "UiAudio"; |
| 208 | case Category::UiLayout: | 208 | case Category::UiLayout: |
| 209 | return "UiLayout"; | 209 | return "UILayout"; |
| 210 | case Category::UiGameList: | 210 | case Category::UiGameList: |
| 211 | return "UiGameList"; | 211 | return "UIGameList"; |
| 212 | case Category::Screenshots: | 212 | case Category::Screenshots: |
| 213 | return "Screenshots"; | 213 | return "Screenshots"; |
| 214 | case Category::Shortcuts: | 214 | case Category::Shortcuts: |
diff --git a/src/common/settings.h b/src/common/settings.h index e899f1ae6..e75099b89 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -232,7 +232,11 @@ struct Values { | |||
| 232 | SwitchableSetting<bool> use_asynchronous_gpu_emulation{ | 232 | SwitchableSetting<bool> use_asynchronous_gpu_emulation{ |
| 233 | linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer}; | 233 | linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer}; |
| 234 | SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage, | 234 | SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage, |
| 235 | #ifdef ANDROID | ||
| 236 | AstcDecodeMode::Cpu, | ||
| 237 | #else | ||
| 235 | AstcDecodeMode::Gpu, | 238 | AstcDecodeMode::Gpu, |
| 239 | #endif | ||
| 236 | AstcDecodeMode::Cpu, | 240 | AstcDecodeMode::Cpu, |
| 237 | AstcDecodeMode::CpuAsynchronous, | 241 | AstcDecodeMode::CpuAsynchronous, |
| 238 | "accelerate_astc", | 242 | "accelerate_astc", |
| @@ -304,7 +308,11 @@ struct Values { | |||
| 304 | linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true}; | 308 | linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true}; |
| 305 | 309 | ||
| 306 | SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage, | 310 | SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage, |
| 311 | #ifdef ANDROID | ||
| 312 | GpuAccuracy::Normal, | ||
| 313 | #else | ||
| 307 | GpuAccuracy::High, | 314 | GpuAccuracy::High, |
| 315 | #endif | ||
| 308 | GpuAccuracy::Normal, | 316 | GpuAccuracy::Normal, |
| 309 | GpuAccuracy::Extreme, | 317 | GpuAccuracy::Extreme, |
| 310 | "gpu_accuracy", | 318 | "gpu_accuracy", |
| @@ -313,20 +321,38 @@ struct Values { | |||
| 313 | true, | 321 | true, |
| 314 | true}; | 322 | true}; |
| 315 | GpuAccuracy current_gpu_accuracy{GpuAccuracy::High}; | 323 | GpuAccuracy current_gpu_accuracy{GpuAccuracy::High}; |
| 316 | SwitchableSetting<AnisotropyMode, true> max_anisotropy{ | 324 | SwitchableSetting<AnisotropyMode, true> max_anisotropy{linkage, |
| 317 | linkage, AnisotropyMode::Automatic, AnisotropyMode::Automatic, AnisotropyMode::X16, | 325 | #ifdef ANDROID |
| 318 | "max_anisotropy", Category::RendererAdvanced}; | 326 | AnisotropyMode::Default, |
| 327 | #else | ||
| 328 | AnisotropyMode::Automatic, | ||
| 329 | #endif | ||
| 330 | AnisotropyMode::Automatic, | ||
| 331 | AnisotropyMode::X16, | ||
| 332 | "max_anisotropy", | ||
| 333 | Category::RendererAdvanced}; | ||
| 319 | SwitchableSetting<AstcRecompression, true> astc_recompression{linkage, | 334 | SwitchableSetting<AstcRecompression, true> astc_recompression{linkage, |
| 320 | AstcRecompression::Uncompressed, | 335 | AstcRecompression::Uncompressed, |
| 321 | AstcRecompression::Uncompressed, | 336 | AstcRecompression::Uncompressed, |
| 322 | AstcRecompression::Bc3, | 337 | AstcRecompression::Bc3, |
| 323 | "astc_recompression", | 338 | "astc_recompression", |
| 324 | Category::RendererAdvanced}; | 339 | Category::RendererAdvanced}; |
| 325 | SwitchableSetting<bool> async_presentation{linkage, false, "async_presentation", | 340 | SwitchableSetting<bool> async_presentation{linkage, |
| 326 | Category::RendererAdvanced}; | 341 | #ifdef ANDROID |
| 342 | true, | ||
| 343 | #else | ||
| 344 | false, | ||
| 345 | #endif | ||
| 346 | "async_presentation", Category::RendererAdvanced}; | ||
| 327 | SwitchableSetting<bool> renderer_force_max_clock{linkage, false, "force_max_clock", | 347 | SwitchableSetting<bool> renderer_force_max_clock{linkage, false, "force_max_clock", |
| 328 | Category::RendererAdvanced}; | 348 | Category::RendererAdvanced}; |
| 329 | SwitchableSetting<bool> use_reactive_flushing{linkage, true, "use_reactive_flushing", | 349 | SwitchableSetting<bool> use_reactive_flushing{linkage, |
| 350 | #ifdef ANDROID | ||
| 351 | false, | ||
| 352 | #else | ||
| 353 | true, | ||
| 354 | #endif | ||
| 355 | "use_reactive_flushing", | ||
| 330 | Category::RendererAdvanced}; | 356 | Category::RendererAdvanced}; |
| 331 | SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders", | 357 | SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders", |
| 332 | Category::RendererAdvanced}; | 358 | Category::RendererAdvanced}; |
| @@ -390,7 +416,11 @@ struct Values { | |||
| 390 | Setting<s32> current_user{linkage, 0, "current_user", Category::System}; | 416 | Setting<s32> current_user{linkage, 0, "current_user", Category::System}; |
| 391 | 417 | ||
| 392 | SwitchableSetting<ConsoleMode> use_docked_mode{linkage, | 418 | SwitchableSetting<ConsoleMode> use_docked_mode{linkage, |
| 419 | #ifdef ANDROID | ||
| 420 | ConsoleMode::Handheld, | ||
| 421 | #else | ||
| 393 | ConsoleMode::Docked, | 422 | ConsoleMode::Docked, |
| 423 | #endif | ||
| 394 | "use_docked_mode", | 424 | "use_docked_mode", |
| 395 | Category::System, | 425 | Category::System, |
| 396 | Specialization::Radio, | 426 | Specialization::Radio, |
diff --git a/src/frontend_common/CMakeLists.txt b/src/frontend_common/CMakeLists.txt new file mode 100644 index 000000000..1537271fc --- /dev/null +++ b/src/frontend_common/CMakeLists.txt | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | # SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | # SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | add_library(frontend_common STATIC | ||
| 5 | config.cpp | ||
| 6 | config.h | ||
| 7 | ) | ||
| 8 | |||
| 9 | create_target_directory_groups(frontend_common) | ||
| 10 | target_link_libraries(frontend_common PUBLIC core SimpleIni PRIVATE common Boost::headers) | ||
diff --git a/src/frontend_common/config.cpp b/src/frontend_common/config.cpp new file mode 100644 index 000000000..7474cb0f9 --- /dev/null +++ b/src/frontend_common/config.cpp | |||
| @@ -0,0 +1,1008 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <array> | ||
| 6 | #include "common/fs/fs.h" | ||
| 7 | #include "common/fs/path_util.h" | ||
| 8 | #include "common/settings.h" | ||
| 9 | #include "common/settings_common.h" | ||
| 10 | #include "common/settings_enums.h" | ||
| 11 | #include "config.h" | ||
| 12 | #include "core/core.h" | ||
| 13 | #include "core/hle/service/acc/profile_manager.h" | ||
| 14 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 15 | #include "network/network.h" | ||
| 16 | |||
| 17 | #include <boost/algorithm/string/replace.hpp> | ||
| 18 | |||
| 19 | #include "common/string_util.h" | ||
| 20 | |||
| 21 | namespace FS = Common::FS; | ||
| 22 | |||
| 23 | Config::Config(const ConfigType config_type) | ||
| 24 | : type(config_type), global{config_type == ConfigType::GlobalConfig} {} | ||
| 25 | |||
| 26 | void Config::Initialize(const std::string& config_name) { | ||
| 27 | const std::filesystem::path fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir); | ||
| 28 | const auto config_file = fmt::format("{}.ini", config_name); | ||
| 29 | |||
| 30 | switch (type) { | ||
| 31 | case ConfigType::GlobalConfig: | ||
| 32 | config_loc = FS::PathToUTF8String(fs_config_loc / config_file); | ||
| 33 | void(FS::CreateParentDir(config_loc)); | ||
| 34 | SetUpIni(); | ||
| 35 | Reload(); | ||
| 36 | break; | ||
| 37 | case ConfigType::PerGameConfig: | ||
| 38 | config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file)); | ||
| 39 | void(FS::CreateParentDir(config_loc)); | ||
| 40 | SetUpIni(); | ||
| 41 | Reload(); | ||
| 42 | break; | ||
| 43 | case ConfigType::InputProfile: | ||
| 44 | config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file); | ||
| 45 | void(FS::CreateParentDir(config_loc)); | ||
| 46 | SetUpIni(); | ||
| 47 | break; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | void Config::Initialize(const std::optional<std::string> config_path) { | ||
| 52 | const std::filesystem::path default_sdl_config_path = | ||
| 53 | FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini"; | ||
| 54 | config_loc = config_path.value_or(FS::PathToUTF8String(default_sdl_config_path)); | ||
| 55 | void(FS::CreateParentDir(config_loc)); | ||
| 56 | SetUpIni(); | ||
| 57 | Reload(); | ||
| 58 | } | ||
| 59 | |||
| 60 | void Config::WriteToIni() const { | ||
| 61 | FILE* fp = nullptr; | ||
| 62 | #ifdef _WIN32 | ||
| 63 | fp = _wfopen(Common::UTF8ToUTF16W(config_loc).data(), L"wb"); | ||
| 64 | #else | ||
| 65 | fp = fopen(config_loc.c_str(), "wb"); | ||
| 66 | #endif | ||
| 67 | |||
| 68 | if (fp == nullptr) { | ||
| 69 | LOG_ERROR(Frontend, "Config file could not be saved!"); | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | |||
| 73 | CSimpleIniA::FileWriter writer(fp); | ||
| 74 | const SI_Error rc = config->Save(writer, false); | ||
| 75 | if (rc < 0) { | ||
| 76 | LOG_ERROR(Frontend, "Config file could not be saved!"); | ||
| 77 | } | ||
| 78 | fclose(fp); | ||
| 79 | } | ||
| 80 | |||
| 81 | void Config::SetUpIni() { | ||
| 82 | config = std::make_unique<CSimpleIniA>(); | ||
| 83 | config->SetUnicode(true); | ||
| 84 | config->SetSpaces(false); | ||
| 85 | |||
| 86 | FILE* fp = nullptr; | ||
| 87 | #ifdef _WIN32 | ||
| 88 | _wfopen_s(&fp, Common::UTF8ToUTF16W(config_loc).data(), L"rb, ccs=UTF-8"); | ||
| 89 | if (fp == nullptr) { | ||
| 90 | fp = _wfopen(Common::UTF8ToUTF16W(config_loc).data(), L"wb, ccs=UTF-8"); | ||
| 91 | } | ||
| 92 | #else | ||
| 93 | fp = fopen(config_loc.c_str(), "rb"); | ||
| 94 | if (fp == nullptr) { | ||
| 95 | fp = fopen(config_loc.c_str(), "wb"); | ||
| 96 | } | ||
| 97 | #endif | ||
| 98 | |||
| 99 | if (fp == nullptr) { | ||
| 100 | LOG_ERROR(Frontend, "Config file could not be loaded!"); | ||
| 101 | return; | ||
| 102 | } | ||
| 103 | |||
| 104 | if (SI_Error rc = config->LoadFile(fp); rc < 0) { | ||
| 105 | LOG_ERROR(Frontend, "Config file could not be loaded!"); | ||
| 106 | } | ||
| 107 | fclose(fp); | ||
| 108 | } | ||
| 109 | |||
| 110 | bool Config::IsCustomConfig() const { | ||
| 111 | return type == ConfigType::PerGameConfig; | ||
| 112 | } | ||
| 113 | |||
| 114 | void Config::ReadPlayerValues(const std::size_t player_index) { | ||
| 115 | std::string player_prefix; | ||
| 116 | if (type != ConfigType::InputProfile) { | ||
| 117 | player_prefix.append("player_").append(ToString(player_index)).append("_"); | ||
| 118 | } | ||
| 119 | |||
| 120 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 121 | if (IsCustomConfig()) { | ||
| 122 | const auto profile_name = | ||
| 123 | ReadStringSetting(std::string(player_prefix).append("profile_name")); | ||
| 124 | if (profile_name.empty()) { | ||
| 125 | // Use the global input config | ||
| 126 | player = Settings::values.players.GetValue(true)[player_index]; | ||
| 127 | return; | ||
| 128 | } | ||
| 129 | player.profile_name = profile_name; | ||
| 130 | } | ||
| 131 | |||
| 132 | if (player_prefix.empty() && Settings::IsConfiguringGlobal()) { | ||
| 133 | const auto controller = static_cast<Settings::ControllerType>( | ||
| 134 | ReadIntegerSetting(std::string(player_prefix).append("type"), | ||
| 135 | static_cast<u8>(Settings::ControllerType::ProController))); | ||
| 136 | |||
| 137 | if (controller == Settings::ControllerType::LeftJoycon || | ||
| 138 | controller == Settings::ControllerType::RightJoycon) { | ||
| 139 | player.controller_type = controller; | ||
| 140 | } | ||
| 141 | } else { | ||
| 142 | std::string connected_key = player_prefix; | ||
| 143 | player.connected = ReadBooleanSetting(connected_key.append("connected"), | ||
| 144 | std::make_optional(player_index == 0)); | ||
| 145 | |||
| 146 | player.controller_type = static_cast<Settings::ControllerType>( | ||
| 147 | ReadIntegerSetting(std::string(player_prefix).append("type"), | ||
| 148 | static_cast<u8>(Settings::ControllerType::ProController))); | ||
| 149 | |||
| 150 | player.vibration_enabled = ReadBooleanSetting( | ||
| 151 | std::string(player_prefix).append("vibration_enabled"), std::make_optional(true)); | ||
| 152 | |||
| 153 | player.vibration_strength = static_cast<int>( | ||
| 154 | ReadIntegerSetting(std::string(player_prefix).append("vibration_strength"), 100)); | ||
| 155 | |||
| 156 | player.body_color_left = static_cast<u32>(ReadIntegerSetting( | ||
| 157 | std::string(player_prefix).append("body_color_left"), Settings::JOYCON_BODY_NEON_BLUE)); | ||
| 158 | player.body_color_right = static_cast<u32>(ReadIntegerSetting( | ||
| 159 | std::string(player_prefix).append("body_color_right"), Settings::JOYCON_BODY_NEON_RED)); | ||
| 160 | player.button_color_left = static_cast<u32>( | ||
| 161 | ReadIntegerSetting(std::string(player_prefix).append("button_color_left"), | ||
| 162 | Settings::JOYCON_BUTTONS_NEON_BLUE)); | ||
| 163 | player.button_color_right = static_cast<u32>( | ||
| 164 | ReadIntegerSetting(std::string(player_prefix).append("button_color_right"), | ||
| 165 | Settings::JOYCON_BUTTONS_NEON_RED)); | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | void Config::ReadTouchscreenValues() { | ||
| 170 | Settings::values.touchscreen.enabled = | ||
| 171 | ReadBooleanSetting(std::string("touchscreen_enabled"), std::make_optional(true)); | ||
| 172 | Settings::values.touchscreen.rotation_angle = | ||
| 173 | static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_angle"), 0)); | ||
| 174 | Settings::values.touchscreen.diameter_x = | ||
| 175 | static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_x"), 15)); | ||
| 176 | Settings::values.touchscreen.diameter_y = | ||
| 177 | static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_y"), 15)); | ||
| 178 | } | ||
| 179 | |||
| 180 | void Config::ReadAudioValues() { | ||
| 181 | BeginGroup(Settings::TranslateCategory(Settings::Category::Audio)); | ||
| 182 | |||
| 183 | ReadCategory(Settings::Category::Audio); | ||
| 184 | ReadCategory(Settings::Category::UiAudio); | ||
| 185 | |||
| 186 | EndGroup(); | ||
| 187 | } | ||
| 188 | |||
| 189 | void Config::ReadControlValues() { | ||
| 190 | BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); | ||
| 191 | |||
| 192 | ReadCategory(Settings::Category::Controls); | ||
| 193 | |||
| 194 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 195 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | ||
| 196 | ReadPlayerValues(p); | ||
| 197 | } | ||
| 198 | |||
| 199 | // Disable docked mode if handheld is selected | ||
| 200 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; | ||
| 201 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 202 | Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig()); | ||
| 203 | Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld); | ||
| 204 | } | ||
| 205 | |||
| 206 | if (IsCustomConfig()) { | ||
| 207 | EndGroup(); | ||
| 208 | return; | ||
| 209 | } | ||
| 210 | ReadTouchscreenValues(); | ||
| 211 | ReadMotionTouchValues(); | ||
| 212 | |||
| 213 | EndGroup(); | ||
| 214 | } | ||
| 215 | |||
| 216 | void Config::ReadMotionTouchValues() { | ||
| 217 | int num_touch_from_button_maps = BeginArray(std::string("touch_from_button_maps")); | ||
| 218 | |||
| 219 | if (num_touch_from_button_maps > 0) { | ||
| 220 | for (int i = 0; i < num_touch_from_button_maps; ++i) { | ||
| 221 | SetArrayIndex(i); | ||
| 222 | |||
| 223 | Settings::TouchFromButtonMap map; | ||
| 224 | map.name = ReadStringSetting(std::string("name"), std::string("default")); | ||
| 225 | |||
| 226 | const int num_touch_maps = BeginArray(std::string("entries")); | ||
| 227 | map.buttons.reserve(num_touch_maps); | ||
| 228 | for (int j = 0; j < num_touch_maps; j++) { | ||
| 229 | SetArrayIndex(j); | ||
| 230 | std::string touch_mapping = ReadStringSetting(std::string("bind")); | ||
| 231 | map.buttons.emplace_back(std::move(touch_mapping)); | ||
| 232 | } | ||
| 233 | EndArray(); // entries | ||
| 234 | Settings::values.touch_from_button_maps.emplace_back(std::move(map)); | ||
| 235 | } | ||
| 236 | } else { | ||
| 237 | Settings::values.touch_from_button_maps.emplace_back( | ||
| 238 | Settings::TouchFromButtonMap{"default", {}}); | ||
| 239 | num_touch_from_button_maps = 1; | ||
| 240 | } | ||
| 241 | EndArray(); // touch_from_button_maps | ||
| 242 | |||
| 243 | Settings::values.touch_from_button_map_index = std::clamp( | ||
| 244 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); | ||
| 245 | } | ||
| 246 | |||
| 247 | void Config::ReadCoreValues() { | ||
| 248 | BeginGroup(Settings::TranslateCategory(Settings::Category::Core)); | ||
| 249 | |||
| 250 | ReadCategory(Settings::Category::Core); | ||
| 251 | |||
| 252 | EndGroup(); | ||
| 253 | } | ||
| 254 | |||
| 255 | void Config::ReadDataStorageValues() { | ||
| 256 | BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage)); | ||
| 257 | |||
| 258 | FS::SetYuzuPath(FS::YuzuPath::NANDDir, ReadStringSetting(std::string("nand_directory"))); | ||
| 259 | FS::SetYuzuPath(FS::YuzuPath::SDMCDir, ReadStringSetting(std::string("sdmc_directory"))); | ||
| 260 | FS::SetYuzuPath(FS::YuzuPath::LoadDir, ReadStringSetting(std::string("load_directory"))); | ||
| 261 | FS::SetYuzuPath(FS::YuzuPath::DumpDir, ReadStringSetting(std::string("dump_directory"))); | ||
| 262 | FS::SetYuzuPath(FS::YuzuPath::TASDir, ReadStringSetting(std::string("tas_directory"))); | ||
| 263 | |||
| 264 | ReadCategory(Settings::Category::DataStorage); | ||
| 265 | |||
| 266 | EndGroup(); | ||
| 267 | } | ||
| 268 | |||
| 269 | void Config::ReadDebuggingValues() { | ||
| 270 | BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging)); | ||
| 271 | |||
| 272 | // Intentionally not using the QT default setting as this is intended to be changed in the ini | ||
| 273 | Settings::values.record_frame_times = | ||
| 274 | ReadBooleanSetting(std::string("record_frame_times"), std::make_optional(false)); | ||
| 275 | |||
| 276 | ReadCategory(Settings::Category::Debugging); | ||
| 277 | ReadCategory(Settings::Category::DebuggingGraphics); | ||
| 278 | |||
| 279 | EndGroup(); | ||
| 280 | } | ||
| 281 | |||
| 282 | void Config::ReadServiceValues() { | ||
| 283 | BeginGroup(Settings::TranslateCategory(Settings::Category::Services)); | ||
| 284 | |||
| 285 | ReadCategory(Settings::Category::Services); | ||
| 286 | |||
| 287 | EndGroup(); | ||
| 288 | } | ||
| 289 | |||
| 290 | void Config::ReadDisabledAddOnValues() { | ||
| 291 | // Custom config section | ||
| 292 | BeginGroup(std::string("DisabledAddOns")); | ||
| 293 | |||
| 294 | const int size = BeginArray(std::string("")); | ||
| 295 | for (int i = 0; i < size; ++i) { | ||
| 296 | SetArrayIndex(i); | ||
| 297 | const auto title_id = ReadUnsignedIntegerSetting(std::string("title_id"), 0); | ||
| 298 | std::vector<std::string> out; | ||
| 299 | const int d_size = BeginArray("disabled"); | ||
| 300 | for (int j = 0; j < d_size; ++j) { | ||
| 301 | SetArrayIndex(j); | ||
| 302 | out.push_back(ReadStringSetting(std::string("d"), std::string(""))); | ||
| 303 | } | ||
| 304 | EndArray(); // d | ||
| 305 | Settings::values.disabled_addons.insert_or_assign(title_id, out); | ||
| 306 | } | ||
| 307 | EndArray(); // Base disabled addons array - Has no base key | ||
| 308 | |||
| 309 | EndGroup(); | ||
| 310 | } | ||
| 311 | |||
| 312 | void Config::ReadMiscellaneousValues() { | ||
| 313 | BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous)); | ||
| 314 | |||
| 315 | ReadCategory(Settings::Category::Miscellaneous); | ||
| 316 | |||
| 317 | EndGroup(); | ||
| 318 | } | ||
| 319 | |||
| 320 | void Config::ReadCpuValues() { | ||
| 321 | BeginGroup(Settings::TranslateCategory(Settings::Category::Cpu)); | ||
| 322 | |||
| 323 | ReadCategory(Settings::Category::Cpu); | ||
| 324 | ReadCategory(Settings::Category::CpuDebug); | ||
| 325 | ReadCategory(Settings::Category::CpuUnsafe); | ||
| 326 | |||
| 327 | EndGroup(); | ||
| 328 | } | ||
| 329 | |||
| 330 | void Config::ReadRendererValues() { | ||
| 331 | BeginGroup(Settings::TranslateCategory(Settings::Category::Renderer)); | ||
| 332 | |||
| 333 | ReadCategory(Settings::Category::Renderer); | ||
| 334 | ReadCategory(Settings::Category::RendererAdvanced); | ||
| 335 | ReadCategory(Settings::Category::RendererDebug); | ||
| 336 | |||
| 337 | EndGroup(); | ||
| 338 | } | ||
| 339 | |||
| 340 | void Config::ReadScreenshotValues() { | ||
| 341 | BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots)); | ||
| 342 | |||
| 343 | ReadCategory(Settings::Category::Screenshots); | ||
| 344 | FS::SetYuzuPath(FS::YuzuPath::ScreenshotsDir, | ||
| 345 | ReadStringSetting(std::string("screenshot_path"))); | ||
| 346 | |||
| 347 | EndGroup(); | ||
| 348 | } | ||
| 349 | |||
| 350 | void Config::ReadSystemValues() { | ||
| 351 | BeginGroup(Settings::TranslateCategory(Settings::Category::System)); | ||
| 352 | |||
| 353 | ReadCategory(Settings::Category::System); | ||
| 354 | ReadCategory(Settings::Category::SystemAudio); | ||
| 355 | |||
| 356 | EndGroup(); | ||
| 357 | } | ||
| 358 | |||
| 359 | void Config::ReadWebServiceValues() { | ||
| 360 | BeginGroup(Settings::TranslateCategory(Settings::Category::WebService)); | ||
| 361 | |||
| 362 | ReadCategory(Settings::Category::WebService); | ||
| 363 | |||
| 364 | EndGroup(); | ||
| 365 | } | ||
| 366 | |||
| 367 | void Config::ReadNetworkValues() { | ||
| 368 | BeginGroup(Settings::TranslateCategory(Settings::Category::Services)); | ||
| 369 | |||
| 370 | ReadCategory(Settings::Category::Network); | ||
| 371 | |||
| 372 | EndGroup(); | ||
| 373 | } | ||
| 374 | |||
| 375 | void Config::ReadValues() { | ||
| 376 | if (global) { | ||
| 377 | ReadDataStorageValues(); | ||
| 378 | ReadDebuggingValues(); | ||
| 379 | ReadDisabledAddOnValues(); | ||
| 380 | ReadNetworkValues(); | ||
| 381 | ReadServiceValues(); | ||
| 382 | ReadWebServiceValues(); | ||
| 383 | ReadMiscellaneousValues(); | ||
| 384 | } | ||
| 385 | ReadControlValues(); | ||
| 386 | ReadCoreValues(); | ||
| 387 | ReadCpuValues(); | ||
| 388 | ReadRendererValues(); | ||
| 389 | ReadAudioValues(); | ||
| 390 | ReadSystemValues(); | ||
| 391 | } | ||
| 392 | |||
| 393 | void Config::SavePlayerValues(const std::size_t player_index) { | ||
| 394 | std::string player_prefix; | ||
| 395 | if (type != ConfigType::InputProfile) { | ||
| 396 | player_prefix = std::string("player_").append(ToString(player_index)).append("_"); | ||
| 397 | } | ||
| 398 | |||
| 399 | const auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 400 | if (IsCustomConfig()) { | ||
| 401 | if (player.profile_name.empty()) { | ||
| 402 | // No custom profile selected | ||
| 403 | return; | ||
| 404 | } | ||
| 405 | WriteSetting(std::string(player_prefix).append("profile_name"), player.profile_name, | ||
| 406 | std::make_optional(std::string(""))); | ||
| 407 | } | ||
| 408 | |||
| 409 | WriteSetting(std::string(player_prefix).append("type"), static_cast<u8>(player.controller_type), | ||
| 410 | std::make_optional(static_cast<u8>(Settings::ControllerType::ProController))); | ||
| 411 | |||
| 412 | if (!player_prefix.empty() || !Settings::IsConfiguringGlobal()) { | ||
| 413 | WriteSetting(std::string(player_prefix).append("connected"), player.connected, | ||
| 414 | std::make_optional(player_index == 0)); | ||
| 415 | WriteSetting(std::string(player_prefix).append("vibration_enabled"), | ||
| 416 | player.vibration_enabled, std::make_optional(true)); | ||
| 417 | WriteSetting(std::string(player_prefix).append("vibration_strength"), | ||
| 418 | player.vibration_strength, std::make_optional(100)); | ||
| 419 | WriteSetting(std::string(player_prefix).append("body_color_left"), player.body_color_left, | ||
| 420 | std::make_optional(Settings::JOYCON_BODY_NEON_BLUE)); | ||
| 421 | WriteSetting(std::string(player_prefix).append("body_color_right"), player.body_color_right, | ||
| 422 | std::make_optional(Settings::JOYCON_BODY_NEON_RED)); | ||
| 423 | WriteSetting(std::string(player_prefix).append("button_color_left"), | ||
| 424 | player.button_color_left, | ||
| 425 | std::make_optional(Settings::JOYCON_BUTTONS_NEON_BLUE)); | ||
| 426 | WriteSetting(std::string(player_prefix).append("button_color_right"), | ||
| 427 | player.button_color_right, | ||
| 428 | std::make_optional(Settings::JOYCON_BUTTONS_NEON_RED)); | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 432 | void Config::SaveTouchscreenValues() { | ||
| 433 | const auto& touchscreen = Settings::values.touchscreen; | ||
| 434 | |||
| 435 | WriteSetting(std::string("touchscreen_enabled"), touchscreen.enabled, std::make_optional(true)); | ||
| 436 | |||
| 437 | WriteSetting(std::string("touchscreen_angle"), touchscreen.rotation_angle, | ||
| 438 | std::make_optional(static_cast<u32>(0))); | ||
| 439 | WriteSetting(std::string("touchscreen_diameter_x"), touchscreen.diameter_x, | ||
| 440 | std::make_optional(static_cast<u32>(15))); | ||
| 441 | WriteSetting(std::string("touchscreen_diameter_y"), touchscreen.diameter_y, | ||
| 442 | std::make_optional(static_cast<u32>(15))); | ||
| 443 | } | ||
| 444 | |||
| 445 | void Config::SaveMotionTouchValues() { | ||
| 446 | BeginArray(std::string("touch_from_button_maps")); | ||
| 447 | for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { | ||
| 448 | SetArrayIndex(static_cast<int>(p)); | ||
| 449 | WriteSetting(std::string("name"), Settings::values.touch_from_button_maps[p].name, | ||
| 450 | std::make_optional(std::string("default"))); | ||
| 451 | |||
| 452 | BeginArray(std::string("entries")); | ||
| 453 | for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size(); | ||
| 454 | ++q) { | ||
| 455 | SetArrayIndex(static_cast<int>(q)); | ||
| 456 | WriteSetting(std::string("bind"), | ||
| 457 | Settings::values.touch_from_button_maps[p].buttons[q]); | ||
| 458 | } | ||
| 459 | EndArray(); // entries | ||
| 460 | } | ||
| 461 | EndArray(); // touch_from_button_maps | ||
| 462 | } | ||
| 463 | |||
| 464 | void Config::SaveValues() { | ||
| 465 | if (global) { | ||
| 466 | SaveDataStorageValues(); | ||
| 467 | SaveDebuggingValues(); | ||
| 468 | SaveDisabledAddOnValues(); | ||
| 469 | SaveNetworkValues(); | ||
| 470 | SaveWebServiceValues(); | ||
| 471 | SaveMiscellaneousValues(); | ||
| 472 | } | ||
| 473 | SaveControlValues(); | ||
| 474 | SaveCoreValues(); | ||
| 475 | SaveCpuValues(); | ||
| 476 | SaveRendererValues(); | ||
| 477 | SaveAudioValues(); | ||
| 478 | SaveSystemValues(); | ||
| 479 | |||
| 480 | WriteToIni(); | ||
| 481 | } | ||
| 482 | |||
| 483 | void Config::SaveAudioValues() { | ||
| 484 | BeginGroup(Settings::TranslateCategory(Settings::Category::Audio)); | ||
| 485 | |||
| 486 | WriteCategory(Settings::Category::Audio); | ||
| 487 | WriteCategory(Settings::Category::UiAudio); | ||
| 488 | |||
| 489 | EndGroup(); | ||
| 490 | } | ||
| 491 | |||
| 492 | void Config::SaveControlValues() { | ||
| 493 | BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); | ||
| 494 | |||
| 495 | WriteCategory(Settings::Category::Controls); | ||
| 496 | |||
| 497 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 498 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | ||
| 499 | SavePlayerValues(p); | ||
| 500 | } | ||
| 501 | if (IsCustomConfig()) { | ||
| 502 | EndGroup(); | ||
| 503 | return; | ||
| 504 | } | ||
| 505 | SaveTouchscreenValues(); | ||
| 506 | SaveMotionTouchValues(); | ||
| 507 | |||
| 508 | EndGroup(); | ||
| 509 | } | ||
| 510 | |||
| 511 | void Config::SaveCoreValues() { | ||
| 512 | BeginGroup(Settings::TranslateCategory(Settings::Category::Core)); | ||
| 513 | |||
| 514 | WriteCategory(Settings::Category::Core); | ||
| 515 | |||
| 516 | EndGroup(); | ||
| 517 | } | ||
| 518 | |||
| 519 | void Config::SaveDataStorageValues() { | ||
| 520 | BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage)); | ||
| 521 | |||
| 522 | WriteSetting(std::string("nand_directory"), FS::GetYuzuPathString(FS::YuzuPath::NANDDir), | ||
| 523 | std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); | ||
| 524 | WriteSetting(std::string("sdmc_directory"), FS::GetYuzuPathString(FS::YuzuPath::SDMCDir), | ||
| 525 | std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir))); | ||
| 526 | WriteSetting(std::string("load_directory"), FS::GetYuzuPathString(FS::YuzuPath::LoadDir), | ||
| 527 | std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::LoadDir))); | ||
| 528 | WriteSetting(std::string("dump_directory"), FS::GetYuzuPathString(FS::YuzuPath::DumpDir), | ||
| 529 | std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); | ||
| 530 | WriteSetting(std::string("tas_directory"), FS::GetYuzuPathString(FS::YuzuPath::TASDir), | ||
| 531 | std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::TASDir))); | ||
| 532 | |||
| 533 | WriteCategory(Settings::Category::DataStorage); | ||
| 534 | |||
| 535 | EndGroup(); | ||
| 536 | } | ||
| 537 | |||
| 538 | void Config::SaveDebuggingValues() { | ||
| 539 | BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging)); | ||
| 540 | |||
| 541 | // Intentionally not using the QT default setting as this is intended to be changed in the ini | ||
| 542 | WriteSetting(std::string("record_frame_times"), Settings::values.record_frame_times); | ||
| 543 | |||
| 544 | WriteCategory(Settings::Category::Debugging); | ||
| 545 | WriteCategory(Settings::Category::DebuggingGraphics); | ||
| 546 | |||
| 547 | EndGroup(); | ||
| 548 | } | ||
| 549 | |||
| 550 | void Config::SaveNetworkValues() { | ||
| 551 | BeginGroup(Settings::TranslateCategory(Settings::Category::Services)); | ||
| 552 | |||
| 553 | WriteCategory(Settings::Category::Network); | ||
| 554 | |||
| 555 | EndGroup(); | ||
| 556 | } | ||
| 557 | |||
| 558 | void Config::SaveDisabledAddOnValues() { | ||
| 559 | // Custom config section | ||
| 560 | BeginGroup(std::string("DisabledAddOns")); | ||
| 561 | |||
| 562 | int i = 0; | ||
| 563 | BeginArray(std::string("")); | ||
| 564 | for (const auto& elem : Settings::values.disabled_addons) { | ||
| 565 | SetArrayIndex(i); | ||
| 566 | WriteSetting(std::string("title_id"), elem.first, std::make_optional(static_cast<u64>(0))); | ||
| 567 | BeginArray(std::string("disabled")); | ||
| 568 | for (std::size_t j = 0; j < elem.second.size(); ++j) { | ||
| 569 | SetArrayIndex(static_cast<int>(j)); | ||
| 570 | WriteSetting(std::string("d"), elem.second[j], std::make_optional(std::string(""))); | ||
| 571 | } | ||
| 572 | EndArray(); // disabled | ||
| 573 | ++i; | ||
| 574 | } | ||
| 575 | EndArray(); // Base disabled addons array - Has no base key | ||
| 576 | |||
| 577 | EndGroup(); | ||
| 578 | } | ||
| 579 | |||
| 580 | void Config::SaveMiscellaneousValues() { | ||
| 581 | BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous)); | ||
| 582 | |||
| 583 | WriteCategory(Settings::Category::Miscellaneous); | ||
| 584 | |||
| 585 | EndGroup(); | ||
| 586 | } | ||
| 587 | |||
| 588 | void Config::SaveCpuValues() { | ||
| 589 | BeginGroup(Settings::TranslateCategory(Settings::Category::Cpu)); | ||
| 590 | |||
| 591 | WriteCategory(Settings::Category::Cpu); | ||
| 592 | WriteCategory(Settings::Category::CpuDebug); | ||
| 593 | WriteCategory(Settings::Category::CpuUnsafe); | ||
| 594 | |||
| 595 | EndGroup(); | ||
| 596 | } | ||
| 597 | |||
| 598 | void Config::SaveRendererValues() { | ||
| 599 | BeginGroup(Settings::TranslateCategory(Settings::Category::Renderer)); | ||
| 600 | |||
| 601 | WriteCategory(Settings::Category::Renderer); | ||
| 602 | WriteCategory(Settings::Category::RendererAdvanced); | ||
| 603 | WriteCategory(Settings::Category::RendererDebug); | ||
| 604 | |||
| 605 | EndGroup(); | ||
| 606 | } | ||
| 607 | |||
| 608 | void Config::SaveScreenshotValues() { | ||
| 609 | BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots)); | ||
| 610 | |||
| 611 | WriteSetting(std::string("screenshot_path"), | ||
| 612 | FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir)); | ||
| 613 | WriteCategory(Settings::Category::Screenshots); | ||
| 614 | |||
| 615 | EndGroup(); | ||
| 616 | } | ||
| 617 | |||
| 618 | void Config::SaveSystemValues() { | ||
| 619 | BeginGroup(Settings::TranslateCategory(Settings::Category::System)); | ||
| 620 | |||
| 621 | WriteCategory(Settings::Category::System); | ||
| 622 | WriteCategory(Settings::Category::SystemAudio); | ||
| 623 | |||
| 624 | EndGroup(); | ||
| 625 | } | ||
| 626 | |||
| 627 | void Config::SaveWebServiceValues() { | ||
| 628 | BeginGroup(Settings::TranslateCategory(Settings::Category::WebService)); | ||
| 629 | |||
| 630 | WriteCategory(Settings::Category::WebService); | ||
| 631 | |||
| 632 | EndGroup(); | ||
| 633 | } | ||
| 634 | |||
| 635 | bool Config::ReadBooleanSetting(const std::string& key, const std::optional<bool> default_value) { | ||
| 636 | std::string full_key = GetFullKey(key, false); | ||
| 637 | if (!default_value.has_value()) { | ||
| 638 | return config->GetBoolValue(GetSection().c_str(), full_key.c_str(), false); | ||
| 639 | } | ||
| 640 | |||
| 641 | if (config->GetBoolValue(GetSection().c_str(), | ||
| 642 | std::string(full_key).append("\\default").c_str(), false)) { | ||
| 643 | return static_cast<bool>(default_value.value()); | ||
| 644 | } else { | ||
| 645 | return config->GetBoolValue(GetSection().c_str(), full_key.c_str(), | ||
| 646 | static_cast<bool>(default_value.value())); | ||
| 647 | } | ||
| 648 | } | ||
| 649 | |||
| 650 | s64 Config::ReadIntegerSetting(const std::string& key, const std::optional<s64> default_value) { | ||
| 651 | std::string full_key = GetFullKey(key, false); | ||
| 652 | if (!default_value.has_value()) { | ||
| 653 | try { | ||
| 654 | return std::stoll( | ||
| 655 | std::string(config->GetValue(GetSection().c_str(), full_key.c_str(), "0"))); | ||
| 656 | } catch (...) { | ||
| 657 | return 0; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | |||
| 661 | s64 result = 0; | ||
| 662 | if (config->GetBoolValue(GetSection().c_str(), | ||
| 663 | std::string(full_key).append("\\default").c_str(), true)) { | ||
| 664 | result = default_value.value(); | ||
| 665 | } else { | ||
| 666 | try { | ||
| 667 | result = std::stoll(std::string(config->GetValue( | ||
| 668 | GetSection().c_str(), full_key.c_str(), ToString(default_value.value()).c_str()))); | ||
| 669 | } catch (...) { | ||
| 670 | result = default_value.value(); | ||
| 671 | } | ||
| 672 | } | ||
| 673 | return result; | ||
| 674 | } | ||
| 675 | |||
| 676 | u64 Config::ReadUnsignedIntegerSetting(const std::string& key, | ||
| 677 | const std::optional<u64> default_value) { | ||
| 678 | std::string full_key = GetFullKey(key, false); | ||
| 679 | if (!default_value.has_value()) { | ||
| 680 | try { | ||
| 681 | return std::stoull( | ||
| 682 | std::string(config->GetValue(GetSection().c_str(), full_key.c_str(), "0"))); | ||
| 683 | } catch (...) { | ||
| 684 | return 0; | ||
| 685 | } | ||
| 686 | } | ||
| 687 | |||
| 688 | u64 result = 0; | ||
| 689 | if (config->GetBoolValue(GetSection().c_str(), | ||
| 690 | std::string(full_key).append("\\default").c_str(), true)) { | ||
| 691 | result = default_value.value(); | ||
| 692 | } else { | ||
| 693 | try { | ||
| 694 | result = std::stoull(std::string(config->GetValue( | ||
| 695 | GetSection().c_str(), full_key.c_str(), ToString(default_value.value()).c_str()))); | ||
| 696 | } catch (...) { | ||
| 697 | result = default_value.value(); | ||
| 698 | } | ||
| 699 | } | ||
| 700 | return result; | ||
| 701 | } | ||
| 702 | |||
| 703 | double Config::ReadDoubleSetting(const std::string& key, | ||
| 704 | const std::optional<double> default_value) { | ||
| 705 | std::string full_key = GetFullKey(key, false); | ||
| 706 | if (!default_value.has_value()) { | ||
| 707 | return config->GetDoubleValue(GetSection().c_str(), full_key.c_str(), 0); | ||
| 708 | } | ||
| 709 | |||
| 710 | double result; | ||
| 711 | if (config->GetBoolValue(GetSection().c_str(), | ||
| 712 | std::string(full_key).append("\\default").c_str(), true)) { | ||
| 713 | result = default_value.value(); | ||
| 714 | } else { | ||
| 715 | result = | ||
| 716 | config->GetDoubleValue(GetSection().c_str(), full_key.c_str(), default_value.value()); | ||
| 717 | } | ||
| 718 | return result; | ||
| 719 | } | ||
| 720 | |||
| 721 | std::string Config::ReadStringSetting(const std::string& key, | ||
| 722 | const std::optional<std::string> default_value) { | ||
| 723 | std::string result; | ||
| 724 | std::string full_key = GetFullKey(key, false); | ||
| 725 | if (!default_value.has_value()) { | ||
| 726 | result = config->GetValue(GetSection().c_str(), full_key.c_str(), ""); | ||
| 727 | boost::replace_all(result, "\"", ""); | ||
| 728 | return result; | ||
| 729 | } | ||
| 730 | |||
| 731 | if (config->GetBoolValue(GetSection().c_str(), | ||
| 732 | std::string(full_key).append("\\default").c_str(), true)) { | ||
| 733 | result = default_value.value(); | ||
| 734 | } else { | ||
| 735 | result = | ||
| 736 | config->GetValue(GetSection().c_str(), full_key.c_str(), default_value.value().c_str()); | ||
| 737 | } | ||
| 738 | boost::replace_all(result, "\"", ""); | ||
| 739 | boost::replace_all(result, "//", "/"); | ||
| 740 | return result; | ||
| 741 | } | ||
| 742 | |||
| 743 | bool Config::Exists(const std::string& section, const std::string& key) const { | ||
| 744 | const std::string value = config->GetValue(section.c_str(), key.c_str(), ""); | ||
| 745 | return !value.empty(); | ||
| 746 | } | ||
| 747 | |||
| 748 | template <typename Type> | ||
| 749 | void Config::WriteSetting(const std::string& key, const Type& value, | ||
| 750 | const std::optional<Type>& default_value, | ||
| 751 | const std::optional<bool>& use_global) { | ||
| 752 | std::string full_key = GetFullKey(key, false); | ||
| 753 | |||
| 754 | std::string saved_value; | ||
| 755 | std::string string_default; | ||
| 756 | if constexpr (std::is_same_v<Type, std::string>) { | ||
| 757 | saved_value.append(AdjustOutputString(value)); | ||
| 758 | if (default_value.has_value()) { | ||
| 759 | string_default.append(AdjustOutputString(default_value.value())); | ||
| 760 | } | ||
| 761 | } else { | ||
| 762 | saved_value.append(AdjustOutputString(ToString(value))); | ||
| 763 | if (default_value.has_value()) { | ||
| 764 | string_default.append(ToString(default_value.value())); | ||
| 765 | } | ||
| 766 | } | ||
| 767 | |||
| 768 | if (default_value.has_value() && use_global.has_value()) { | ||
| 769 | if (!global) { | ||
| 770 | WriteSettingInternal(std::string(full_key).append("\\global"), | ||
| 771 | ToString(use_global.value())); | ||
| 772 | } | ||
| 773 | if (global || use_global.value() == false) { | ||
| 774 | WriteSettingInternal(std::string(full_key).append("\\default"), | ||
| 775 | ToString(string_default == saved_value)); | ||
| 776 | WriteSettingInternal(full_key, saved_value); | ||
| 777 | } | ||
| 778 | } else if (default_value.has_value() && !use_global.has_value()) { | ||
| 779 | WriteSettingInternal(std::string(full_key).append("\\default"), | ||
| 780 | ToString(string_default == saved_value)); | ||
| 781 | WriteSettingInternal(full_key, saved_value); | ||
| 782 | } else { | ||
| 783 | WriteSettingInternal(full_key, saved_value); | ||
| 784 | } | ||
| 785 | } | ||
| 786 | |||
| 787 | void Config::WriteSettingInternal(const std::string& key, const std::string& value) { | ||
| 788 | config->SetValue(GetSection().c_str(), key.c_str(), value.c_str()); | ||
| 789 | } | ||
| 790 | |||
| 791 | void Config::Reload() { | ||
| 792 | ReadValues(); | ||
| 793 | // To apply default value changes | ||
| 794 | SaveValues(); | ||
| 795 | } | ||
| 796 | |||
| 797 | void Config::Save() { | ||
| 798 | SaveValues(); | ||
| 799 | } | ||
| 800 | |||
| 801 | void Config::ClearControlPlayerValues() const { | ||
| 802 | // If key is an empty string, all keys in the current group() are removed. | ||
| 803 | const char* section = Settings::TranslateCategory(Settings::Category::Controls); | ||
| 804 | CSimpleIniA::TNamesDepend keys; | ||
| 805 | config->GetAllKeys(section, keys); | ||
| 806 | for (const auto& key : keys) { | ||
| 807 | if (std::string(config->GetValue(section, key.pItem)).empty()) { | ||
| 808 | config->Delete(section, key.pItem); | ||
| 809 | } | ||
| 810 | } | ||
| 811 | } | ||
| 812 | |||
| 813 | const std::string& Config::GetConfigFilePath() const { | ||
| 814 | return config_loc; | ||
| 815 | } | ||
| 816 | |||
| 817 | void Config::ReadCategory(const Settings::Category category) { | ||
| 818 | const auto& settings = FindRelevantList(category); | ||
| 819 | std::ranges::for_each(settings, [&](const auto& setting) { ReadSettingGeneric(setting); }); | ||
| 820 | } | ||
| 821 | |||
| 822 | void Config::WriteCategory(const Settings::Category category) { | ||
| 823 | const auto& settings = FindRelevantList(category); | ||
| 824 | std::ranges::for_each(settings, [&](const auto& setting) { WriteSettingGeneric(setting); }); | ||
| 825 | } | ||
| 826 | |||
| 827 | void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) { | ||
| 828 | if (!setting->Save() || (!setting->Switchable() && !global)) { | ||
| 829 | return; | ||
| 830 | } | ||
| 831 | |||
| 832 | const std::string key = AdjustKey(setting->GetLabel()); | ||
| 833 | const std::string default_value(setting->DefaultToString()); | ||
| 834 | |||
| 835 | bool use_global = true; | ||
| 836 | if (setting->Switchable() && !global) { | ||
| 837 | use_global = | ||
| 838 | ReadBooleanSetting(std::string(key).append("\\use_global"), std::make_optional(true)); | ||
| 839 | setting->SetGlobal(use_global); | ||
| 840 | } | ||
| 841 | |||
| 842 | if (global || !use_global) { | ||
| 843 | const bool is_default = | ||
| 844 | ReadBooleanSetting(std::string(key).append("\\default"), std::make_optional(true)); | ||
| 845 | if (!is_default) { | ||
| 846 | const std::string setting_string = ReadStringSetting(key, default_value); | ||
| 847 | setting->LoadString(setting_string); | ||
| 848 | } else { | ||
| 849 | // Empty string resets the Setting to default | ||
| 850 | setting->LoadString(""); | ||
| 851 | } | ||
| 852 | } | ||
| 853 | } | ||
| 854 | |||
| 855 | void Config::WriteSettingGeneric(const Settings::BasicSetting* const setting) { | ||
| 856 | if (!setting->Save()) { | ||
| 857 | return; | ||
| 858 | } | ||
| 859 | |||
| 860 | std::string key = AdjustKey(setting->GetLabel()); | ||
| 861 | if (setting->Switchable()) { | ||
| 862 | if (!global) { | ||
| 863 | WriteSetting(std::string(key).append("\\use_global"), setting->UsingGlobal()); | ||
| 864 | } | ||
| 865 | if (global || !setting->UsingGlobal()) { | ||
| 866 | WriteSetting(std::string(key).append("\\default"), | ||
| 867 | setting->ToString() == setting->DefaultToString()); | ||
| 868 | WriteSetting(key, setting->ToString()); | ||
| 869 | } | ||
| 870 | } else if (global) { | ||
| 871 | WriteSetting(std::string(key).append("\\default"), | ||
| 872 | setting->ToString() == setting->DefaultToString()); | ||
| 873 | WriteSetting(key, setting->ToString()); | ||
| 874 | } | ||
| 875 | } | ||
| 876 | |||
| 877 | void Config::BeginGroup(const std::string& group) { | ||
| 878 | // You can't begin a group while reading/writing from a config array | ||
| 879 | ASSERT(array_stack.empty()); | ||
| 880 | |||
| 881 | key_stack.push_back(AdjustKey(group)); | ||
| 882 | } | ||
| 883 | |||
| 884 | void Config::EndGroup() { | ||
| 885 | // You can't end a group if you haven't started one yet | ||
| 886 | ASSERT(!key_stack.empty()); | ||
| 887 | |||
| 888 | // You can't end a group when reading/writing from a config array | ||
| 889 | ASSERT(array_stack.empty()); | ||
| 890 | |||
| 891 | key_stack.pop_back(); | ||
| 892 | } | ||
| 893 | |||
| 894 | std::string Config::GetSection() { | ||
| 895 | if (key_stack.empty()) { | ||
| 896 | return std::string{""}; | ||
| 897 | } | ||
| 898 | |||
| 899 | return key_stack.front(); | ||
| 900 | } | ||
| 901 | |||
| 902 | std::string Config::GetGroup() const { | ||
| 903 | if (key_stack.size() <= 1) { | ||
| 904 | return std::string{""}; | ||
| 905 | } | ||
| 906 | |||
| 907 | std::string key; | ||
| 908 | for (size_t i = 1; i < key_stack.size(); ++i) { | ||
| 909 | key.append(key_stack[i]).append("\\"); | ||
| 910 | } | ||
| 911 | return key; | ||
| 912 | } | ||
| 913 | |||
| 914 | std::string Config::AdjustKey(const std::string& key) { | ||
| 915 | std::string adjusted_key(key); | ||
| 916 | boost::replace_all(adjusted_key, "/", "\\"); | ||
| 917 | boost::replace_all(adjusted_key, " ", "%20"); | ||
| 918 | return adjusted_key; | ||
| 919 | } | ||
| 920 | |||
| 921 | std::string Config::AdjustOutputString(const std::string& string) { | ||
| 922 | std::string adjusted_string(string); | ||
| 923 | boost::replace_all(adjusted_string, "\\", "/"); | ||
| 924 | |||
| 925 | // Windows requires that two forward slashes are used at the start of a path for unmapped | ||
| 926 | // network drives so we have to watch for that here | ||
| 927 | if (string.substr(0, 2) == "//") { | ||
| 928 | boost::replace_all(adjusted_string, "//", "/"); | ||
| 929 | adjusted_string.insert(0, "/"); | ||
| 930 | } else { | ||
| 931 | boost::replace_all(adjusted_string, "//", "/"); | ||
| 932 | } | ||
| 933 | |||
| 934 | // Needed for backwards compatibility with QSettings deserialization | ||
| 935 | for (const auto& special_character : special_characters) { | ||
| 936 | if (adjusted_string.find(special_character) != std::string::npos) { | ||
| 937 | adjusted_string.insert(0, "\""); | ||
| 938 | adjusted_string.append("\""); | ||
| 939 | break; | ||
| 940 | } | ||
| 941 | } | ||
| 942 | return adjusted_string; | ||
| 943 | } | ||
| 944 | |||
| 945 | std::string Config::GetFullKey(const std::string& key, bool skipArrayIndex) { | ||
| 946 | if (array_stack.empty()) { | ||
| 947 | return std::string(GetGroup()).append(AdjustKey(key)); | ||
| 948 | } | ||
| 949 | |||
| 950 | std::string array_key; | ||
| 951 | for (size_t i = 0; i < array_stack.size(); ++i) { | ||
| 952 | if (!array_stack[i].name.empty()) { | ||
| 953 | array_key.append(array_stack[i].name).append("\\"); | ||
| 954 | } | ||
| 955 | |||
| 956 | if (!skipArrayIndex || (array_stack.size() - 1 != i && array_stack.size() > 1)) { | ||
| 957 | array_key.append(ToString(array_stack[i].index)).append("\\"); | ||
| 958 | } | ||
| 959 | } | ||
| 960 | std::string final_key = std::string(GetGroup()).append(array_key).append(AdjustKey(key)); | ||
| 961 | return final_key; | ||
| 962 | } | ||
| 963 | |||
| 964 | int Config::BeginArray(const std::string& array) { | ||
| 965 | array_stack.push_back(ConfigArray{AdjustKey(array), 0, 0}); | ||
| 966 | const int size = config->GetLongValue(GetSection().c_str(), | ||
| 967 | GetFullKey(std::string("size"), true).c_str(), 0); | ||
| 968 | array_stack.back().size = size; | ||
| 969 | return size; | ||
| 970 | } | ||
| 971 | |||
| 972 | void Config::EndArray() { | ||
| 973 | // You can't end a config array before starting one | ||
| 974 | ASSERT(!array_stack.empty()); | ||
| 975 | |||
| 976 | // Set the array size to 0 if the array is ended without changing the index | ||
| 977 | int size = 0; | ||
| 978 | if (array_stack.back().index != 0) { | ||
| 979 | size = array_stack.back().size; | ||
| 980 | } | ||
| 981 | |||
| 982 | // Write out the size to config | ||
| 983 | if (key_stack.size() == 1 && array_stack.back().name.empty()) { | ||
| 984 | // Edge-case where the first array created doesn't have a name | ||
| 985 | config->SetValue(GetSection().c_str(), std::string("size").c_str(), ToString(size).c_str()); | ||
| 986 | } else { | ||
| 987 | const auto key = GetFullKey(std::string("size"), true); | ||
| 988 | config->SetValue(GetSection().c_str(), key.c_str(), ToString(size).c_str()); | ||
| 989 | } | ||
| 990 | |||
| 991 | array_stack.pop_back(); | ||
| 992 | } | ||
| 993 | |||
| 994 | void Config::SetArrayIndex(const int index) { | ||
| 995 | // You can't set the array index if you haven't started one yet | ||
| 996 | ASSERT(!array_stack.empty()); | ||
| 997 | |||
| 998 | const int array_index = index + 1; | ||
| 999 | |||
| 1000 | // You can't exceed the known max size of the array by more than 1 | ||
| 1001 | ASSERT(array_stack.front().size + 1 >= array_index); | ||
| 1002 | |||
| 1003 | // Change the config array size to the current index since you may want | ||
| 1004 | // to reduce the number of elements that you read back from the config | ||
| 1005 | // in the future. | ||
| 1006 | array_stack.back().size = array_index; | ||
| 1007 | array_stack.back().index = array_index; | ||
| 1008 | } | ||
diff --git a/src/frontend_common/config.h b/src/frontend_common/config.h new file mode 100644 index 000000000..20a1a8056 --- /dev/null +++ b/src/frontend_common/config.h | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | #include <string> | ||
| 8 | #include "common/settings.h" | ||
| 9 | |||
| 10 | #include <SimpleIni.h> | ||
| 11 | #include <boost/algorithm/string/replace.hpp> | ||
| 12 | |||
| 13 | // Workaround for conflicting definition in libloaderapi.h caused by SimpleIni | ||
| 14 | #undef LoadString | ||
| 15 | #undef CreateFile | ||
| 16 | #undef DeleteFile | ||
| 17 | #undef CopyFile | ||
| 18 | #undef CreateDirectory | ||
| 19 | #undef MoveFile | ||
| 20 | |||
| 21 | namespace Core { | ||
| 22 | class System; | ||
| 23 | } | ||
| 24 | |||
| 25 | class Config { | ||
| 26 | public: | ||
| 27 | enum class ConfigType { | ||
| 28 | GlobalConfig, | ||
| 29 | PerGameConfig, | ||
| 30 | InputProfile, | ||
| 31 | }; | ||
| 32 | |||
| 33 | virtual ~Config() = default; | ||
| 34 | |||
| 35 | void ClearControlPlayerValues() const; | ||
| 36 | |||
| 37 | [[nodiscard]] const std::string& GetConfigFilePath() const; | ||
| 38 | |||
| 39 | [[nodiscard]] bool Exists(const std::string& section, const std::string& key) const; | ||
| 40 | |||
| 41 | protected: | ||
| 42 | explicit Config(ConfigType config_type = ConfigType::GlobalConfig); | ||
| 43 | |||
| 44 | void Initialize(const std::string& config_name = "config"); | ||
| 45 | void Initialize(std::optional<std::string> config_path); | ||
| 46 | |||
| 47 | void WriteToIni() const; | ||
| 48 | |||
| 49 | void SetUpIni(); | ||
| 50 | [[nodiscard]] bool IsCustomConfig() const; | ||
| 51 | |||
| 52 | void Reload(); | ||
| 53 | void Save(); | ||
| 54 | |||
| 55 | /** | ||
| 56 | * Derived config classes must implement this so they can reload all platform-specific | ||
| 57 | * values and global ones. | ||
| 58 | */ | ||
| 59 | virtual void ReloadAllValues() = 0; | ||
| 60 | |||
| 61 | /** | ||
| 62 | * Derived config classes must implement this so they can save all platform-specific | ||
| 63 | * and global values. | ||
| 64 | */ | ||
| 65 | virtual void SaveAllValues() = 0; | ||
| 66 | |||
| 67 | void ReadValues(); | ||
| 68 | void ReadPlayerValues(std::size_t player_index); | ||
| 69 | |||
| 70 | void ReadTouchscreenValues(); | ||
| 71 | void ReadMotionTouchValues(); | ||
| 72 | |||
| 73 | // Read functions bases off the respective config section names. | ||
| 74 | void ReadAudioValues(); | ||
| 75 | void ReadControlValues(); | ||
| 76 | void ReadCoreValues(); | ||
| 77 | void ReadDataStorageValues(); | ||
| 78 | void ReadDebuggingValues(); | ||
| 79 | void ReadServiceValues(); | ||
| 80 | void ReadDisabledAddOnValues(); | ||
| 81 | void ReadMiscellaneousValues(); | ||
| 82 | void ReadCpuValues(); | ||
| 83 | void ReadRendererValues(); | ||
| 84 | void ReadScreenshotValues(); | ||
| 85 | void ReadSystemValues(); | ||
| 86 | void ReadWebServiceValues(); | ||
| 87 | void ReadNetworkValues(); | ||
| 88 | |||
| 89 | // Read platform specific sections | ||
| 90 | virtual void ReadHidbusValues() = 0; | ||
| 91 | virtual void ReadDebugControlValues() = 0; | ||
| 92 | virtual void ReadPathValues() = 0; | ||
| 93 | virtual void ReadShortcutValues() = 0; | ||
| 94 | virtual void ReadUIValues() = 0; | ||
| 95 | virtual void ReadUIGamelistValues() = 0; | ||
| 96 | virtual void ReadUILayoutValues() = 0; | ||
| 97 | virtual void ReadMultiplayerValues() = 0; | ||
| 98 | |||
| 99 | void SaveValues(); | ||
| 100 | void SavePlayerValues(std::size_t player_index); | ||
| 101 | void SaveTouchscreenValues(); | ||
| 102 | void SaveMotionTouchValues(); | ||
| 103 | |||
| 104 | // Save functions based off the respective config section names. | ||
| 105 | void SaveAudioValues(); | ||
| 106 | void SaveControlValues(); | ||
| 107 | void SaveCoreValues(); | ||
| 108 | void SaveDataStorageValues(); | ||
| 109 | void SaveDebuggingValues(); | ||
| 110 | void SaveNetworkValues(); | ||
| 111 | void SaveDisabledAddOnValues(); | ||
| 112 | void SaveMiscellaneousValues(); | ||
| 113 | void SaveCpuValues(); | ||
| 114 | void SaveRendererValues(); | ||
| 115 | void SaveScreenshotValues(); | ||
| 116 | void SaveSystemValues(); | ||
| 117 | void SaveWebServiceValues(); | ||
| 118 | |||
| 119 | // Save platform specific sections | ||
| 120 | virtual void SaveHidbusValues() = 0; | ||
| 121 | virtual void SaveDebugControlValues() = 0; | ||
| 122 | virtual void SavePathValues() = 0; | ||
| 123 | virtual void SaveShortcutValues() = 0; | ||
| 124 | virtual void SaveUIValues() = 0; | ||
| 125 | virtual void SaveUIGamelistValues() = 0; | ||
| 126 | virtual void SaveUILayoutValues() = 0; | ||
| 127 | virtual void SaveMultiplayerValues() = 0; | ||
| 128 | |||
| 129 | virtual std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) = 0; | ||
| 130 | |||
| 131 | /** | ||
| 132 | * Reads a setting from the qt_config. | ||
| 133 | * | ||
| 134 | * @param key The setting's identifier | ||
| 135 | * @param default_value The value to use when the setting is not already present in the config | ||
| 136 | */ | ||
| 137 | bool ReadBooleanSetting(const std::string& key, | ||
| 138 | std::optional<bool> default_value = std::nullopt); | ||
| 139 | s64 ReadIntegerSetting(const std::string& key, std::optional<s64> default_value = std::nullopt); | ||
| 140 | u64 ReadUnsignedIntegerSetting(const std::string& key, | ||
| 141 | std::optional<u64> default_value = std::nullopt); | ||
| 142 | double ReadDoubleSetting(const std::string& key, | ||
| 143 | std::optional<double> default_value = std::nullopt); | ||
| 144 | std::string ReadStringSetting(const std::string& key, | ||
| 145 | std::optional<std::string> default_value = std::nullopt); | ||
| 146 | |||
| 147 | /** | ||
| 148 | * Writes a setting to the qt_config. | ||
| 149 | * | ||
| 150 | * @param key The setting's idetentifier | ||
| 151 | * @param value Value of the setting | ||
| 152 | * @param default_value Default of the setting if not present in config | ||
| 153 | * @param use_global Specifies if the custom or global config should be in use, for custom | ||
| 154 | * configs | ||
| 155 | */ | ||
| 156 | template <typename Type = int> | ||
| 157 | void WriteSetting(const std::string& key, const Type& value, | ||
| 158 | const std::optional<Type>& default_value = std::nullopt, | ||
| 159 | const std::optional<bool>& use_global = std::nullopt); | ||
| 160 | void WriteSettingInternal(const std::string& key, const std::string& value); | ||
| 161 | |||
| 162 | void ReadCategory(Settings::Category category); | ||
| 163 | void WriteCategory(Settings::Category category); | ||
| 164 | void ReadSettingGeneric(Settings::BasicSetting* setting); | ||
| 165 | void WriteSettingGeneric(const Settings::BasicSetting* setting); | ||
| 166 | |||
| 167 | template <typename T> | ||
| 168 | [[nodiscard]] std::string ToString(const T& value_) { | ||
| 169 | if constexpr (std::is_same_v<T, std::string>) { | ||
| 170 | return value_; | ||
| 171 | } else if constexpr (std::is_same_v<T, std::optional<u32>>) { | ||
| 172 | return value_.has_value() ? std::to_string(*value_) : "none"; | ||
| 173 | } else if constexpr (std::is_same_v<T, bool>) { | ||
| 174 | return value_ ? "true" : "false"; | ||
| 175 | } else if constexpr (std::is_same_v<T, u64>) { | ||
| 176 | return std::to_string(static_cast<u64>(value_)); | ||
| 177 | } else { | ||
| 178 | return std::to_string(static_cast<s64>(value_)); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | void BeginGroup(const std::string& group); | ||
| 183 | void EndGroup(); | ||
| 184 | std::string GetSection(); | ||
| 185 | [[nodiscard]] std::string GetGroup() const; | ||
| 186 | static std::string AdjustKey(const std::string& key); | ||
| 187 | static std::string AdjustOutputString(const std::string& string); | ||
| 188 | std::string GetFullKey(const std::string& key, bool skipArrayIndex); | ||
| 189 | int BeginArray(const std::string& array); | ||
| 190 | void EndArray(); | ||
| 191 | void SetArrayIndex(int index); | ||
| 192 | |||
| 193 | const ConfigType type; | ||
| 194 | std::unique_ptr<CSimpleIniA> config; | ||
| 195 | std::string config_loc; | ||
| 196 | const bool global; | ||
| 197 | |||
| 198 | private: | ||
| 199 | inline static std::array<char, 19> special_characters = {'!', '#', '$', '%', '^', '&', '*', | ||
| 200 | '|', ';', '\'', '\"', ',', '<', '.', | ||
| 201 | '>', '?', '`', '~', '='}; | ||
| 202 | |||
| 203 | struct ConfigArray { | ||
| 204 | std::string name; | ||
| 205 | int size; | ||
| 206 | int index; | ||
| 207 | }; | ||
| 208 | std::vector<ConfigArray> array_stack; | ||
| 209 | std::vector<std::string> key_stack; | ||
| 210 | }; | ||
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 181b2817c..90278052a 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -38,8 +38,6 @@ add_executable(yuzu | |||
| 38 | compatdb.ui | 38 | compatdb.ui |
| 39 | compatibility_list.cpp | 39 | compatibility_list.cpp |
| 40 | compatibility_list.h | 40 | compatibility_list.h |
| 41 | configuration/config.cpp | ||
| 42 | configuration/config.h | ||
| 43 | configuration/configuration_shared.cpp | 41 | configuration/configuration_shared.cpp |
| 44 | configuration/configuration_shared.h | 42 | configuration/configuration_shared.h |
| 45 | configuration/configure.ui | 43 | configuration/configure.ui |
| @@ -147,6 +145,8 @@ add_executable(yuzu | |||
| 147 | configuration/shared_translation.h | 145 | configuration/shared_translation.h |
| 148 | configuration/shared_widget.cpp | 146 | configuration/shared_widget.cpp |
| 149 | configuration/shared_widget.h | 147 | configuration/shared_widget.h |
| 148 | configuration/qt_config.cpp | ||
| 149 | configuration/qt_config.h | ||
| 150 | debugger/console.cpp | 150 | debugger/console.cpp |
| 151 | debugger/console.h | 151 | debugger/console.h |
| 152 | debugger/controller.cpp | 152 | debugger/controller.cpp |
| @@ -377,7 +377,7 @@ endif() | |||
| 377 | 377 | ||
| 378 | create_target_directory_groups(yuzu) | 378 | create_target_directory_groups(yuzu) |
| 379 | 379 | ||
| 380 | target_link_libraries(yuzu PRIVATE common core input_common network video_core) | 380 | target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core) |
| 381 | target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets) | 381 | target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets) |
| 382 | target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) | 382 | target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) |
| 383 | 383 | ||
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp deleted file mode 100644 index c0ae6468b..000000000 --- a/src/yuzu/configuration/config.cpp +++ /dev/null | |||
| @@ -1,1309 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2014 Citra Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <array> | ||
| 6 | #include <QKeySequence> | ||
| 7 | #include <QSettings> | ||
| 8 | #include "common/fs/fs.h" | ||
| 9 | #include "common/fs/path_util.h" | ||
| 10 | #include "common/settings.h" | ||
| 11 | #include "common/settings_common.h" | ||
| 12 | #include "common/settings_enums.h" | ||
| 13 | #include "core/core.h" | ||
| 14 | #include "core/hle/service/acc/profile_manager.h" | ||
| 15 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 16 | #include "input_common/main.h" | ||
| 17 | #include "network/network.h" | ||
| 18 | #include "yuzu/configuration/config.h" | ||
| 19 | |||
| 20 | namespace FS = Common::FS; | ||
| 21 | |||
| 22 | Config::Config(const std::string& config_name, ConfigType config_type) | ||
| 23 | : type(config_type), global{config_type == ConfigType::GlobalConfig} { | ||
| 24 | Initialize(config_name); | ||
| 25 | } | ||
| 26 | |||
| 27 | Config::~Config() { | ||
| 28 | if (global) { | ||
| 29 | Save(); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { | ||
| 34 | Qt::Key_C, Qt::Key_X, Qt::Key_V, Qt::Key_Z, Qt::Key_F, | ||
| 35 | Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T, | ||
| 36 | Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, | ||
| 37 | Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0, | ||
| 38 | Qt::Key_Q, Qt::Key_E, | ||
| 39 | }; | ||
| 40 | |||
| 41 | const std::array<int, Settings::NativeMotion::NumMotions> Config::default_motions = { | ||
| 42 | Qt::Key_7, | ||
| 43 | Qt::Key_8, | ||
| 44 | }; | ||
| 45 | |||
| 46 | const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ | ||
| 47 | { | ||
| 48 | Qt::Key_W, | ||
| 49 | Qt::Key_S, | ||
| 50 | Qt::Key_A, | ||
| 51 | Qt::Key_D, | ||
| 52 | }, | ||
| 53 | { | ||
| 54 | Qt::Key_I, | ||
| 55 | Qt::Key_K, | ||
| 56 | Qt::Key_J, | ||
| 57 | Qt::Key_L, | ||
| 58 | }, | ||
| 59 | }}; | ||
| 60 | |||
| 61 | const std::array<int, 2> Config::default_stick_mod = { | ||
| 62 | Qt::Key_Shift, | ||
| 63 | 0, | ||
| 64 | }; | ||
| 65 | |||
| 66 | const std::array<int, 2> Config::default_ringcon_analogs{{ | ||
| 67 | Qt::Key_A, | ||
| 68 | Qt::Key_D, | ||
| 69 | }}; | ||
| 70 | |||
| 71 | const std::map<Settings::AntiAliasing, QString> Config::anti_aliasing_texts_map = { | ||
| 72 | {Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))}, | ||
| 73 | {Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))}, | ||
| 74 | {Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))}, | ||
| 75 | }; | ||
| 76 | |||
| 77 | const std::map<Settings::ScalingFilter, QString> Config::scaling_filter_texts_map = { | ||
| 78 | {Settings::ScalingFilter::NearestNeighbor, | ||
| 79 | QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))}, | ||
| 80 | {Settings::ScalingFilter::Bilinear, | ||
| 81 | QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))}, | ||
| 82 | {Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))}, | ||
| 83 | {Settings::ScalingFilter::Gaussian, | ||
| 84 | QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))}, | ||
| 85 | {Settings::ScalingFilter::ScaleForce, | ||
| 86 | QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))}, | ||
| 87 | {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))}, | ||
| 88 | }; | ||
| 89 | |||
| 90 | const std::map<Settings::ConsoleMode, QString> Config::use_docked_mode_texts_map = { | ||
| 91 | {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))}, | ||
| 92 | {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))}, | ||
| 93 | }; | ||
| 94 | |||
| 95 | const std::map<Settings::GpuAccuracy, QString> Config::gpu_accuracy_texts_map = { | ||
| 96 | {Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))}, | ||
| 97 | {Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))}, | ||
| 98 | {Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))}, | ||
| 99 | }; | ||
| 100 | |||
| 101 | const std::map<Settings::RendererBackend, QString> Config::renderer_backend_texts_map = { | ||
| 102 | {Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))}, | ||
| 103 | {Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))}, | ||
| 104 | {Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))}, | ||
| 105 | }; | ||
| 106 | |||
| 107 | const std::map<Settings::ShaderBackend, QString> Config::shader_backend_texts_map = { | ||
| 108 | {Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))}, | ||
| 109 | {Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))}, | ||
| 110 | {Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))}, | ||
| 111 | }; | ||
| 112 | |||
| 113 | // This shouldn't have anything except static initializers (no functions). So | ||
| 114 | // QKeySequence(...).toString() is NOT ALLOWED HERE. | ||
| 115 | // This must be in alphabetical order according to action name as it must have the same order as | ||
| 116 | // UISetting::values.shortcuts, which is alphabetically ordered. | ||
| 117 | // clang-format off | ||
| 118 | const std::array<UISettings::Shortcut, 23> Config::default_hotkeys{{ | ||
| 119 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut, false}}, | ||
| 120 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut, true}}, | ||
| 121 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut, true}}, | ||
| 122 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut, false}}, | ||
| 123 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut, false}}, | ||
| 124 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut, false}}, | ||
| 125 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut, false}}, | ||
| 126 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut, false}}, | ||
| 127 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut, false}}, | ||
| 128 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut, false}}, | ||
| 129 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F11"), QStringLiteral("Home+B"), Qt::WindowShortcut, false}}, | ||
| 130 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut, false}}, | ||
| 131 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut, false}}, | ||
| 132 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral("R+Plus+Minus"), Qt::WindowShortcut, false}}, | ||
| 133 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral("L+Plus+Minus"), Qt::WindowShortcut, false}}, | ||
| 134 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, | ||
| 135 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, | ||
| 136 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, | ||
| 137 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut, false}}, | ||
| 138 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut, false}}, | ||
| 139 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, | ||
| 140 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral(""), QStringLiteral(""), Qt::ApplicationShortcut, false}}, | ||
| 141 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut, false}}, | ||
| 142 | }}; | ||
| 143 | // clang-format on | ||
| 144 | |||
| 145 | void Config::Initialize(const std::string& config_name) { | ||
| 146 | const auto fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir); | ||
| 147 | const auto config_file = fmt::format("{}.ini", config_name); | ||
| 148 | |||
| 149 | switch (type) { | ||
| 150 | case ConfigType::GlobalConfig: | ||
| 151 | qt_config_loc = FS::PathToUTF8String(fs_config_loc / config_file); | ||
| 152 | void(FS::CreateParentDir(qt_config_loc)); | ||
| 153 | qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), | ||
| 154 | QSettings::IniFormat); | ||
| 155 | Reload(); | ||
| 156 | break; | ||
| 157 | case ConfigType::PerGameConfig: | ||
| 158 | qt_config_loc = | ||
| 159 | FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file)); | ||
| 160 | void(FS::CreateParentDir(qt_config_loc)); | ||
| 161 | qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), | ||
| 162 | QSettings::IniFormat); | ||
| 163 | Reload(); | ||
| 164 | break; | ||
| 165 | case ConfigType::InputProfile: | ||
| 166 | qt_config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file); | ||
| 167 | void(FS::CreateParentDir(qt_config_loc)); | ||
| 168 | qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), | ||
| 169 | QSettings::IniFormat); | ||
| 170 | break; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | bool Config::IsCustomConfig() { | ||
| 175 | return type == ConfigType::PerGameConfig; | ||
| 176 | } | ||
| 177 | |||
| 178 | void Config::ReadPlayerValue(std::size_t player_index) { | ||
| 179 | const QString player_prefix = [this, player_index] { | ||
| 180 | if (type == ConfigType::InputProfile) { | ||
| 181 | return QString{}; | ||
| 182 | } else { | ||
| 183 | return QStringLiteral("player_%1_").arg(player_index); | ||
| 184 | } | ||
| 185 | }(); | ||
| 186 | |||
| 187 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 188 | if (IsCustomConfig()) { | ||
| 189 | const auto profile_name = | ||
| 190 | qt_config->value(QStringLiteral("%1profile_name").arg(player_prefix), QString{}) | ||
| 191 | .toString() | ||
| 192 | .toStdString(); | ||
| 193 | if (profile_name.empty()) { | ||
| 194 | // Use the global input config | ||
| 195 | player = Settings::values.players.GetValue(true)[player_index]; | ||
| 196 | return; | ||
| 197 | } | ||
| 198 | player.profile_name = profile_name; | ||
| 199 | } | ||
| 200 | |||
| 201 | if (player_prefix.isEmpty() && Settings::IsConfiguringGlobal()) { | ||
| 202 | const auto controller = static_cast<Settings::ControllerType>( | ||
| 203 | qt_config | ||
| 204 | ->value(QStringLiteral("%1type").arg(player_prefix), | ||
| 205 | static_cast<u8>(Settings::ControllerType::ProController)) | ||
| 206 | .toUInt()); | ||
| 207 | |||
| 208 | if (controller == Settings::ControllerType::LeftJoycon || | ||
| 209 | controller == Settings::ControllerType::RightJoycon) { | ||
| 210 | player.controller_type = controller; | ||
| 211 | } | ||
| 212 | } else { | ||
| 213 | player.connected = | ||
| 214 | ReadSetting(QStringLiteral("%1connected").arg(player_prefix), player_index == 0) | ||
| 215 | .toBool(); | ||
| 216 | |||
| 217 | player.controller_type = static_cast<Settings::ControllerType>( | ||
| 218 | qt_config | ||
| 219 | ->value(QStringLiteral("%1type").arg(player_prefix), | ||
| 220 | static_cast<u8>(Settings::ControllerType::ProController)) | ||
| 221 | .toUInt()); | ||
| 222 | |||
| 223 | player.vibration_enabled = | ||
| 224 | qt_config->value(QStringLiteral("%1vibration_enabled").arg(player_prefix), true) | ||
| 225 | .toBool(); | ||
| 226 | |||
| 227 | player.vibration_strength = | ||
| 228 | qt_config->value(QStringLiteral("%1vibration_strength").arg(player_prefix), 100) | ||
| 229 | .toInt(); | ||
| 230 | |||
| 231 | player.body_color_left = qt_config | ||
| 232 | ->value(QStringLiteral("%1body_color_left").arg(player_prefix), | ||
| 233 | Settings::JOYCON_BODY_NEON_BLUE) | ||
| 234 | .toUInt(); | ||
| 235 | player.body_color_right = | ||
| 236 | qt_config | ||
| 237 | ->value(QStringLiteral("%1body_color_right").arg(player_prefix), | ||
| 238 | Settings::JOYCON_BODY_NEON_RED) | ||
| 239 | .toUInt(); | ||
| 240 | player.button_color_left = | ||
| 241 | qt_config | ||
| 242 | ->value(QStringLiteral("%1button_color_left").arg(player_prefix), | ||
| 243 | Settings::JOYCON_BUTTONS_NEON_BLUE) | ||
| 244 | .toUInt(); | ||
| 245 | player.button_color_right = | ||
| 246 | qt_config | ||
| 247 | ->value(QStringLiteral("%1button_color_right").arg(player_prefix), | ||
| 248 | Settings::JOYCON_BUTTONS_NEON_RED) | ||
| 249 | .toUInt(); | ||
| 250 | } | ||
| 251 | |||
| 252 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 253 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 254 | auto& player_buttons = player.buttons[i]; | ||
| 255 | |||
| 256 | player_buttons = qt_config | ||
| 257 | ->value(QStringLiteral("%1").arg(player_prefix) + | ||
| 258 | QString::fromUtf8(Settings::NativeButton::mapping[i]), | ||
| 259 | QString::fromStdString(default_param)) | ||
| 260 | .toString() | ||
| 261 | .toStdString(); | ||
| 262 | if (player_buttons.empty()) { | ||
| 263 | player_buttons = default_param; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 268 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 269 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 270 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 271 | auto& player_analogs = player.analogs[i]; | ||
| 272 | |||
| 273 | player_analogs = qt_config | ||
| 274 | ->value(QStringLiteral("%1").arg(player_prefix) + | ||
| 275 | QString::fromUtf8(Settings::NativeAnalog::mapping[i]), | ||
| 276 | QString::fromStdString(default_param)) | ||
| 277 | .toString() | ||
| 278 | .toStdString(); | ||
| 279 | if (player_analogs.empty()) { | ||
| 280 | player_analogs = default_param; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | ||
| 285 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); | ||
| 286 | auto& player_motions = player.motions[i]; | ||
| 287 | |||
| 288 | player_motions = qt_config | ||
| 289 | ->value(QStringLiteral("%1").arg(player_prefix) + | ||
| 290 | QString::fromUtf8(Settings::NativeMotion::mapping[i]), | ||
| 291 | QString::fromStdString(default_param)) | ||
| 292 | .toString() | ||
| 293 | .toStdString(); | ||
| 294 | if (player_motions.empty()) { | ||
| 295 | player_motions = default_param; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | void Config::ReadDebugValues() { | ||
| 301 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 302 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 303 | auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; | ||
| 304 | |||
| 305 | debug_pad_buttons = qt_config | ||
| 306 | ->value(QStringLiteral("debug_pad_") + | ||
| 307 | QString::fromUtf8(Settings::NativeButton::mapping[i]), | ||
| 308 | QString::fromStdString(default_param)) | ||
| 309 | .toString() | ||
| 310 | .toStdString(); | ||
| 311 | if (debug_pad_buttons.empty()) { | ||
| 312 | debug_pad_buttons = default_param; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 317 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 318 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 319 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 320 | auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; | ||
| 321 | |||
| 322 | debug_pad_analogs = qt_config | ||
| 323 | ->value(QStringLiteral("debug_pad_") + | ||
| 324 | QString::fromUtf8(Settings::NativeAnalog::mapping[i]), | ||
| 325 | QString::fromStdString(default_param)) | ||
| 326 | .toString() | ||
| 327 | .toStdString(); | ||
| 328 | if (debug_pad_analogs.empty()) { | ||
| 329 | debug_pad_analogs = default_param; | ||
| 330 | } | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | void Config::ReadTouchscreenValues() { | ||
| 335 | Settings::values.touchscreen.enabled = | ||
| 336 | ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool(); | ||
| 337 | |||
| 338 | Settings::values.touchscreen.rotation_angle = | ||
| 339 | ReadSetting(QStringLiteral("touchscreen_angle"), 0).toUInt(); | ||
| 340 | Settings::values.touchscreen.diameter_x = | ||
| 341 | ReadSetting(QStringLiteral("touchscreen_diameter_x"), 15).toUInt(); | ||
| 342 | Settings::values.touchscreen.diameter_y = | ||
| 343 | ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt(); | ||
| 344 | } | ||
| 345 | |||
| 346 | void Config::ReadHidbusValues() { | ||
| 347 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 348 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); | ||
| 349 | auto& ringcon_analogs = Settings::values.ringcon_analogs; | ||
| 350 | |||
| 351 | ringcon_analogs = | ||
| 352 | qt_config->value(QStringLiteral("ring_controller"), QString::fromStdString(default_param)) | ||
| 353 | .toString() | ||
| 354 | .toStdString(); | ||
| 355 | if (ringcon_analogs.empty()) { | ||
| 356 | ringcon_analogs = default_param; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | void Config::ReadAudioValues() { | ||
| 361 | qt_config->beginGroup(QStringLiteral("Audio")); | ||
| 362 | |||
| 363 | ReadCategory(Settings::Category::Audio); | ||
| 364 | ReadCategory(Settings::Category::UiAudio); | ||
| 365 | |||
| 366 | qt_config->endGroup(); | ||
| 367 | } | ||
| 368 | |||
| 369 | void Config::ReadControlValues() { | ||
| 370 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 371 | |||
| 372 | ReadCategory(Settings::Category::Controls); | ||
| 373 | |||
| 374 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 375 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | ||
| 376 | ReadPlayerValue(p); | ||
| 377 | } | ||
| 378 | |||
| 379 | // Disable docked mode if handheld is selected | ||
| 380 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; | ||
| 381 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 382 | Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig()); | ||
| 383 | Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld); | ||
| 384 | } | ||
| 385 | |||
| 386 | if (IsCustomConfig()) { | ||
| 387 | qt_config->endGroup(); | ||
| 388 | return; | ||
| 389 | } | ||
| 390 | ReadDebugValues(); | ||
| 391 | ReadTouchscreenValues(); | ||
| 392 | ReadMotionTouchValues(); | ||
| 393 | ReadHidbusValues(); | ||
| 394 | |||
| 395 | qt_config->endGroup(); | ||
| 396 | } | ||
| 397 | |||
| 398 | void Config::ReadMotionTouchValues() { | ||
| 399 | int num_touch_from_button_maps = | ||
| 400 | qt_config->beginReadArray(QStringLiteral("touch_from_button_maps")); | ||
| 401 | |||
| 402 | if (num_touch_from_button_maps > 0) { | ||
| 403 | const auto append_touch_from_button_map = [this] { | ||
| 404 | Settings::TouchFromButtonMap map; | ||
| 405 | map.name = ReadSetting(QStringLiteral("name"), QStringLiteral("default")) | ||
| 406 | .toString() | ||
| 407 | .toStdString(); | ||
| 408 | const int num_touch_maps = qt_config->beginReadArray(QStringLiteral("entries")); | ||
| 409 | map.buttons.reserve(num_touch_maps); | ||
| 410 | for (int i = 0; i < num_touch_maps; i++) { | ||
| 411 | qt_config->setArrayIndex(i); | ||
| 412 | std::string touch_mapping = | ||
| 413 | ReadSetting(QStringLiteral("bind")).toString().toStdString(); | ||
| 414 | map.buttons.emplace_back(std::move(touch_mapping)); | ||
| 415 | } | ||
| 416 | qt_config->endArray(); // entries | ||
| 417 | Settings::values.touch_from_button_maps.emplace_back(std::move(map)); | ||
| 418 | }; | ||
| 419 | |||
| 420 | for (int i = 0; i < num_touch_from_button_maps; ++i) { | ||
| 421 | qt_config->setArrayIndex(i); | ||
| 422 | append_touch_from_button_map(); | ||
| 423 | } | ||
| 424 | } else { | ||
| 425 | Settings::values.touch_from_button_maps.emplace_back( | ||
| 426 | Settings::TouchFromButtonMap{"default", {}}); | ||
| 427 | num_touch_from_button_maps = 1; | ||
| 428 | } | ||
| 429 | qt_config->endArray(); | ||
| 430 | |||
| 431 | Settings::values.touch_from_button_map_index = std::clamp( | ||
| 432 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); | ||
| 433 | } | ||
| 434 | |||
| 435 | void Config::ReadCoreValues() { | ||
| 436 | qt_config->beginGroup(QStringLiteral("Core")); | ||
| 437 | |||
| 438 | ReadCategory(Settings::Category::Core); | ||
| 439 | |||
| 440 | qt_config->endGroup(); | ||
| 441 | } | ||
| 442 | |||
| 443 | void Config::ReadDataStorageValues() { | ||
| 444 | qt_config->beginGroup(QStringLiteral("Data Storage")); | ||
| 445 | |||
| 446 | FS::SetYuzuPath( | ||
| 447 | FS::YuzuPath::NANDDir, | ||
| 448 | qt_config | ||
| 449 | ->value(QStringLiteral("nand_directory"), | ||
| 450 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))) | ||
| 451 | .toString() | ||
| 452 | .toStdString()); | ||
| 453 | FS::SetYuzuPath( | ||
| 454 | FS::YuzuPath::SDMCDir, | ||
| 455 | qt_config | ||
| 456 | ->value(QStringLiteral("sdmc_directory"), | ||
| 457 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir))) | ||
| 458 | .toString() | ||
| 459 | .toStdString()); | ||
| 460 | FS::SetYuzuPath( | ||
| 461 | FS::YuzuPath::LoadDir, | ||
| 462 | qt_config | ||
| 463 | ->value(QStringLiteral("load_directory"), | ||
| 464 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir))) | ||
| 465 | .toString() | ||
| 466 | .toStdString()); | ||
| 467 | FS::SetYuzuPath( | ||
| 468 | FS::YuzuPath::DumpDir, | ||
| 469 | qt_config | ||
| 470 | ->value(QStringLiteral("dump_directory"), | ||
| 471 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))) | ||
| 472 | .toString() | ||
| 473 | .toStdString()); | ||
| 474 | FS::SetYuzuPath(FS::YuzuPath::TASDir, | ||
| 475 | qt_config | ||
| 476 | ->value(QStringLiteral("tas_directory"), | ||
| 477 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir))) | ||
| 478 | .toString() | ||
| 479 | .toStdString()); | ||
| 480 | |||
| 481 | ReadCategory(Settings::Category::DataStorage); | ||
| 482 | |||
| 483 | qt_config->endGroup(); | ||
| 484 | } | ||
| 485 | |||
| 486 | void Config::ReadDebuggingValues() { | ||
| 487 | qt_config->beginGroup(QStringLiteral("Debugging")); | ||
| 488 | |||
| 489 | // Intentionally not using the QT default setting as this is intended to be changed in the ini | ||
| 490 | Settings::values.record_frame_times = | ||
| 491 | qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); | ||
| 492 | |||
| 493 | ReadCategory(Settings::Category::Debugging); | ||
| 494 | ReadCategory(Settings::Category::DebuggingGraphics); | ||
| 495 | |||
| 496 | qt_config->endGroup(); | ||
| 497 | } | ||
| 498 | |||
| 499 | void Config::ReadServiceValues() { | ||
| 500 | qt_config->beginGroup(QStringLiteral("Services")); | ||
| 501 | |||
| 502 | ReadCategory(Settings::Category::Services); | ||
| 503 | |||
| 504 | qt_config->endGroup(); | ||
| 505 | } | ||
| 506 | |||
| 507 | void Config::ReadDisabledAddOnValues() { | ||
| 508 | const auto size = qt_config->beginReadArray(QStringLiteral("DisabledAddOns")); | ||
| 509 | |||
| 510 | for (int i = 0; i < size; ++i) { | ||
| 511 | qt_config->setArrayIndex(i); | ||
| 512 | const auto title_id = ReadSetting(QStringLiteral("title_id"), 0).toULongLong(); | ||
| 513 | std::vector<std::string> out; | ||
| 514 | const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled")); | ||
| 515 | for (int j = 0; j < d_size; ++j) { | ||
| 516 | qt_config->setArrayIndex(j); | ||
| 517 | out.push_back(ReadSetting(QStringLiteral("d"), QString{}).toString().toStdString()); | ||
| 518 | } | ||
| 519 | qt_config->endArray(); | ||
| 520 | Settings::values.disabled_addons.insert_or_assign(title_id, out); | ||
| 521 | } | ||
| 522 | |||
| 523 | qt_config->endArray(); | ||
| 524 | } | ||
| 525 | |||
| 526 | void Config::ReadMiscellaneousValues() { | ||
| 527 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); | ||
| 528 | |||
| 529 | ReadCategory(Settings::Category::Miscellaneous); | ||
| 530 | |||
| 531 | qt_config->endGroup(); | ||
| 532 | } | ||
| 533 | |||
| 534 | void Config::ReadPathValues() { | ||
| 535 | qt_config->beginGroup(QStringLiteral("Paths")); | ||
| 536 | |||
| 537 | UISettings::values.roms_path = ReadSetting(QStringLiteral("romsPath")).toString(); | ||
| 538 | UISettings::values.symbols_path = ReadSetting(QStringLiteral("symbolsPath")).toString(); | ||
| 539 | UISettings::values.game_dir_deprecated = | ||
| 540 | ReadSetting(QStringLiteral("gameListRootDir"), QStringLiteral(".")).toString(); | ||
| 541 | UISettings::values.game_dir_deprecated_deepscan = | ||
| 542 | ReadSetting(QStringLiteral("gameListDeepScan"), false).toBool(); | ||
| 543 | const int gamedirs_size = qt_config->beginReadArray(QStringLiteral("gamedirs")); | ||
| 544 | for (int i = 0; i < gamedirs_size; ++i) { | ||
| 545 | qt_config->setArrayIndex(i); | ||
| 546 | UISettings::GameDir game_dir; | ||
| 547 | game_dir.path = ReadSetting(QStringLiteral("path")).toString(); | ||
| 548 | game_dir.deep_scan = ReadSetting(QStringLiteral("deep_scan"), false).toBool(); | ||
| 549 | game_dir.expanded = ReadSetting(QStringLiteral("expanded"), true).toBool(); | ||
| 550 | UISettings::values.game_dirs.append(game_dir); | ||
| 551 | } | ||
| 552 | qt_config->endArray(); | ||
| 553 | // create NAND and SD card directories if empty, these are not removable through the UI, | ||
| 554 | // also carries over old game list settings if present | ||
| 555 | if (UISettings::values.game_dirs.isEmpty()) { | ||
| 556 | UISettings::GameDir game_dir; | ||
| 557 | game_dir.path = QStringLiteral("SDMC"); | ||
| 558 | game_dir.expanded = true; | ||
| 559 | UISettings::values.game_dirs.append(game_dir); | ||
| 560 | game_dir.path = QStringLiteral("UserNAND"); | ||
| 561 | UISettings::values.game_dirs.append(game_dir); | ||
| 562 | game_dir.path = QStringLiteral("SysNAND"); | ||
| 563 | UISettings::values.game_dirs.append(game_dir); | ||
| 564 | if (UISettings::values.game_dir_deprecated != QStringLiteral(".")) { | ||
| 565 | game_dir.path = UISettings::values.game_dir_deprecated; | ||
| 566 | game_dir.deep_scan = UISettings::values.game_dir_deprecated_deepscan; | ||
| 567 | UISettings::values.game_dirs.append(game_dir); | ||
| 568 | } | ||
| 569 | } | ||
| 570 | UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList(); | ||
| 571 | UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString(); | ||
| 572 | |||
| 573 | qt_config->endGroup(); | ||
| 574 | } | ||
| 575 | |||
| 576 | void Config::ReadCpuValues() { | ||
| 577 | qt_config->beginGroup(QStringLiteral("Cpu")); | ||
| 578 | |||
| 579 | ReadCategory(Settings::Category::Cpu); | ||
| 580 | ReadCategory(Settings::Category::CpuDebug); | ||
| 581 | ReadCategory(Settings::Category::CpuUnsafe); | ||
| 582 | |||
| 583 | qt_config->endGroup(); | ||
| 584 | } | ||
| 585 | |||
| 586 | void Config::ReadRendererValues() { | ||
| 587 | qt_config->beginGroup(QStringLiteral("Renderer")); | ||
| 588 | |||
| 589 | ReadCategory(Settings::Category::Renderer); | ||
| 590 | ReadCategory(Settings::Category::RendererAdvanced); | ||
| 591 | ReadCategory(Settings::Category::RendererDebug); | ||
| 592 | |||
| 593 | qt_config->endGroup(); | ||
| 594 | } | ||
| 595 | |||
| 596 | void Config::ReadScreenshotValues() { | ||
| 597 | qt_config->beginGroup(QStringLiteral("Screenshots")); | ||
| 598 | |||
| 599 | ReadCategory(Settings::Category::Screenshots); | ||
| 600 | FS::SetYuzuPath( | ||
| 601 | FS::YuzuPath::ScreenshotsDir, | ||
| 602 | qt_config | ||
| 603 | ->value(QStringLiteral("screenshot_path"), | ||
| 604 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir))) | ||
| 605 | .toString() | ||
| 606 | .toStdString()); | ||
| 607 | |||
| 608 | qt_config->endGroup(); | ||
| 609 | } | ||
| 610 | |||
| 611 | void Config::ReadShortcutValues() { | ||
| 612 | qt_config->beginGroup(QStringLiteral("Shortcuts")); | ||
| 613 | |||
| 614 | for (const auto& [name, group, shortcut] : default_hotkeys) { | ||
| 615 | qt_config->beginGroup(group); | ||
| 616 | qt_config->beginGroup(name); | ||
| 617 | // No longer using ReadSetting for shortcut.second as it inaccurately returns a value of 1 | ||
| 618 | // for WidgetWithChildrenShortcut which is a value of 3. Needed to fix shortcuts the open | ||
| 619 | // a file dialog in windowed mode | ||
| 620 | UISettings::values.shortcuts.push_back( | ||
| 621 | {name, | ||
| 622 | group, | ||
| 623 | {ReadSetting(QStringLiteral("KeySeq"), shortcut.keyseq).toString(), | ||
| 624 | ReadSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq) | ||
| 625 | .toString(), | ||
| 626 | shortcut.context, ReadSetting(QStringLiteral("Repeat"), shortcut.repeat).toBool()}}); | ||
| 627 | qt_config->endGroup(); | ||
| 628 | qt_config->endGroup(); | ||
| 629 | } | ||
| 630 | |||
| 631 | qt_config->endGroup(); | ||
| 632 | } | ||
| 633 | |||
| 634 | void Config::ReadSystemValues() { | ||
| 635 | qt_config->beginGroup(QStringLiteral("System")); | ||
| 636 | |||
| 637 | ReadCategory(Settings::Category::System); | ||
| 638 | ReadCategory(Settings::Category::SystemAudio); | ||
| 639 | |||
| 640 | qt_config->endGroup(); | ||
| 641 | } | ||
| 642 | |||
| 643 | void Config::ReadUIValues() { | ||
| 644 | qt_config->beginGroup(QStringLiteral("UI")); | ||
| 645 | |||
| 646 | UISettings::values.theme = | ||
| 647 | ReadSetting( | ||
| 648 | QStringLiteral("theme"), | ||
| 649 | QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second)) | ||
| 650 | .toString(); | ||
| 651 | |||
| 652 | ReadUIGamelistValues(); | ||
| 653 | ReadUILayoutValues(); | ||
| 654 | ReadPathValues(); | ||
| 655 | ReadScreenshotValues(); | ||
| 656 | ReadShortcutValues(); | ||
| 657 | ReadMultiplayerValues(); | ||
| 658 | |||
| 659 | ReadCategory(Settings::Category::Ui); | ||
| 660 | ReadCategory(Settings::Category::UiGeneral); | ||
| 661 | |||
| 662 | qt_config->endGroup(); | ||
| 663 | } | ||
| 664 | |||
| 665 | void Config::ReadUIGamelistValues() { | ||
| 666 | qt_config->beginGroup(QStringLiteral("UIGameList")); | ||
| 667 | |||
| 668 | ReadCategory(Settings::Category::UiGameList); | ||
| 669 | |||
| 670 | const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); | ||
| 671 | for (int i = 0; i < favorites_size; i++) { | ||
| 672 | qt_config->setArrayIndex(i); | ||
| 673 | UISettings::values.favorited_ids.append( | ||
| 674 | ReadSetting(QStringLiteral("program_id")).toULongLong()); | ||
| 675 | } | ||
| 676 | qt_config->endArray(); | ||
| 677 | |||
| 678 | qt_config->endGroup(); | ||
| 679 | } | ||
| 680 | |||
| 681 | void Config::ReadUILayoutValues() { | ||
| 682 | qt_config->beginGroup(QStringLiteral("UILayout")); | ||
| 683 | |||
| 684 | UISettings::values.geometry = ReadSetting(QStringLiteral("geometry")).toByteArray(); | ||
| 685 | UISettings::values.state = ReadSetting(QStringLiteral("state")).toByteArray(); | ||
| 686 | UISettings::values.renderwindow_geometry = | ||
| 687 | ReadSetting(QStringLiteral("geometryRenderWindow")).toByteArray(); | ||
| 688 | UISettings::values.gamelist_header_state = | ||
| 689 | ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray(); | ||
| 690 | UISettings::values.microprofile_geometry = | ||
| 691 | ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray(); | ||
| 692 | |||
| 693 | ReadCategory(Settings::Category::UiLayout); | ||
| 694 | |||
| 695 | qt_config->endGroup(); | ||
| 696 | } | ||
| 697 | |||
| 698 | void Config::ReadWebServiceValues() { | ||
| 699 | qt_config->beginGroup(QStringLiteral("WebService")); | ||
| 700 | |||
| 701 | ReadCategory(Settings::Category::WebService); | ||
| 702 | |||
| 703 | qt_config->endGroup(); | ||
| 704 | } | ||
| 705 | |||
| 706 | void Config::ReadMultiplayerValues() { | ||
| 707 | qt_config->beginGroup(QStringLiteral("Multiplayer")); | ||
| 708 | |||
| 709 | ReadCategory(Settings::Category::Multiplayer); | ||
| 710 | |||
| 711 | // Read ban list back | ||
| 712 | int size = qt_config->beginReadArray(QStringLiteral("username_ban_list")); | ||
| 713 | UISettings::values.multiplayer_ban_list.first.resize(size); | ||
| 714 | for (int i = 0; i < size; ++i) { | ||
| 715 | qt_config->setArrayIndex(i); | ||
| 716 | UISettings::values.multiplayer_ban_list.first[i] = | ||
| 717 | ReadSetting(QStringLiteral("username")).toString().toStdString(); | ||
| 718 | } | ||
| 719 | qt_config->endArray(); | ||
| 720 | size = qt_config->beginReadArray(QStringLiteral("ip_ban_list")); | ||
| 721 | UISettings::values.multiplayer_ban_list.second.resize(size); | ||
| 722 | for (int i = 0; i < size; ++i) { | ||
| 723 | qt_config->setArrayIndex(i); | ||
| 724 | UISettings::values.multiplayer_ban_list.second[i] = | ||
| 725 | ReadSetting(QStringLiteral("ip")).toString().toStdString(); | ||
| 726 | } | ||
| 727 | qt_config->endArray(); | ||
| 728 | |||
| 729 | qt_config->endGroup(); | ||
| 730 | } | ||
| 731 | |||
| 732 | void Config::ReadNetworkValues() { | ||
| 733 | qt_config->beginGroup(QString::fromStdString("Services")); | ||
| 734 | |||
| 735 | ReadCategory(Settings::Category::Network); | ||
| 736 | |||
| 737 | qt_config->endGroup(); | ||
| 738 | } | ||
| 739 | |||
| 740 | void Config::ReadValues() { | ||
| 741 | if (global) { | ||
| 742 | ReadDataStorageValues(); | ||
| 743 | ReadDebuggingValues(); | ||
| 744 | ReadDisabledAddOnValues(); | ||
| 745 | ReadNetworkValues(); | ||
| 746 | ReadServiceValues(); | ||
| 747 | ReadUIValues(); | ||
| 748 | ReadWebServiceValues(); | ||
| 749 | ReadMiscellaneousValues(); | ||
| 750 | } | ||
| 751 | ReadControlValues(); | ||
| 752 | ReadCoreValues(); | ||
| 753 | ReadCpuValues(); | ||
| 754 | ReadRendererValues(); | ||
| 755 | ReadAudioValues(); | ||
| 756 | ReadSystemValues(); | ||
| 757 | } | ||
| 758 | |||
| 759 | void Config::SavePlayerValue(std::size_t player_index) { | ||
| 760 | const QString player_prefix = [this, player_index] { | ||
| 761 | if (type == ConfigType::InputProfile) { | ||
| 762 | return QString{}; | ||
| 763 | } else { | ||
| 764 | return QStringLiteral("player_%1_").arg(player_index); | ||
| 765 | } | ||
| 766 | }(); | ||
| 767 | |||
| 768 | const auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 769 | if (IsCustomConfig()) { | ||
| 770 | if (player.profile_name.empty()) { | ||
| 771 | // No custom profile selected | ||
| 772 | return; | ||
| 773 | } | ||
| 774 | WriteSetting(QStringLiteral("%1profile_name").arg(player_prefix), | ||
| 775 | QString::fromStdString(player.profile_name), QString{}); | ||
| 776 | } | ||
| 777 | |||
| 778 | WriteSetting(QStringLiteral("%1type").arg(player_prefix), | ||
| 779 | static_cast<u8>(player.controller_type), | ||
| 780 | static_cast<u8>(Settings::ControllerType::ProController)); | ||
| 781 | |||
| 782 | if (!player_prefix.isEmpty() || !Settings::IsConfiguringGlobal()) { | ||
| 783 | WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, | ||
| 784 | player_index == 0); | ||
| 785 | WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), | ||
| 786 | player.vibration_enabled, true); | ||
| 787 | WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix), | ||
| 788 | player.vibration_strength, 100); | ||
| 789 | WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left, | ||
| 790 | Settings::JOYCON_BODY_NEON_BLUE); | ||
| 791 | WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix), | ||
| 792 | player.body_color_right, Settings::JOYCON_BODY_NEON_RED); | ||
| 793 | WriteSetting(QStringLiteral("%1button_color_left").arg(player_prefix), | ||
| 794 | player.button_color_left, Settings::JOYCON_BUTTONS_NEON_BLUE); | ||
| 795 | WriteSetting(QStringLiteral("%1button_color_right").arg(player_prefix), | ||
| 796 | player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED); | ||
| 797 | } | ||
| 798 | |||
| 799 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 800 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 801 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + | ||
| 802 | QString::fromStdString(Settings::NativeButton::mapping[i]), | ||
| 803 | QString::fromStdString(player.buttons[i]), | ||
| 804 | QString::fromStdString(default_param)); | ||
| 805 | } | ||
| 806 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 807 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 808 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 809 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 810 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + | ||
| 811 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), | ||
| 812 | QString::fromStdString(player.analogs[i]), | ||
| 813 | QString::fromStdString(default_param)); | ||
| 814 | } | ||
| 815 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | ||
| 816 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); | ||
| 817 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + | ||
| 818 | QString::fromStdString(Settings::NativeMotion::mapping[i]), | ||
| 819 | QString::fromStdString(player.motions[i]), | ||
| 820 | QString::fromStdString(default_param)); | ||
| 821 | } | ||
| 822 | } | ||
| 823 | |||
| 824 | void Config::SaveDebugValues() { | ||
| 825 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 826 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 827 | WriteSetting(QStringLiteral("debug_pad_") + | ||
| 828 | QString::fromStdString(Settings::NativeButton::mapping[i]), | ||
| 829 | QString::fromStdString(Settings::values.debug_pad_buttons[i]), | ||
| 830 | QString::fromStdString(default_param)); | ||
| 831 | } | ||
| 832 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 833 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 834 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 835 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 836 | WriteSetting(QStringLiteral("debug_pad_") + | ||
| 837 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), | ||
| 838 | QString::fromStdString(Settings::values.debug_pad_analogs[i]), | ||
| 839 | QString::fromStdString(default_param)); | ||
| 840 | } | ||
| 841 | } | ||
| 842 | |||
| 843 | void Config::SaveTouchscreenValues() { | ||
| 844 | const auto& touchscreen = Settings::values.touchscreen; | ||
| 845 | |||
| 846 | WriteSetting(QStringLiteral("touchscreen_enabled"), touchscreen.enabled, true); | ||
| 847 | |||
| 848 | WriteSetting(QStringLiteral("touchscreen_angle"), touchscreen.rotation_angle, 0); | ||
| 849 | WriteSetting(QStringLiteral("touchscreen_diameter_x"), touchscreen.diameter_x, 15); | ||
| 850 | WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); | ||
| 851 | } | ||
| 852 | |||
| 853 | void Config::SaveMotionTouchValues() { | ||
| 854 | qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); | ||
| 855 | for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { | ||
| 856 | qt_config->setArrayIndex(static_cast<int>(p)); | ||
| 857 | WriteSetting(QStringLiteral("name"), | ||
| 858 | QString::fromStdString(Settings::values.touch_from_button_maps[p].name), | ||
| 859 | QStringLiteral("default")); | ||
| 860 | qt_config->beginWriteArray(QStringLiteral("entries")); | ||
| 861 | for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size(); | ||
| 862 | ++q) { | ||
| 863 | qt_config->setArrayIndex(static_cast<int>(q)); | ||
| 864 | WriteSetting( | ||
| 865 | QStringLiteral("bind"), | ||
| 866 | QString::fromStdString(Settings::values.touch_from_button_maps[p].buttons[q])); | ||
| 867 | } | ||
| 868 | qt_config->endArray(); | ||
| 869 | } | ||
| 870 | qt_config->endArray(); | ||
| 871 | } | ||
| 872 | |||
| 873 | void Config::SaveHidbusValues() { | ||
| 874 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 875 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); | ||
| 876 | WriteSetting(QStringLiteral("ring_controller"), | ||
| 877 | QString::fromStdString(Settings::values.ringcon_analogs), | ||
| 878 | QString::fromStdString(default_param)); | ||
| 879 | } | ||
| 880 | |||
| 881 | void Config::SaveValues() { | ||
| 882 | if (global) { | ||
| 883 | SaveDataStorageValues(); | ||
| 884 | SaveDebuggingValues(); | ||
| 885 | SaveDisabledAddOnValues(); | ||
| 886 | SaveNetworkValues(); | ||
| 887 | SaveUIValues(); | ||
| 888 | SaveWebServiceValues(); | ||
| 889 | SaveMiscellaneousValues(); | ||
| 890 | } | ||
| 891 | SaveControlValues(); | ||
| 892 | SaveCoreValues(); | ||
| 893 | SaveCpuValues(); | ||
| 894 | SaveRendererValues(); | ||
| 895 | SaveAudioValues(); | ||
| 896 | SaveSystemValues(); | ||
| 897 | |||
| 898 | qt_config->sync(); | ||
| 899 | } | ||
| 900 | |||
| 901 | void Config::SaveAudioValues() { | ||
| 902 | qt_config->beginGroup(QStringLiteral("Audio")); | ||
| 903 | |||
| 904 | WriteCategory(Settings::Category::Audio); | ||
| 905 | WriteCategory(Settings::Category::UiAudio); | ||
| 906 | |||
| 907 | qt_config->endGroup(); | ||
| 908 | } | ||
| 909 | |||
| 910 | void Config::SaveControlValues() { | ||
| 911 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 912 | |||
| 913 | WriteCategory(Settings::Category::Controls); | ||
| 914 | |||
| 915 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 916 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | ||
| 917 | SavePlayerValue(p); | ||
| 918 | } | ||
| 919 | if (IsCustomConfig()) { | ||
| 920 | qt_config->endGroup(); | ||
| 921 | return; | ||
| 922 | } | ||
| 923 | SaveDebugValues(); | ||
| 924 | SaveTouchscreenValues(); | ||
| 925 | SaveMotionTouchValues(); | ||
| 926 | SaveHidbusValues(); | ||
| 927 | |||
| 928 | qt_config->endGroup(); | ||
| 929 | } | ||
| 930 | |||
| 931 | void Config::SaveCoreValues() { | ||
| 932 | qt_config->beginGroup(QStringLiteral("Core")); | ||
| 933 | |||
| 934 | WriteCategory(Settings::Category::Core); | ||
| 935 | |||
| 936 | qt_config->endGroup(); | ||
| 937 | } | ||
| 938 | |||
| 939 | void Config::SaveDataStorageValues() { | ||
| 940 | qt_config->beginGroup(QStringLiteral("Data Storage")); | ||
| 941 | |||
| 942 | WriteSetting(QStringLiteral("nand_directory"), | ||
| 943 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)), | ||
| 944 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); | ||
| 945 | WriteSetting(QStringLiteral("sdmc_directory"), | ||
| 946 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)), | ||
| 947 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir))); | ||
| 948 | WriteSetting(QStringLiteral("load_directory"), | ||
| 949 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)), | ||
| 950 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir))); | ||
| 951 | WriteSetting(QStringLiteral("dump_directory"), | ||
| 952 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)), | ||
| 953 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); | ||
| 954 | WriteSetting(QStringLiteral("tas_directory"), | ||
| 955 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)), | ||
| 956 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir))); | ||
| 957 | |||
| 958 | WriteCategory(Settings::Category::DataStorage); | ||
| 959 | |||
| 960 | qt_config->endGroup(); | ||
| 961 | } | ||
| 962 | |||
| 963 | void Config::SaveDebuggingValues() { | ||
| 964 | qt_config->beginGroup(QStringLiteral("Debugging")); | ||
| 965 | |||
| 966 | // Intentionally not using the QT default setting as this is intended to be changed in the ini | ||
| 967 | qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); | ||
| 968 | |||
| 969 | WriteCategory(Settings::Category::Debugging); | ||
| 970 | WriteCategory(Settings::Category::DebuggingGraphics); | ||
| 971 | |||
| 972 | qt_config->endGroup(); | ||
| 973 | } | ||
| 974 | |||
| 975 | void Config::SaveNetworkValues() { | ||
| 976 | qt_config->beginGroup(QStringLiteral("Services")); | ||
| 977 | |||
| 978 | WriteCategory(Settings::Category::Network); | ||
| 979 | |||
| 980 | qt_config->endGroup(); | ||
| 981 | } | ||
| 982 | |||
| 983 | void Config::SaveDisabledAddOnValues() { | ||
| 984 | qt_config->beginWriteArray(QStringLiteral("DisabledAddOns")); | ||
| 985 | |||
| 986 | int i = 0; | ||
| 987 | for (const auto& elem : Settings::values.disabled_addons) { | ||
| 988 | qt_config->setArrayIndex(i); | ||
| 989 | WriteSetting(QStringLiteral("title_id"), QVariant::fromValue<u64>(elem.first), 0); | ||
| 990 | qt_config->beginWriteArray(QStringLiteral("disabled")); | ||
| 991 | for (std::size_t j = 0; j < elem.second.size(); ++j) { | ||
| 992 | qt_config->setArrayIndex(static_cast<int>(j)); | ||
| 993 | WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), QString{}); | ||
| 994 | } | ||
| 995 | qt_config->endArray(); | ||
| 996 | ++i; | ||
| 997 | } | ||
| 998 | |||
| 999 | qt_config->endArray(); | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | void Config::SaveMiscellaneousValues() { | ||
| 1003 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); | ||
| 1004 | |||
| 1005 | WriteCategory(Settings::Category::Miscellaneous); | ||
| 1006 | |||
| 1007 | qt_config->endGroup(); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | void Config::SavePathValues() { | ||
| 1011 | qt_config->beginGroup(QStringLiteral("Paths")); | ||
| 1012 | |||
| 1013 | WriteSetting(QStringLiteral("romsPath"), UISettings::values.roms_path); | ||
| 1014 | WriteSetting(QStringLiteral("symbolsPath"), UISettings::values.symbols_path); | ||
| 1015 | qt_config->beginWriteArray(QStringLiteral("gamedirs")); | ||
| 1016 | for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) { | ||
| 1017 | qt_config->setArrayIndex(i); | ||
| 1018 | const auto& game_dir = UISettings::values.game_dirs[i]; | ||
| 1019 | WriteSetting(QStringLiteral("path"), game_dir.path); | ||
| 1020 | WriteSetting(QStringLiteral("deep_scan"), game_dir.deep_scan, false); | ||
| 1021 | WriteSetting(QStringLiteral("expanded"), game_dir.expanded, true); | ||
| 1022 | } | ||
| 1023 | qt_config->endArray(); | ||
| 1024 | WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files); | ||
| 1025 | WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{}); | ||
| 1026 | |||
| 1027 | qt_config->endGroup(); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | void Config::SaveCpuValues() { | ||
| 1031 | qt_config->beginGroup(QStringLiteral("Cpu")); | ||
| 1032 | |||
| 1033 | WriteCategory(Settings::Category::Cpu); | ||
| 1034 | WriteCategory(Settings::Category::CpuDebug); | ||
| 1035 | WriteCategory(Settings::Category::CpuUnsafe); | ||
| 1036 | |||
| 1037 | qt_config->endGroup(); | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | void Config::SaveRendererValues() { | ||
| 1041 | qt_config->beginGroup(QStringLiteral("Renderer")); | ||
| 1042 | |||
| 1043 | WriteCategory(Settings::Category::Renderer); | ||
| 1044 | WriteCategory(Settings::Category::RendererAdvanced); | ||
| 1045 | WriteCategory(Settings::Category::RendererDebug); | ||
| 1046 | |||
| 1047 | qt_config->endGroup(); | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | void Config::SaveScreenshotValues() { | ||
| 1051 | qt_config->beginGroup(QStringLiteral("Screenshots")); | ||
| 1052 | |||
| 1053 | WriteSetting(QStringLiteral("screenshot_path"), | ||
| 1054 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir))); | ||
| 1055 | WriteCategory(Settings::Category::Screenshots); | ||
| 1056 | |||
| 1057 | qt_config->endGroup(); | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | void Config::SaveShortcutValues() { | ||
| 1061 | qt_config->beginGroup(QStringLiteral("Shortcuts")); | ||
| 1062 | |||
| 1063 | // Lengths of UISettings::values.shortcuts & default_hotkeys are same. | ||
| 1064 | // However, their ordering must also be the same. | ||
| 1065 | for (std::size_t i = 0; i < default_hotkeys.size(); i++) { | ||
| 1066 | const auto& [name, group, shortcut] = UISettings::values.shortcuts[i]; | ||
| 1067 | const auto& default_hotkey = default_hotkeys[i].shortcut; | ||
| 1068 | |||
| 1069 | qt_config->beginGroup(group); | ||
| 1070 | qt_config->beginGroup(name); | ||
| 1071 | WriteSetting(QStringLiteral("KeySeq"), shortcut.keyseq, default_hotkey.keyseq); | ||
| 1072 | WriteSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq, | ||
| 1073 | default_hotkey.controller_keyseq); | ||
| 1074 | WriteSetting(QStringLiteral("Context"), shortcut.context, default_hotkey.context); | ||
| 1075 | WriteSetting(QStringLiteral("Repeat"), shortcut.repeat, default_hotkey.repeat); | ||
| 1076 | qt_config->endGroup(); | ||
| 1077 | qt_config->endGroup(); | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | qt_config->endGroup(); | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | void Config::SaveSystemValues() { | ||
| 1084 | qt_config->beginGroup(QStringLiteral("System")); | ||
| 1085 | |||
| 1086 | WriteCategory(Settings::Category::System); | ||
| 1087 | WriteCategory(Settings::Category::SystemAudio); | ||
| 1088 | |||
| 1089 | qt_config->endGroup(); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | void Config::SaveUIValues() { | ||
| 1093 | qt_config->beginGroup(QStringLiteral("UI")); | ||
| 1094 | |||
| 1095 | WriteCategory(Settings::Category::Ui); | ||
| 1096 | WriteCategory(Settings::Category::UiGeneral); | ||
| 1097 | |||
| 1098 | WriteSetting(QStringLiteral("theme"), UISettings::values.theme, | ||
| 1099 | QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second)); | ||
| 1100 | |||
| 1101 | SaveUIGamelistValues(); | ||
| 1102 | SaveUILayoutValues(); | ||
| 1103 | SavePathValues(); | ||
| 1104 | SaveScreenshotValues(); | ||
| 1105 | SaveShortcutValues(); | ||
| 1106 | SaveMultiplayerValues(); | ||
| 1107 | |||
| 1108 | qt_config->endGroup(); | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | void Config::SaveUIGamelistValues() { | ||
| 1112 | qt_config->beginGroup(QStringLiteral("UIGameList")); | ||
| 1113 | |||
| 1114 | WriteCategory(Settings::Category::UiGameList); | ||
| 1115 | |||
| 1116 | qt_config->beginWriteArray(QStringLiteral("favorites")); | ||
| 1117 | for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { | ||
| 1118 | qt_config->setArrayIndex(i); | ||
| 1119 | WriteSetting(QStringLiteral("program_id"), | ||
| 1120 | QVariant::fromValue(UISettings::values.favorited_ids[i])); | ||
| 1121 | } | ||
| 1122 | qt_config->endArray(); | ||
| 1123 | |||
| 1124 | qt_config->endGroup(); | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | void Config::SaveUILayoutValues() { | ||
| 1128 | qt_config->beginGroup(QStringLiteral("UILayout")); | ||
| 1129 | |||
| 1130 | WriteSetting(QStringLiteral("geometry"), UISettings::values.geometry); | ||
| 1131 | WriteSetting(QStringLiteral("state"), UISettings::values.state); | ||
| 1132 | WriteSetting(QStringLiteral("geometryRenderWindow"), UISettings::values.renderwindow_geometry); | ||
| 1133 | WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state); | ||
| 1134 | WriteSetting(QStringLiteral("microProfileDialogGeometry"), | ||
| 1135 | UISettings::values.microprofile_geometry); | ||
| 1136 | |||
| 1137 | WriteCategory(Settings::Category::UiLayout); | ||
| 1138 | |||
| 1139 | qt_config->endGroup(); | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | void Config::SaveWebServiceValues() { | ||
| 1143 | qt_config->beginGroup(QStringLiteral("WebService")); | ||
| 1144 | |||
| 1145 | WriteCategory(Settings::Category::WebService); | ||
| 1146 | |||
| 1147 | qt_config->endGroup(); | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | void Config::SaveMultiplayerValues() { | ||
| 1151 | qt_config->beginGroup(QStringLiteral("Multiplayer")); | ||
| 1152 | |||
| 1153 | WriteCategory(Settings::Category::Multiplayer); | ||
| 1154 | |||
| 1155 | // Write ban list | ||
| 1156 | qt_config->beginWriteArray(QStringLiteral("username_ban_list")); | ||
| 1157 | for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.first.size(); ++i) { | ||
| 1158 | qt_config->setArrayIndex(static_cast<int>(i)); | ||
| 1159 | WriteSetting(QStringLiteral("username"), | ||
| 1160 | QString::fromStdString(UISettings::values.multiplayer_ban_list.first[i])); | ||
| 1161 | } | ||
| 1162 | qt_config->endArray(); | ||
| 1163 | qt_config->beginWriteArray(QStringLiteral("ip_ban_list")); | ||
| 1164 | for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.second.size(); ++i) { | ||
| 1165 | qt_config->setArrayIndex(static_cast<int>(i)); | ||
| 1166 | WriteSetting(QStringLiteral("ip"), | ||
| 1167 | QString::fromStdString(UISettings::values.multiplayer_ban_list.second[i])); | ||
| 1168 | } | ||
| 1169 | qt_config->endArray(); | ||
| 1170 | |||
| 1171 | qt_config->endGroup(); | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | QVariant Config::ReadSetting(const QString& name) const { | ||
| 1175 | return qt_config->value(name); | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) const { | ||
| 1179 | QVariant result; | ||
| 1180 | if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { | ||
| 1181 | result = default_value; | ||
| 1182 | } else { | ||
| 1183 | result = qt_config->value(name, default_value); | ||
| 1184 | } | ||
| 1185 | return result; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | void Config::WriteSetting(const QString& name, const QVariant& value) { | ||
| 1189 | qt_config->setValue(name, value); | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | void Config::WriteSetting(const QString& name, const QVariant& value, | ||
| 1193 | const QVariant& default_value) { | ||
| 1194 | qt_config->setValue(name + QStringLiteral("/default"), value == default_value); | ||
| 1195 | qt_config->setValue(name, value); | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | void Config::WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, | ||
| 1199 | bool use_global) { | ||
| 1200 | if (!global) { | ||
| 1201 | qt_config->setValue(name + QStringLiteral("/use_global"), use_global); | ||
| 1202 | } | ||
| 1203 | if (global || !use_global) { | ||
| 1204 | qt_config->setValue(name + QStringLiteral("/default"), value == default_value); | ||
| 1205 | qt_config->setValue(name, value); | ||
| 1206 | } | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | void Config::Reload() { | ||
| 1210 | ReadValues(); | ||
| 1211 | // To apply default value changes | ||
| 1212 | SaveValues(); | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | void Config::Save() { | ||
| 1216 | SaveValues(); | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | void Config::ReadControlPlayerValue(std::size_t player_index) { | ||
| 1220 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 1221 | ReadPlayerValue(player_index); | ||
| 1222 | qt_config->endGroup(); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | void Config::SaveControlPlayerValue(std::size_t player_index) { | ||
| 1226 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 1227 | SavePlayerValue(player_index); | ||
| 1228 | qt_config->endGroup(); | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | void Config::ClearControlPlayerValues() { | ||
| 1232 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 1233 | // If key is an empty string, all keys in the current group() are removed. | ||
| 1234 | qt_config->remove(QString{}); | ||
| 1235 | qt_config->endGroup(); | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | const std::string& Config::GetConfigFilePath() const { | ||
| 1239 | return qt_config_loc; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static auto FindRelevantList(Settings::Category category) { | ||
| 1243 | auto& map = Settings::values.linkage.by_category; | ||
| 1244 | if (map.contains(category)) { | ||
| 1245 | return Settings::values.linkage.by_category[category]; | ||
| 1246 | } | ||
| 1247 | return UISettings::values.linkage.by_category[category]; | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | void Config::ReadCategory(Settings::Category category) { | ||
| 1251 | const auto& settings = FindRelevantList(category); | ||
| 1252 | std::for_each(settings.begin(), settings.end(), | ||
| 1253 | [&](const auto& setting) { ReadSettingGeneric(setting); }); | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | void Config::WriteCategory(Settings::Category category) { | ||
| 1257 | const auto& settings = FindRelevantList(category); | ||
| 1258 | std::for_each(settings.begin(), settings.end(), | ||
| 1259 | [&](const auto& setting) { WriteSettingGeneric(setting); }); | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) { | ||
| 1263 | if (!setting->Save() || (!setting->Switchable() && !global)) { | ||
| 1264 | return; | ||
| 1265 | } | ||
| 1266 | const QString name = QString::fromStdString(setting->GetLabel()); | ||
| 1267 | const auto default_value = | ||
| 1268 | QVariant::fromValue<QString>(QString::fromStdString(setting->DefaultToString())); | ||
| 1269 | |||
| 1270 | bool use_global = true; | ||
| 1271 | if (setting->Switchable() && !global) { | ||
| 1272 | use_global = qt_config->value(name + QStringLiteral("/use_global"), true).value<bool>(); | ||
| 1273 | setting->SetGlobal(use_global); | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | if (global || !use_global) { | ||
| 1277 | const bool is_default = | ||
| 1278 | qt_config->value(name + QStringLiteral("/default"), true).value<bool>(); | ||
| 1279 | if (!is_default) { | ||
| 1280 | setting->LoadString( | ||
| 1281 | qt_config->value(name, default_value).value<QString>().toStdString()); | ||
| 1282 | } else { | ||
| 1283 | // Empty string resets the Setting to default | ||
| 1284 | setting->LoadString(""); | ||
| 1285 | } | ||
| 1286 | } | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | void Config::WriteSettingGeneric(Settings::BasicSetting* const setting) const { | ||
| 1290 | if (!setting->Save()) { | ||
| 1291 | return; | ||
| 1292 | } | ||
| 1293 | const QVariant value = QVariant::fromValue(QString::fromStdString(setting->ToString())); | ||
| 1294 | const QVariant default_value = | ||
| 1295 | QVariant::fromValue(QString::fromStdString(setting->DefaultToString())); | ||
| 1296 | const QString label = QString::fromStdString(setting->GetLabel()); | ||
| 1297 | if (setting->Switchable()) { | ||
| 1298 | if (!global) { | ||
| 1299 | qt_config->setValue(label + QStringLiteral("/use_global"), setting->UsingGlobal()); | ||
| 1300 | } | ||
| 1301 | if (global || !setting->UsingGlobal()) { | ||
| 1302 | qt_config->setValue(label + QStringLiteral("/default"), value == default_value); | ||
| 1303 | qt_config->setValue(label, value); | ||
| 1304 | } | ||
| 1305 | } else if (global) { | ||
| 1306 | qt_config->setValue(label + QStringLiteral("/default"), value == default_value); | ||
| 1307 | qt_config->setValue(label, value); | ||
| 1308 | } | ||
| 1309 | } | ||
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h deleted file mode 100644 index 1589ba057..000000000 --- a/src/yuzu/configuration/config.h +++ /dev/null | |||
| @@ -1,179 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2014 Citra Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | #include <QMetaType> | ||
| 10 | #include <QVariant> | ||
| 11 | #include "common/settings.h" | ||
| 12 | #include "common/settings_enums.h" | ||
| 13 | #include "yuzu/uisettings.h" | ||
| 14 | |||
| 15 | class QSettings; | ||
| 16 | |||
| 17 | namespace Core { | ||
| 18 | class System; | ||
| 19 | } | ||
| 20 | |||
| 21 | class Config { | ||
| 22 | public: | ||
| 23 | enum class ConfigType { | ||
| 24 | GlobalConfig, | ||
| 25 | PerGameConfig, | ||
| 26 | InputProfile, | ||
| 27 | }; | ||
| 28 | |||
| 29 | explicit Config(const std::string& config_name = "qt-config", | ||
| 30 | ConfigType config_type = ConfigType::GlobalConfig); | ||
| 31 | ~Config(); | ||
| 32 | |||
| 33 | void Reload(); | ||
| 34 | void Save(); | ||
| 35 | |||
| 36 | void ReadControlPlayerValue(std::size_t player_index); | ||
| 37 | void SaveControlPlayerValue(std::size_t player_index); | ||
| 38 | void ClearControlPlayerValues(); | ||
| 39 | |||
| 40 | const std::string& GetConfigFilePath() const; | ||
| 41 | |||
| 42 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; | ||
| 43 | static const std::array<int, Settings::NativeMotion::NumMotions> default_motions; | ||
| 44 | static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs; | ||
| 45 | static const std::array<int, 2> default_stick_mod; | ||
| 46 | static const std::array<int, 2> default_ringcon_analogs; | ||
| 47 | static const std::array<int, Settings::NativeMouseButton::NumMouseButtons> | ||
| 48 | default_mouse_buttons; | ||
| 49 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; | ||
| 50 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods; | ||
| 51 | static const std::array<UISettings::Shortcut, 23> default_hotkeys; | ||
| 52 | |||
| 53 | static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map; | ||
| 54 | static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map; | ||
| 55 | static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map; | ||
| 56 | static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map; | ||
| 57 | static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map; | ||
| 58 | static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map; | ||
| 59 | |||
| 60 | static constexpr UISettings::Theme default_theme{ | ||
| 61 | #ifdef _WIN32 | ||
| 62 | UISettings::Theme::DarkColorful | ||
| 63 | #else | ||
| 64 | UISettings::Theme::DefaultColorful | ||
| 65 | #endif | ||
| 66 | }; | ||
| 67 | |||
| 68 | private: | ||
| 69 | void Initialize(const std::string& config_name); | ||
| 70 | bool IsCustomConfig(); | ||
| 71 | |||
| 72 | void ReadValues(); | ||
| 73 | void ReadPlayerValue(std::size_t player_index); | ||
| 74 | void ReadDebugValues(); | ||
| 75 | void ReadKeyboardValues(); | ||
| 76 | void ReadMouseValues(); | ||
| 77 | void ReadTouchscreenValues(); | ||
| 78 | void ReadMotionTouchValues(); | ||
| 79 | void ReadHidbusValues(); | ||
| 80 | void ReadIrCameraValues(); | ||
| 81 | |||
| 82 | // Read functions bases off the respective config section names. | ||
| 83 | void ReadAudioValues(); | ||
| 84 | void ReadControlValues(); | ||
| 85 | void ReadCoreValues(); | ||
| 86 | void ReadDataStorageValues(); | ||
| 87 | void ReadDebuggingValues(); | ||
| 88 | void ReadServiceValues(); | ||
| 89 | void ReadDisabledAddOnValues(); | ||
| 90 | void ReadMiscellaneousValues(); | ||
| 91 | void ReadPathValues(); | ||
| 92 | void ReadCpuValues(); | ||
| 93 | void ReadRendererValues(); | ||
| 94 | void ReadScreenshotValues(); | ||
| 95 | void ReadShortcutValues(); | ||
| 96 | void ReadSystemValues(); | ||
| 97 | void ReadUIValues(); | ||
| 98 | void ReadUIGamelistValues(); | ||
| 99 | void ReadUILayoutValues(); | ||
| 100 | void ReadWebServiceValues(); | ||
| 101 | void ReadMultiplayerValues(); | ||
| 102 | void ReadNetworkValues(); | ||
| 103 | |||
| 104 | void SaveValues(); | ||
| 105 | void SavePlayerValue(std::size_t player_index); | ||
| 106 | void SaveDebugValues(); | ||
| 107 | void SaveMouseValues(); | ||
| 108 | void SaveTouchscreenValues(); | ||
| 109 | void SaveMotionTouchValues(); | ||
| 110 | void SaveHidbusValues(); | ||
| 111 | void SaveIrCameraValues(); | ||
| 112 | |||
| 113 | // Save functions based off the respective config section names. | ||
| 114 | void SaveAudioValues(); | ||
| 115 | void SaveControlValues(); | ||
| 116 | void SaveCoreValues(); | ||
| 117 | void SaveDataStorageValues(); | ||
| 118 | void SaveDebuggingValues(); | ||
| 119 | void SaveNetworkValues(); | ||
| 120 | void SaveDisabledAddOnValues(); | ||
| 121 | void SaveMiscellaneousValues(); | ||
| 122 | void SavePathValues(); | ||
| 123 | void SaveCpuValues(); | ||
| 124 | void SaveRendererValues(); | ||
| 125 | void SaveScreenshotValues(); | ||
| 126 | void SaveShortcutValues(); | ||
| 127 | void SaveSystemValues(); | ||
| 128 | void SaveUIValues(); | ||
| 129 | void SaveUIGamelistValues(); | ||
| 130 | void SaveUILayoutValues(); | ||
| 131 | void SaveWebServiceValues(); | ||
| 132 | void SaveMultiplayerValues(); | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Reads a setting from the qt_config. | ||
| 136 | * | ||
| 137 | * @param name The setting's identifier | ||
| 138 | * @param default_value The value to use when the setting is not already present in the config | ||
| 139 | */ | ||
| 140 | QVariant ReadSetting(const QString& name) const; | ||
| 141 | QVariant ReadSetting(const QString& name, const QVariant& default_value) const; | ||
| 142 | |||
| 143 | /** | ||
| 144 | * Writes a setting to the qt_config. | ||
| 145 | * | ||
| 146 | * @param name The setting's idetentifier | ||
| 147 | * @param value Value of the setting | ||
| 148 | * @param default_value Default of the setting if not present in qt_config | ||
| 149 | * @param use_global Specifies if the custom or global config should be in use, for custom | ||
| 150 | * configs | ||
| 151 | */ | ||
| 152 | void WriteSetting(const QString& name, const QVariant& value); | ||
| 153 | void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); | ||
| 154 | void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, | ||
| 155 | bool use_global); | ||
| 156 | |||
| 157 | void ReadCategory(Settings::Category category); | ||
| 158 | void WriteCategory(Settings::Category category); | ||
| 159 | void ReadSettingGeneric(Settings::BasicSetting* const setting); | ||
| 160 | void WriteSettingGeneric(Settings::BasicSetting* const setting) const; | ||
| 161 | |||
| 162 | const ConfigType type; | ||
| 163 | std::unique_ptr<QSettings> qt_config; | ||
| 164 | std::string qt_config_loc; | ||
| 165 | const bool global; | ||
| 166 | }; | ||
| 167 | |||
| 168 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT | ||
| 169 | Q_DECLARE_METATYPE(Settings::CpuAccuracy); | ||
| 170 | Q_DECLARE_METATYPE(Settings::GpuAccuracy); | ||
| 171 | Q_DECLARE_METATYPE(Settings::FullscreenMode); | ||
| 172 | Q_DECLARE_METATYPE(Settings::NvdecEmulation); | ||
| 173 | Q_DECLARE_METATYPE(Settings::ResolutionSetup); | ||
| 174 | Q_DECLARE_METATYPE(Settings::ScalingFilter); | ||
| 175 | Q_DECLARE_METATYPE(Settings::AntiAliasing); | ||
| 176 | Q_DECLARE_METATYPE(Settings::RendererBackend); | ||
| 177 | Q_DECLARE_METATYPE(Settings::ShaderBackend); | ||
| 178 | Q_DECLARE_METATYPE(Settings::AstcRecompression); | ||
| 179 | Q_DECLARE_METATYPE(Settings::AstcDecodeMode); | ||
diff --git a/src/yuzu/configuration/configure_camera.cpp b/src/yuzu/configuration/configure_camera.cpp index d95e96696..3368f53f3 100644 --- a/src/yuzu/configuration/configure_camera.cpp +++ b/src/yuzu/configuration/configure_camera.cpp | |||
| @@ -10,10 +10,10 @@ | |||
| 10 | #include <QStandardItemModel> | 10 | #include <QStandardItemModel> |
| 11 | #include <QTimer> | 11 | #include <QTimer> |
| 12 | 12 | ||
| 13 | #include "common/settings.h" | ||
| 13 | #include "input_common/drivers/camera.h" | 14 | #include "input_common/drivers/camera.h" |
| 14 | #include "input_common/main.h" | 15 | #include "input_common/main.h" |
| 15 | #include "ui_configure_camera.h" | 16 | #include "ui_configure_camera.h" |
| 16 | #include "yuzu/configuration/config.h" | ||
| 17 | #include "yuzu/configuration/configure_camera.h" | 17 | #include "yuzu/configuration/configure_camera.h" |
| 18 | 18 | ||
| 19 | ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_) | 19 | ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_) |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 0ad95cc02..aab54a1cc 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "ui_configure.h" | 9 | #include "ui_configure.h" |
| 10 | #include "vk_device_info.h" | 10 | #include "vk_device_info.h" |
| 11 | #include "yuzu/configuration/config.h" | ||
| 12 | #include "yuzu/configuration/configure_audio.h" | 11 | #include "yuzu/configuration/configure_audio.h" |
| 13 | #include "yuzu/configuration/configure_cpu.h" | 12 | #include "yuzu/configuration/configure_cpu.h" |
| 14 | #include "yuzu/configuration/configure_debug_tab.h" | 13 | #include "yuzu/configuration/configure_debug_tab.h" |
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index 68e21cd84..76fc33e49 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp | |||
| @@ -9,10 +9,11 @@ | |||
| 9 | #include "core/hid/emulated_controller.h" | 9 | #include "core/hid/emulated_controller.h" |
| 10 | #include "core/hid/hid_core.h" | 10 | #include "core/hid/hid_core.h" |
| 11 | 11 | ||
| 12 | #include "frontend_common/config.h" | ||
| 12 | #include "ui_configure_hotkeys.h" | 13 | #include "ui_configure_hotkeys.h" |
| 13 | #include "yuzu/configuration/config.h" | ||
| 14 | #include "yuzu/configuration/configure_hotkeys.h" | 14 | #include "yuzu/configuration/configure_hotkeys.h" |
| 15 | #include "yuzu/hotkeys.h" | 15 | #include "yuzu/hotkeys.h" |
| 16 | #include "yuzu/uisettings.h" | ||
| 16 | #include "yuzu/util/sequence_dialog/sequence_dialog.h" | 17 | #include "yuzu/util/sequence_dialog/sequence_dialog.h" |
| 17 | 18 | ||
| 18 | constexpr int name_column = 0; | 19 | constexpr int name_column = 0; |
| @@ -62,18 +63,21 @@ ConfigureHotkeys::~ConfigureHotkeys() = default; | |||
| 62 | 63 | ||
| 63 | void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { | 64 | void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { |
| 64 | for (const auto& group : registry.hotkey_groups) { | 65 | for (const auto& group : registry.hotkey_groups) { |
| 66 | QString parent_item_data = QString::fromStdString(group.first); | ||
| 65 | auto* parent_item = | 67 | auto* parent_item = |
| 66 | new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(group.first))); | 68 | new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(parent_item_data))); |
| 67 | parent_item->setEditable(false); | 69 | parent_item->setEditable(false); |
| 68 | parent_item->setData(group.first); | 70 | parent_item->setData(parent_item_data); |
| 69 | for (const auto& hotkey : group.second) { | 71 | for (const auto& hotkey : group.second) { |
| 70 | auto* action = | 72 | QString hotkey_action_data = QString::fromStdString(hotkey.first); |
| 71 | new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(hotkey.first))); | 73 | auto* action = new QStandardItem( |
| 74 | QCoreApplication::translate("Hotkeys", qPrintable(hotkey_action_data))); | ||
| 72 | auto* keyseq = | 75 | auto* keyseq = |
| 73 | new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText)); | 76 | new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText)); |
| 74 | auto* controller_keyseq = new QStandardItem(hotkey.second.controller_keyseq); | 77 | auto* controller_keyseq = |
| 78 | new QStandardItem(QString::fromStdString(hotkey.second.controller_keyseq)); | ||
| 75 | action->setEditable(false); | 79 | action->setEditable(false); |
| 76 | action->setData(hotkey.first); | 80 | action->setData(hotkey_action_data); |
| 77 | keyseq->setEditable(false); | 81 | keyseq->setEditable(false); |
| 78 | controller_keyseq->setEditable(false); | 82 | controller_keyseq->setEditable(false); |
| 79 | parent_item->appendRow({action, keyseq, controller_keyseq}); | 83 | parent_item->appendRow({action, keyseq, controller_keyseq}); |
| @@ -301,13 +305,13 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) { | |||
| 301 | const QStandardItem* controller_keyseq = | 305 | const QStandardItem* controller_keyseq = |
| 302 | parent->child(key_column_id, controller_column); | 306 | parent->child(key_column_id, controller_column); |
| 303 | for (auto& [group, sub_actions] : registry.hotkey_groups) { | 307 | for (auto& [group, sub_actions] : registry.hotkey_groups) { |
| 304 | if (group != parent->data()) | 308 | if (group != parent->data().toString().toStdString()) |
| 305 | continue; | 309 | continue; |
| 306 | for (auto& [action_name, hotkey] : sub_actions) { | 310 | for (auto& [action_name, hotkey] : sub_actions) { |
| 307 | if (action_name != action->data()) | 311 | if (action_name != action->data().toString().toStdString()) |
| 308 | continue; | 312 | continue; |
| 309 | hotkey.keyseq = QKeySequence(keyseq->text()); | 313 | hotkey.keyseq = QKeySequence(keyseq->text()); |
| 310 | hotkey.controller_keyseq = controller_keyseq->text(); | 314 | hotkey.controller_keyseq = controller_keyseq->text().toStdString(); |
| 311 | } | 315 | } |
| 312 | } | 316 | } |
| 313 | } | 317 | } |
| @@ -319,7 +323,7 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) { | |||
| 319 | void ConfigureHotkeys::RestoreDefaults() { | 323 | void ConfigureHotkeys::RestoreDefaults() { |
| 320 | for (int r = 0; r < model->rowCount(); ++r) { | 324 | for (int r = 0; r < model->rowCount(); ++r) { |
| 321 | const QStandardItem* parent = model->item(r, 0); | 325 | const QStandardItem* parent = model->item(r, 0); |
| 322 | const int hotkey_size = static_cast<int>(Config::default_hotkeys.size()); | 326 | const int hotkey_size = static_cast<int>(UISettings::default_hotkeys.size()); |
| 323 | 327 | ||
| 324 | if (hotkey_size != parent->rowCount()) { | 328 | if (hotkey_size != parent->rowCount()) { |
| 325 | QMessageBox::warning(this, tr("Invalid hotkey settings"), | 329 | QMessageBox::warning(this, tr("Invalid hotkey settings"), |
| @@ -330,10 +334,11 @@ void ConfigureHotkeys::RestoreDefaults() { | |||
| 330 | for (int r2 = 0; r2 < parent->rowCount(); ++r2) { | 334 | for (int r2 = 0; r2 < parent->rowCount(); ++r2) { |
| 331 | model->item(r, 0) | 335 | model->item(r, 0) |
| 332 | ->child(r2, hotkey_column) | 336 | ->child(r2, hotkey_column) |
| 333 | ->setText(Config::default_hotkeys[r2].shortcut.keyseq); | 337 | ->setText(QString::fromStdString(UISettings::default_hotkeys[r2].shortcut.keyseq)); |
| 334 | model->item(r, 0) | 338 | model->item(r, 0) |
| 335 | ->child(r2, controller_column) | 339 | ->child(r2, controller_column) |
| 336 | ->setText(Config::default_hotkeys[r2].shortcut.controller_keyseq); | 340 | ->setText(QString::fromStdString( |
| 341 | UISettings::default_hotkeys[r2].shortcut.controller_keyseq)); | ||
| 337 | } | 342 | } |
| 338 | } | 343 | } |
| 339 | } | 344 | } |
| @@ -379,7 +384,7 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) { | |||
| 379 | 384 | ||
| 380 | void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) { | 385 | void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) { |
| 381 | const QString& default_key_sequence = | 386 | const QString& default_key_sequence = |
| 382 | Config::default_hotkeys[index.row()].shortcut.controller_keyseq; | 387 | QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.controller_keyseq); |
| 383 | const auto [key_sequence_used, used_action] = IsUsedControllerKey(default_key_sequence); | 388 | const auto [key_sequence_used, used_action] = IsUsedControllerKey(default_key_sequence); |
| 384 | 389 | ||
| 385 | if (key_sequence_used && default_key_sequence != model->data(index).toString()) { | 390 | if (key_sequence_used && default_key_sequence != model->data(index).toString()) { |
| @@ -393,7 +398,8 @@ void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) { | |||
| 393 | 398 | ||
| 394 | void ConfigureHotkeys::RestoreHotkey(QModelIndex index) { | 399 | void ConfigureHotkeys::RestoreHotkey(QModelIndex index) { |
| 395 | const QKeySequence& default_key_sequence = QKeySequence::fromString( | 400 | const QKeySequence& default_key_sequence = QKeySequence::fromString( |
| 396 | Config::default_hotkeys[index.row()].shortcut.keyseq, QKeySequence::NativeText); | 401 | QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.keyseq), |
| 402 | QKeySequence::NativeText); | ||
| 397 | const auto [key_sequence_used, used_action] = IsUsedKey(default_key_sequence); | 403 | const auto [key_sequence_used, used_action] = IsUsedKey(default_key_sequence); |
| 398 | 404 | ||
| 399 | if (key_sequence_used && default_key_sequence != QKeySequence(model->data(index).toString())) { | 405 | if (key_sequence_used && default_key_sequence != QKeySequence(model->data(index).toString())) { |
diff --git a/src/yuzu/configuration/configure_input_per_game.cpp b/src/yuzu/configuration/configure_input_per_game.cpp index 78e65d468..8d9f65a05 100644 --- a/src/yuzu/configuration/configure_input_per_game.cpp +++ b/src/yuzu/configuration/configure_input_per_game.cpp | |||
| @@ -5,12 +5,12 @@ | |||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hid/emulated_controller.h" | 6 | #include "core/hid/emulated_controller.h" |
| 7 | #include "core/hid/hid_core.h" | 7 | #include "core/hid/hid_core.h" |
| 8 | #include "frontend_common/config.h" | ||
| 8 | #include "ui_configure_input_per_game.h" | 9 | #include "ui_configure_input_per_game.h" |
| 9 | #include "yuzu/configuration/config.h" | ||
| 10 | #include "yuzu/configuration/configure_input_per_game.h" | 10 | #include "yuzu/configuration/configure_input_per_game.h" |
| 11 | #include "yuzu/configuration/input_profiles.h" | 11 | #include "yuzu/configuration/input_profiles.h" |
| 12 | 12 | ||
| 13 | ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, Config* config_, | 13 | ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, QtConfig* config_, |
| 14 | QWidget* parent) | 14 | QWidget* parent) |
| 15 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPerGame>()), | 15 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPerGame>()), |
| 16 | profiles(std::make_unique<InputProfiles>()), system{system_}, config{config_} { | 16 | profiles(std::make_unique<InputProfiles>()), system{system_}, config{config_} { |
| @@ -110,6 +110,6 @@ void ConfigureInputPerGame::SaveConfiguration() { | |||
| 110 | // Clear all controls from the config in case the user reverted back to globals | 110 | // Clear all controls from the config in case the user reverted back to globals |
| 111 | config->ClearControlPlayerValues(); | 111 | config->ClearControlPlayerValues(); |
| 112 | for (size_t index = 0; index < Settings::values.players.GetValue().size(); ++index) { | 112 | for (size_t index = 0; index < Settings::values.players.GetValue().size(); ++index) { |
| 113 | config->SaveControlPlayerValue(index); | 113 | config->SaveQtControlPlayerValues(index); |
| 114 | } | 114 | } |
| 115 | } | 115 | } |
diff --git a/src/yuzu/configuration/configure_input_per_game.h b/src/yuzu/configuration/configure_input_per_game.h index 660faf574..4420e856c 100644 --- a/src/yuzu/configuration/configure_input_per_game.h +++ b/src/yuzu/configuration/configure_input_per_game.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include "ui_configure_input_per_game.h" | 10 | #include "ui_configure_input_per_game.h" |
| 11 | #include "yuzu/configuration/input_profiles.h" | 11 | #include "yuzu/configuration/input_profiles.h" |
| 12 | #include "yuzu/configuration/qt_config.h" | ||
| 12 | 13 | ||
| 13 | class QComboBox; | 14 | class QComboBox; |
| 14 | 15 | ||
| @@ -22,7 +23,7 @@ class ConfigureInputPerGame : public QWidget { | |||
| 22 | Q_OBJECT | 23 | Q_OBJECT |
| 23 | 24 | ||
| 24 | public: | 25 | public: |
| 25 | explicit ConfigureInputPerGame(Core::System& system_, Config* config_, | 26 | explicit ConfigureInputPerGame(Core::System& system_, QtConfig* config_, |
| 26 | QWidget* parent = nullptr); | 27 | QWidget* parent = nullptr); |
| 27 | 28 | ||
| 28 | /// Load and Save configurations to settings file. | 29 | /// Load and Save configurations to settings file. |
| @@ -41,5 +42,5 @@ private: | |||
| 41 | std::array<QComboBox*, 8> profile_comboboxes; | 42 | std::array<QComboBox*, 8> profile_comboboxes; |
| 42 | 43 | ||
| 43 | Core::System& system; | 44 | Core::System& system; |
| 44 | Config* config; | 45 | QtConfig* config; |
| 45 | }; | 46 | }; |
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 9259e2a5d..0f7b3714e 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -12,15 +12,16 @@ | |||
| 12 | #include <QTimer> | 12 | #include <QTimer> |
| 13 | #include "common/assert.h" | 13 | #include "common/assert.h" |
| 14 | #include "common/param_package.h" | 14 | #include "common/param_package.h" |
| 15 | #include "configuration/qt_config.h" | ||
| 15 | #include "core/hid/emulated_controller.h" | 16 | #include "core/hid/emulated_controller.h" |
| 16 | #include "core/hid/hid_core.h" | 17 | #include "core/hid/hid_core.h" |
| 17 | #include "core/hid/hid_types.h" | 18 | #include "core/hid/hid_types.h" |
| 19 | #include "frontend_common/config.h" | ||
| 18 | #include "input_common/drivers/keyboard.h" | 20 | #include "input_common/drivers/keyboard.h" |
| 19 | #include "input_common/drivers/mouse.h" | 21 | #include "input_common/drivers/mouse.h" |
| 20 | #include "input_common/main.h" | 22 | #include "input_common/main.h" |
| 21 | #include "ui_configure_input_player.h" | 23 | #include "ui_configure_input_player.h" |
| 22 | #include "yuzu/bootmanager.h" | 24 | #include "yuzu/bootmanager.h" |
| 23 | #include "yuzu/configuration/config.h" | ||
| 24 | #include "yuzu/configuration/configure_input_player.h" | 25 | #include "yuzu/configuration/configure_input_player.h" |
| 25 | #include "yuzu/configuration/configure_input_player_widget.h" | 26 | #include "yuzu/configuration/configure_input_player_widget.h" |
| 26 | #include "yuzu/configuration/configure_mouse_panning.h" | 27 | #include "yuzu/configuration/configure_mouse_panning.h" |
| @@ -1397,25 +1398,25 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { | |||
| 1397 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | 1398 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { |
| 1398 | emulated_controller->SetButtonParam( | 1399 | emulated_controller->SetButtonParam( |
| 1399 | button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( | 1400 | button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( |
| 1400 | Config::default_buttons[button_id])}); | 1401 | QtConfig::default_buttons[button_id])}); |
| 1401 | } | 1402 | } |
| 1402 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | 1403 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { |
| 1403 | Common::ParamPackage analog_param{}; | 1404 | Common::ParamPackage analog_param{}; |
| 1404 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | 1405 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { |
| 1405 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | 1406 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( |
| 1406 | Config::default_analogs[analog_id][sub_button_id])}; | 1407 | QtConfig::default_analogs[analog_id][sub_button_id])}; |
| 1407 | SetAnalogParam(params, analog_param, analog_sub_buttons[sub_button_id]); | 1408 | SetAnalogParam(params, analog_param, analog_sub_buttons[sub_button_id]); |
| 1408 | } | 1409 | } |
| 1409 | 1410 | ||
| 1410 | analog_param.Set("modifier", InputCommon::GenerateKeyboardParam( | 1411 | analog_param.Set("modifier", InputCommon::GenerateKeyboardParam( |
| 1411 | Config::default_stick_mod[analog_id])); | 1412 | QtConfig::default_stick_mod[analog_id])); |
| 1412 | emulated_controller->SetStickParam(analog_id, analog_param); | 1413 | emulated_controller->SetStickParam(analog_id, analog_param); |
| 1413 | } | 1414 | } |
| 1414 | 1415 | ||
| 1415 | for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { | 1416 | for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { |
| 1416 | emulated_controller->SetMotionParam( | 1417 | emulated_controller->SetMotionParam( |
| 1417 | motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( | 1418 | motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( |
| 1418 | Config::default_motions[motion_id])}); | 1419 | QtConfig::default_motions[motion_id])}); |
| 1419 | } | 1420 | } |
| 1420 | 1421 | ||
| 1421 | // If mouse is selected we want to override with mappings from the driver | 1422 | // If mouse is selected we want to override with mappings from the driver |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index b91d6ad4a..b274a3321 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -25,8 +25,8 @@ | |||
| 25 | #include "core/file_sys/patch_manager.h" | 25 | #include "core/file_sys/patch_manager.h" |
| 26 | #include "core/file_sys/xts_archive.h" | 26 | #include "core/file_sys/xts_archive.h" |
| 27 | #include "core/loader/loader.h" | 27 | #include "core/loader/loader.h" |
| 28 | #include "frontend_common/config.h" | ||
| 28 | #include "ui_configure_per_game.h" | 29 | #include "ui_configure_per_game.h" |
| 29 | #include "yuzu/configuration/config.h" | ||
| 30 | #include "yuzu/configuration/configuration_shared.h" | 30 | #include "yuzu/configuration/configuration_shared.h" |
| 31 | #include "yuzu/configuration/configure_audio.h" | 31 | #include "yuzu/configuration/configure_audio.h" |
| 32 | #include "yuzu/configuration/configure_cpu.h" | 32 | #include "yuzu/configuration/configure_cpu.h" |
| @@ -50,8 +50,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st | |||
| 50 | const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name)); | 50 | const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name)); |
| 51 | const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) | 51 | const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) |
| 52 | : fmt::format("{:016X}", title_id); | 52 | : fmt::format("{:016X}", title_id); |
| 53 | game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig); | 53 | game_config = std::make_unique<QtConfig>(config_file_name, Config::ConfigType::PerGameConfig); |
| 54 | |||
| 55 | addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this); | 54 | addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this); |
| 56 | audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, *builder, this); | 55 | audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, *builder, this); |
| 57 | cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, *builder, this); | 56 | cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, *builder, this); |
| @@ -108,7 +107,7 @@ void ConfigurePerGame::ApplyConfiguration() { | |||
| 108 | system.ApplySettings(); | 107 | system.ApplySettings(); |
| 109 | Settings::LogSettings(); | 108 | Settings::LogSettings(); |
| 110 | 109 | ||
| 111 | game_config->Save(); | 110 | game_config->SaveAllValues(); |
| 112 | } | 111 | } |
| 113 | 112 | ||
| 114 | void ConfigurePerGame::changeEvent(QEvent* event) { | 113 | void ConfigurePerGame::changeEvent(QEvent* event) { |
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index cc2513001..c8ee46c04 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h | |||
| @@ -12,9 +12,10 @@ | |||
| 12 | 12 | ||
| 13 | #include "configuration/shared_widget.h" | 13 | #include "configuration/shared_widget.h" |
| 14 | #include "core/file_sys/vfs_types.h" | 14 | #include "core/file_sys/vfs_types.h" |
| 15 | #include "frontend_common/config.h" | ||
| 15 | #include "vk_device_info.h" | 16 | #include "vk_device_info.h" |
| 16 | #include "yuzu/configuration/config.h" | ||
| 17 | #include "yuzu/configuration/configuration_shared.h" | 17 | #include "yuzu/configuration/configuration_shared.h" |
| 18 | #include "yuzu/configuration/qt_config.h" | ||
| 18 | #include "yuzu/configuration/shared_translation.h" | 19 | #include "yuzu/configuration/shared_translation.h" |
| 19 | 20 | ||
| 20 | namespace Core { | 21 | namespace Core { |
| @@ -72,7 +73,7 @@ private: | |||
| 72 | 73 | ||
| 73 | QGraphicsScene* scene; | 74 | QGraphicsScene* scene; |
| 74 | 75 | ||
| 75 | std::unique_ptr<Config> game_config; | 76 | std::unique_ptr<QtConfig> game_config; |
| 76 | 77 | ||
| 77 | Core::System& system; | 78 | Core::System& system; |
| 78 | std::unique_ptr<ConfigurationShared::Builder> builder; | 79 | std::unique_ptr<ConfigurationShared::Builder> builder; |
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 674a75a62..140a7fe5d 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #include "core/file_sys/xts_archive.h" | 19 | #include "core/file_sys/xts_archive.h" |
| 20 | #include "core/loader/loader.h" | 20 | #include "core/loader/loader.h" |
| 21 | #include "ui_configure_per_game_addons.h" | 21 | #include "ui_configure_per_game_addons.h" |
| 22 | #include "yuzu/configuration/config.h" | ||
| 23 | #include "yuzu/configuration/configure_input.h" | 22 | #include "yuzu/configuration/configure_input.h" |
| 24 | #include "yuzu/configuration/configure_per_game_addons.h" | 23 | #include "yuzu/configuration/configure_per_game_addons.h" |
| 25 | #include "yuzu/uisettings.h" | 24 | #include "yuzu/uisettings.h" |
diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp index f83705544..9572ff43c 100644 --- a/src/yuzu/configuration/configure_ringcon.cpp +++ b/src/yuzu/configuration/configure_ringcon.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <QTimer> | 8 | #include <QTimer> |
| 9 | #include <fmt/format.h> | 9 | #include <fmt/format.h> |
| 10 | 10 | ||
| 11 | #include "configuration/qt_config.h" | ||
| 11 | #include "core/hid/emulated_controller.h" | 12 | #include "core/hid/emulated_controller.h" |
| 12 | #include "core/hid/hid_core.h" | 13 | #include "core/hid/hid_core.h" |
| 13 | #include "input_common/drivers/keyboard.h" | 14 | #include "input_common/drivers/keyboard.h" |
| @@ -15,7 +16,6 @@ | |||
| 15 | #include "input_common/main.h" | 16 | #include "input_common/main.h" |
| 16 | #include "ui_configure_ringcon.h" | 17 | #include "ui_configure_ringcon.h" |
| 17 | #include "yuzu/bootmanager.h" | 18 | #include "yuzu/bootmanager.h" |
| 18 | #include "yuzu/configuration/config.h" | ||
| 19 | #include "yuzu/configuration/configure_ringcon.h" | 19 | #include "yuzu/configuration/configure_ringcon.h" |
| 20 | 20 | ||
| 21 | const std::array<std::string, ConfigureRingController::ANALOG_SUB_BUTTONS_NUM> | 21 | const std::array<std::string, ConfigureRingController::ANALOG_SUB_BUTTONS_NUM> |
| @@ -270,7 +270,7 @@ void ConfigureRingController::LoadConfiguration() { | |||
| 270 | 270 | ||
| 271 | void ConfigureRingController::RestoreDefaults() { | 271 | void ConfigureRingController::RestoreDefaults() { |
| 272 | const std::string default_ring_string = InputCommon::GenerateAnalogParamFromKeys( | 272 | const std::string default_ring_string = InputCommon::GenerateAnalogParamFromKeys( |
| 273 | 0, 0, Config::default_ringcon_analogs[0], Config::default_ringcon_analogs[1], 0, 0.05f); | 273 | 0, 0, QtConfig::default_ringcon_analogs[0], QtConfig::default_ringcon_analogs[1], 0, 0.05f); |
| 274 | emulated_controller->SetRingParam(Common::ParamPackage(default_ring_string)); | 274 | emulated_controller->SetRingParam(Common::ParamPackage(default_ring_string)); |
| 275 | UpdateUI(); | 275 | UpdateUI(); |
| 276 | } | 276 | } |
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 0c8e5c8b4..7cbf43775 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include "core/core.h" | 16 | #include "core/core.h" |
| 17 | #include "core/hle/service/time/time_manager.h" | 17 | #include "core/hle/service/time/time_manager.h" |
| 18 | #include "ui_configure_system.h" | 18 | #include "ui_configure_system.h" |
| 19 | #include "yuzu/configuration/config.h" | ||
| 20 | #include "yuzu/configuration/configuration_shared.h" | 19 | #include "yuzu/configuration/configuration_shared.h" |
| 21 | #include "yuzu/configuration/configure_system.h" | 20 | #include "yuzu/configuration/configure_system.h" |
| 22 | #include "yuzu/configuration/shared_widget.h" | 21 | #include "yuzu/configuration/shared_widget.h" |
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp index 5a03e48df..94df6d9d3 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp +++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <memory> | 4 | #include <memory> |
| 5 | #include "common/settings.h" | ||
| 5 | #include "ui_configure_touchscreen_advanced.h" | 6 | #include "ui_configure_touchscreen_advanced.h" |
| 6 | #include "yuzu/configuration/config.h" | ||
| 7 | #include "yuzu/configuration/configure_touchscreen_advanced.h" | 7 | #include "yuzu/configuration/configure_touchscreen_advanced.h" |
| 8 | 8 | ||
| 9 | ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent) | 9 | ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent) |
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 82f3b6e78..dd43f0a0e 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp | |||
| @@ -164,7 +164,7 @@ ConfigureUi::~ConfigureUi() = default; | |||
| 164 | 164 | ||
| 165 | void ConfigureUi::ApplyConfiguration() { | 165 | void ConfigureUi::ApplyConfiguration() { |
| 166 | UISettings::values.theme = | 166 | UISettings::values.theme = |
| 167 | ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); | 167 | ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString().toStdString(); |
| 168 | UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); | 168 | UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); |
| 169 | UISettings::values.show_compat = ui->show_compat->isChecked(); | 169 | UISettings::values.show_compat = ui->show_compat->isChecked(); |
| 170 | UISettings::values.show_size = ui->show_size->isChecked(); | 170 | UISettings::values.show_size = ui->show_size->isChecked(); |
| @@ -191,9 +191,10 @@ void ConfigureUi::RequestGameListUpdate() { | |||
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | void ConfigureUi::SetConfiguration() { | 193 | void ConfigureUi::SetConfiguration() { |
| 194 | ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); | 194 | ui->theme_combobox->setCurrentIndex( |
| 195 | ui->theme_combobox->findData(QString::fromStdString(UISettings::values.theme))); | ||
| 195 | ui->language_combobox->setCurrentIndex( | 196 | ui->language_combobox->setCurrentIndex( |
| 196 | ui->language_combobox->findData(UISettings::values.language)); | 197 | ui->language_combobox->findData(QString::fromStdString(UISettings::values.language))); |
| 197 | ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue()); | 198 | ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue()); |
| 198 | ui->show_compat->setChecked(UISettings::values.show_compat.GetValue()); | 199 | ui->show_compat->setChecked(UISettings::values.show_compat.GetValue()); |
| 199 | ui->show_size->setChecked(UISettings::values.show_size.GetValue()); | 200 | ui->show_size->setChecked(UISettings::values.show_size.GetValue()); |
diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp index 41ef4250a..716efbccd 100644 --- a/src/yuzu/configuration/input_profiles.cpp +++ b/src/yuzu/configuration/input_profiles.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "common/fs/fs.h" | 6 | #include "common/fs/fs.h" |
| 7 | #include "common/fs/path_util.h" | 7 | #include "common/fs/path_util.h" |
| 8 | #include "yuzu/configuration/config.h" | 8 | #include "frontend_common/config.h" |
| 9 | #include "yuzu/configuration/input_profiles.h" | 9 | #include "yuzu/configuration/input_profiles.h" |
| 10 | 10 | ||
| 11 | namespace FS = Common::FS; | 11 | namespace FS = Common::FS; |
| @@ -44,7 +44,7 @@ InputProfiles::InputProfiles() { | |||
| 44 | if (IsINI(filename) && IsProfileNameValid(name_without_ext)) { | 44 | if (IsINI(filename) && IsProfileNameValid(name_without_ext)) { |
| 45 | map_profiles.insert_or_assign( | 45 | map_profiles.insert_or_assign( |
| 46 | name_without_ext, | 46 | name_without_ext, |
| 47 | std::make_unique<Config>(name_without_ext, Config::ConfigType::InputProfile)); | 47 | std::make_unique<QtConfig>(name_without_ext, Config::ConfigType::InputProfile)); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | return true; | 50 | return true; |
| @@ -85,7 +85,7 @@ bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t p | |||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | map_profiles.insert_or_assign( | 87 | map_profiles.insert_or_assign( |
| 88 | profile_name, std::make_unique<Config>(profile_name, Config::ConfigType::InputProfile)); | 88 | profile_name, std::make_unique<QtConfig>(profile_name, Config::ConfigType::InputProfile)); |
| 89 | 89 | ||
| 90 | return SaveProfile(profile_name, player_index); | 90 | return SaveProfile(profile_name, player_index); |
| 91 | } | 91 | } |
| @@ -113,7 +113,7 @@ bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t pla | |||
| 113 | return false; | 113 | return false; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | map_profiles[profile_name]->ReadControlPlayerValue(player_index); | 116 | map_profiles[profile_name]->ReadQtControlPlayerValues(player_index); |
| 117 | return true; | 117 | return true; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| @@ -122,7 +122,7 @@ bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t pla | |||
| 122 | return false; | 122 | return false; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | map_profiles[profile_name]->SaveControlPlayerValue(player_index); | 125 | map_profiles[profile_name]->SaveQtControlPlayerValues(player_index); |
| 126 | return true; | 126 | return true; |
| 127 | } | 127 | } |
| 128 | 128 | ||
diff --git a/src/yuzu/configuration/input_profiles.h b/src/yuzu/configuration/input_profiles.h index 2bf3e4250..023ec74a6 100644 --- a/src/yuzu/configuration/input_profiles.h +++ b/src/yuzu/configuration/input_profiles.h | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | #include <string> | 6 | #include <string> |
| 7 | #include <unordered_map> | 7 | #include <unordered_map> |
| 8 | 8 | ||
| 9 | #include "configuration/qt_config.h" | ||
| 10 | |||
| 9 | namespace Core { | 11 | namespace Core { |
| 10 | class System; | 12 | class System; |
| 11 | } | 13 | } |
| @@ -30,5 +32,5 @@ public: | |||
| 30 | private: | 32 | private: |
| 31 | bool ProfileExistsInMap(const std::string& profile_name) const; | 33 | bool ProfileExistsInMap(const std::string& profile_name) const; |
| 32 | 34 | ||
| 33 | std::unordered_map<std::string, std::unique_ptr<Config>> map_profiles; | 35 | std::unordered_map<std::string, std::unique_ptr<QtConfig>> map_profiles; |
| 34 | }; | 36 | }; |
diff --git a/src/yuzu/configuration/qt_config.cpp b/src/yuzu/configuration/qt_config.cpp new file mode 100644 index 000000000..5a8e69aa9 --- /dev/null +++ b/src/yuzu/configuration/qt_config.cpp | |||
| @@ -0,0 +1,549 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "input_common/main.h" | ||
| 5 | #include "qt_config.h" | ||
| 6 | #include "uisettings.h" | ||
| 7 | |||
| 8 | const std::array<int, Settings::NativeButton::NumButtons> QtConfig::default_buttons = { | ||
| 9 | Qt::Key_C, Qt::Key_X, Qt::Key_V, Qt::Key_Z, Qt::Key_F, | ||
| 10 | Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T, | ||
| 11 | Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, | ||
| 12 | Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0, | ||
| 13 | Qt::Key_Q, Qt::Key_E, | ||
| 14 | }; | ||
| 15 | |||
| 16 | const std::array<int, Settings::NativeMotion::NumMotions> QtConfig::default_motions = { | ||
| 17 | Qt::Key_7, | ||
| 18 | Qt::Key_8, | ||
| 19 | }; | ||
| 20 | |||
| 21 | const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> QtConfig::default_analogs{{ | ||
| 22 | { | ||
| 23 | Qt::Key_W, | ||
| 24 | Qt::Key_S, | ||
| 25 | Qt::Key_A, | ||
| 26 | Qt::Key_D, | ||
| 27 | }, | ||
| 28 | { | ||
| 29 | Qt::Key_I, | ||
| 30 | Qt::Key_K, | ||
| 31 | Qt::Key_J, | ||
| 32 | Qt::Key_L, | ||
| 33 | }, | ||
| 34 | }}; | ||
| 35 | |||
| 36 | const std::array<int, 2> QtConfig::default_stick_mod = { | ||
| 37 | Qt::Key_Shift, | ||
| 38 | 0, | ||
| 39 | }; | ||
| 40 | |||
| 41 | const std::array<int, 2> QtConfig::default_ringcon_analogs{{ | ||
| 42 | Qt::Key_A, | ||
| 43 | Qt::Key_D, | ||
| 44 | }}; | ||
| 45 | |||
| 46 | QtConfig::QtConfig(const std::string& config_name, const ConfigType config_type) | ||
| 47 | : Config(config_type) { | ||
| 48 | Initialize(config_name); | ||
| 49 | if (config_type != ConfigType::InputProfile) { | ||
| 50 | ReadQtValues(); | ||
| 51 | SaveQtValues(); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | QtConfig::~QtConfig() { | ||
| 56 | if (global) { | ||
| 57 | QtConfig::SaveAllValues(); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | void QtConfig::ReloadAllValues() { | ||
| 62 | Reload(); | ||
| 63 | ReadQtValues(); | ||
| 64 | SaveQtValues(); | ||
| 65 | } | ||
| 66 | |||
| 67 | void QtConfig::SaveAllValues() { | ||
| 68 | Save(); | ||
| 69 | SaveQtValues(); | ||
| 70 | } | ||
| 71 | |||
| 72 | void QtConfig::ReadQtValues() { | ||
| 73 | if (global) { | ||
| 74 | ReadUIValues(); | ||
| 75 | } | ||
| 76 | ReadQtControlValues(); | ||
| 77 | } | ||
| 78 | |||
| 79 | void QtConfig::ReadQtPlayerValues(const std::size_t player_index) { | ||
| 80 | std::string player_prefix; | ||
| 81 | if (type != ConfigType::InputProfile) { | ||
| 82 | player_prefix.append("player_").append(ToString(player_index)).append("_"); | ||
| 83 | } | ||
| 84 | |||
| 85 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 86 | if (IsCustomConfig()) { | ||
| 87 | const auto profile_name = | ||
| 88 | ReadStringSetting(std::string(player_prefix).append("profile_name")); | ||
| 89 | if (profile_name.empty()) { | ||
| 90 | // Use the global input config | ||
| 91 | player = Settings::values.players.GetValue(true)[player_index]; | ||
| 92 | return; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 97 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 98 | auto& player_buttons = player.buttons[i]; | ||
| 99 | |||
| 100 | player_buttons = ReadStringSetting( | ||
| 101 | std::string(player_prefix).append(Settings::NativeButton::mapping[i]), default_param); | ||
| 102 | if (player_buttons.empty()) { | ||
| 103 | player_buttons = default_param; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 108 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 109 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 110 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 111 | auto& player_analogs = player.analogs[i]; | ||
| 112 | |||
| 113 | player_analogs = ReadStringSetting( | ||
| 114 | std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), default_param); | ||
| 115 | if (player_analogs.empty()) { | ||
| 116 | player_analogs = default_param; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | ||
| 121 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); | ||
| 122 | auto& player_motions = player.motions[i]; | ||
| 123 | |||
| 124 | player_motions = ReadStringSetting( | ||
| 125 | std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), default_param); | ||
| 126 | if (player_motions.empty()) { | ||
| 127 | player_motions = default_param; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | void QtConfig::ReadHidbusValues() { | ||
| 133 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 134 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); | ||
| 135 | auto& ringcon_analogs = Settings::values.ringcon_analogs; | ||
| 136 | |||
| 137 | ringcon_analogs = ReadStringSetting(std::string("ring_controller"), default_param); | ||
| 138 | if (ringcon_analogs.empty()) { | ||
| 139 | ringcon_analogs = default_param; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | void QtConfig::ReadDebugControlValues() { | ||
| 144 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 145 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 146 | auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; | ||
| 147 | |||
| 148 | debug_pad_buttons = ReadStringSetting( | ||
| 149 | std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), default_param); | ||
| 150 | if (debug_pad_buttons.empty()) { | ||
| 151 | debug_pad_buttons = default_param; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 156 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 157 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 158 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 159 | auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; | ||
| 160 | |||
| 161 | debug_pad_analogs = ReadStringSetting( | ||
| 162 | std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), default_param); | ||
| 163 | if (debug_pad_analogs.empty()) { | ||
| 164 | debug_pad_analogs = default_param; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | void QtConfig::ReadQtControlValues() { | ||
| 170 | BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); | ||
| 171 | |||
| 172 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 173 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | ||
| 174 | ReadQtPlayerValues(p); | ||
| 175 | } | ||
| 176 | if (IsCustomConfig()) { | ||
| 177 | EndGroup(); | ||
| 178 | return; | ||
| 179 | } | ||
| 180 | ReadDebugControlValues(); | ||
| 181 | ReadHidbusValues(); | ||
| 182 | |||
| 183 | EndGroup(); | ||
| 184 | } | ||
| 185 | |||
| 186 | void QtConfig::ReadPathValues() { | ||
| 187 | BeginGroup(Settings::TranslateCategory(Settings::Category::Paths)); | ||
| 188 | |||
| 189 | UISettings::values.roms_path = ReadStringSetting(std::string("romsPath")); | ||
| 190 | UISettings::values.symbols_path = ReadStringSetting(std::string("symbolsPath")); | ||
| 191 | UISettings::values.game_dir_deprecated = | ||
| 192 | ReadStringSetting(std::string("gameListRootDir"), std::string(".")); | ||
| 193 | UISettings::values.game_dir_deprecated_deepscan = | ||
| 194 | ReadBooleanSetting(std::string("gameListDeepScan"), std::make_optional(false)); | ||
| 195 | |||
| 196 | const int gamedirs_size = BeginArray(std::string("gamedirs")); | ||
| 197 | for (int i = 0; i < gamedirs_size; ++i) { | ||
| 198 | SetArrayIndex(i); | ||
| 199 | UISettings::GameDir game_dir; | ||
| 200 | game_dir.path = ReadStringSetting(std::string("path")); | ||
| 201 | game_dir.deep_scan = | ||
| 202 | ReadBooleanSetting(std::string("deep_scan"), std::make_optional(false)); | ||
| 203 | game_dir.expanded = ReadBooleanSetting(std::string("expanded"), std::make_optional(true)); | ||
| 204 | UISettings::values.game_dirs.append(game_dir); | ||
| 205 | } | ||
| 206 | EndArray(); | ||
| 207 | |||
| 208 | // Create NAND and SD card directories if empty, these are not removable through the UI, | ||
| 209 | // also carries over old game list settings if present | ||
| 210 | if (UISettings::values.game_dirs.empty()) { | ||
| 211 | UISettings::GameDir game_dir; | ||
| 212 | game_dir.path = std::string("SDMC"); | ||
| 213 | game_dir.expanded = true; | ||
| 214 | UISettings::values.game_dirs.append(game_dir); | ||
| 215 | game_dir.path = std::string("UserNAND"); | ||
| 216 | UISettings::values.game_dirs.append(game_dir); | ||
| 217 | game_dir.path = std::string("SysNAND"); | ||
| 218 | UISettings::values.game_dirs.append(game_dir); | ||
| 219 | if (UISettings::values.game_dir_deprecated != std::string(".")) { | ||
| 220 | game_dir.path = UISettings::values.game_dir_deprecated; | ||
| 221 | game_dir.deep_scan = UISettings::values.game_dir_deprecated_deepscan; | ||
| 222 | UISettings::values.game_dirs.append(game_dir); | ||
| 223 | } | ||
| 224 | } | ||
| 225 | UISettings::values.recent_files = | ||
| 226 | QString::fromStdString(ReadStringSetting(std::string("recentFiles"))) | ||
| 227 | .split(QStringLiteral(", "), Qt::SkipEmptyParts, Qt::CaseSensitive); | ||
| 228 | UISettings::values.language = ReadStringSetting(std::string("language"), std::string("")); | ||
| 229 | |||
| 230 | EndGroup(); | ||
| 231 | } | ||
| 232 | |||
| 233 | void QtConfig::ReadShortcutValues() { | ||
| 234 | BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts)); | ||
| 235 | |||
| 236 | for (const auto& [name, group, shortcut] : UISettings::default_hotkeys) { | ||
| 237 | BeginGroup(group); | ||
| 238 | BeginGroup(name); | ||
| 239 | |||
| 240 | // No longer using ReadSetting for shortcut.second as it inaccurately returns a value of 1 | ||
| 241 | // for WidgetWithChildrenShortcut which is a value of 3. Needed to fix shortcuts the open | ||
| 242 | // a file dialog in windowed mode | ||
| 243 | UISettings::values.shortcuts.push_back( | ||
| 244 | {name, | ||
| 245 | group, | ||
| 246 | {ReadStringSetting(std::string("KeySeq"), shortcut.keyseq), | ||
| 247 | ReadStringSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq), | ||
| 248 | shortcut.context, | ||
| 249 | ReadBooleanSetting(std::string("Repeat"), std::optional(shortcut.repeat))}}); | ||
| 250 | |||
| 251 | EndGroup(); // name | ||
| 252 | EndGroup(); // group | ||
| 253 | } | ||
| 254 | |||
| 255 | EndGroup(); | ||
| 256 | } | ||
| 257 | |||
| 258 | void QtConfig::ReadUIValues() { | ||
| 259 | BeginGroup(Settings::TranslateCategory(Settings::Category::Ui)); | ||
| 260 | |||
| 261 | UISettings::values.theme = ReadStringSetting( | ||
| 262 | std::string("theme"), | ||
| 263 | std::string(UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second)); | ||
| 264 | |||
| 265 | ReadUIGamelistValues(); | ||
| 266 | ReadUILayoutValues(); | ||
| 267 | ReadPathValues(); | ||
| 268 | ReadScreenshotValues(); | ||
| 269 | ReadShortcutValues(); | ||
| 270 | ReadMultiplayerValues(); | ||
| 271 | |||
| 272 | ReadCategory(Settings::Category::Ui); | ||
| 273 | ReadCategory(Settings::Category::UiGeneral); | ||
| 274 | |||
| 275 | EndGroup(); | ||
| 276 | } | ||
| 277 | |||
| 278 | void QtConfig::ReadUIGamelistValues() { | ||
| 279 | BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList)); | ||
| 280 | |||
| 281 | ReadCategory(Settings::Category::UiGameList); | ||
| 282 | |||
| 283 | const int favorites_size = BeginArray("favorites"); | ||
| 284 | for (int i = 0; i < favorites_size; i++) { | ||
| 285 | SetArrayIndex(i); | ||
| 286 | UISettings::values.favorited_ids.append( | ||
| 287 | ReadUnsignedIntegerSetting(std::string("program_id"))); | ||
| 288 | } | ||
| 289 | EndArray(); | ||
| 290 | |||
| 291 | EndGroup(); | ||
| 292 | } | ||
| 293 | |||
| 294 | void QtConfig::ReadUILayoutValues() { | ||
| 295 | BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList)); | ||
| 296 | |||
| 297 | ReadCategory(Settings::Category::UiLayout); | ||
| 298 | |||
| 299 | EndGroup(); | ||
| 300 | } | ||
| 301 | |||
| 302 | void QtConfig::ReadMultiplayerValues() { | ||
| 303 | BeginGroup(Settings::TranslateCategory(Settings::Category::Multiplayer)); | ||
| 304 | |||
| 305 | ReadCategory(Settings::Category::Multiplayer); | ||
| 306 | |||
| 307 | // Read ban list back | ||
| 308 | int size = BeginArray(std::string("username_ban_list")); | ||
| 309 | UISettings::values.multiplayer_ban_list.first.resize(size); | ||
| 310 | for (int i = 0; i < size; ++i) { | ||
| 311 | SetArrayIndex(i); | ||
| 312 | UISettings::values.multiplayer_ban_list.first[i] = | ||
| 313 | ReadStringSetting(std::string("username"), std::string("")); | ||
| 314 | } | ||
| 315 | EndArray(); | ||
| 316 | |||
| 317 | size = BeginArray(std::string("ip_ban_list")); | ||
| 318 | UISettings::values.multiplayer_ban_list.second.resize(size); | ||
| 319 | for (int i = 0; i < size; ++i) { | ||
| 320 | UISettings::values.multiplayer_ban_list.second[i] = | ||
| 321 | ReadStringSetting("username", std::string("")); | ||
| 322 | } | ||
| 323 | EndArray(); | ||
| 324 | |||
| 325 | EndGroup(); | ||
| 326 | } | ||
| 327 | |||
| 328 | void QtConfig::SaveQtValues() { | ||
| 329 | if (global) { | ||
| 330 | SaveUIValues(); | ||
| 331 | } | ||
| 332 | SaveQtControlValues(); | ||
| 333 | |||
| 334 | WriteToIni(); | ||
| 335 | } | ||
| 336 | |||
| 337 | void QtConfig::SaveQtPlayerValues(const std::size_t player_index) { | ||
| 338 | std::string player_prefix; | ||
| 339 | if (type != ConfigType::InputProfile) { | ||
| 340 | player_prefix = std::string("player_").append(ToString(player_index)).append("_"); | ||
| 341 | } | ||
| 342 | |||
| 343 | const auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 344 | if (IsCustomConfig() && player.profile_name.empty()) { | ||
| 345 | // No custom profile selected | ||
| 346 | return; | ||
| 347 | } | ||
| 348 | |||
| 349 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 350 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 351 | WriteSetting(std::string(player_prefix).append(Settings::NativeButton::mapping[i]), | ||
| 352 | player.buttons[i], std::make_optional(default_param)); | ||
| 353 | } | ||
| 354 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 355 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 356 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 357 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 358 | WriteSetting(std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), | ||
| 359 | player.analogs[i], std::make_optional(default_param)); | ||
| 360 | } | ||
| 361 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | ||
| 362 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); | ||
| 363 | WriteSetting(std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), | ||
| 364 | player.motions[i], std::make_optional(default_param)); | ||
| 365 | } | ||
| 366 | } | ||
| 367 | |||
| 368 | void QtConfig::SaveDebugControlValues() { | ||
| 369 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 370 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 371 | WriteSetting(std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), | ||
| 372 | Settings::values.debug_pad_buttons[i], std::make_optional(default_param)); | ||
| 373 | } | ||
| 374 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 375 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 376 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 377 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 378 | WriteSetting(std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), | ||
| 379 | Settings::values.debug_pad_analogs[i], std::make_optional(default_param)); | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | void QtConfig::SaveHidbusValues() { | ||
| 384 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 385 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); | ||
| 386 | WriteSetting(std::string("ring_controller"), Settings::values.ringcon_analogs, | ||
| 387 | std::make_optional(default_param)); | ||
| 388 | } | ||
| 389 | |||
| 390 | void QtConfig::SaveQtControlValues() { | ||
| 391 | BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); | ||
| 392 | |||
| 393 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 394 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | ||
| 395 | SaveQtPlayerValues(p); | ||
| 396 | } | ||
| 397 | if (IsCustomConfig()) { | ||
| 398 | EndGroup(); | ||
| 399 | return; | ||
| 400 | } | ||
| 401 | SaveDebugControlValues(); | ||
| 402 | SaveHidbusValues(); | ||
| 403 | |||
| 404 | EndGroup(); | ||
| 405 | } | ||
| 406 | |||
| 407 | void QtConfig::SavePathValues() { | ||
| 408 | BeginGroup(Settings::TranslateCategory(Settings::Category::Paths)); | ||
| 409 | |||
| 410 | WriteSetting(std::string("romsPath"), UISettings::values.roms_path); | ||
| 411 | WriteSetting(std::string("symbolsPath"), UISettings::values.symbols_path); | ||
| 412 | BeginArray(std::string("gamedirs")); | ||
| 413 | for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) { | ||
| 414 | SetArrayIndex(i); | ||
| 415 | const auto& game_dir = UISettings::values.game_dirs[i]; | ||
| 416 | WriteSetting(std::string("path"), game_dir.path); | ||
| 417 | WriteSetting(std::string("deep_scan"), game_dir.deep_scan, std::make_optional(false)); | ||
| 418 | WriteSetting(std::string("expanded"), game_dir.expanded, std::make_optional(true)); | ||
| 419 | } | ||
| 420 | EndArray(); | ||
| 421 | |||
| 422 | WriteSetting(std::string("recentFiles"), | ||
| 423 | UISettings::values.recent_files.join(QStringLiteral(", ")).toStdString()); | ||
| 424 | WriteSetting(std::string("language"), UISettings::values.language); | ||
| 425 | |||
| 426 | EndGroup(); | ||
| 427 | } | ||
| 428 | |||
| 429 | void QtConfig::SaveShortcutValues() { | ||
| 430 | BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts)); | ||
| 431 | |||
| 432 | // Lengths of UISettings::values.shortcuts & default_hotkeys are same. | ||
| 433 | // However, their ordering must also be the same. | ||
| 434 | for (std::size_t i = 0; i < UISettings::default_hotkeys.size(); i++) { | ||
| 435 | const auto& [name, group, shortcut] = UISettings::values.shortcuts[i]; | ||
| 436 | const auto& default_hotkey = UISettings::default_hotkeys[i].shortcut; | ||
| 437 | |||
| 438 | BeginGroup(group); | ||
| 439 | BeginGroup(name); | ||
| 440 | |||
| 441 | WriteSetting(std::string("KeySeq"), shortcut.keyseq, | ||
| 442 | std::make_optional(default_hotkey.keyseq)); | ||
| 443 | WriteSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq, | ||
| 444 | std::make_optional(default_hotkey.controller_keyseq)); | ||
| 445 | WriteSetting(std::string("Context"), shortcut.context, | ||
| 446 | std::make_optional(default_hotkey.context)); | ||
| 447 | WriteSetting(std::string("Repeat"), shortcut.repeat, | ||
| 448 | std::make_optional(default_hotkey.repeat)); | ||
| 449 | |||
| 450 | EndGroup(); // name | ||
| 451 | EndGroup(); // group | ||
| 452 | } | ||
| 453 | |||
| 454 | EndGroup(); | ||
| 455 | } | ||
| 456 | |||
| 457 | void QtConfig::SaveUIValues() { | ||
| 458 | BeginGroup(Settings::TranslateCategory(Settings::Category::Ui)); | ||
| 459 | |||
| 460 | WriteCategory(Settings::Category::Ui); | ||
| 461 | WriteCategory(Settings::Category::UiGeneral); | ||
| 462 | |||
| 463 | WriteSetting(std::string("theme"), UISettings::values.theme, | ||
| 464 | std::make_optional(std::string( | ||
| 465 | UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second))); | ||
| 466 | |||
| 467 | SaveUIGamelistValues(); | ||
| 468 | SaveUILayoutValues(); | ||
| 469 | SavePathValues(); | ||
| 470 | SaveScreenshotValues(); | ||
| 471 | SaveShortcutValues(); | ||
| 472 | SaveMultiplayerValues(); | ||
| 473 | |||
| 474 | EndGroup(); | ||
| 475 | } | ||
| 476 | |||
| 477 | void QtConfig::SaveUIGamelistValues() { | ||
| 478 | BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList)); | ||
| 479 | |||
| 480 | WriteCategory(Settings::Category::UiGameList); | ||
| 481 | |||
| 482 | BeginArray(std::string("favorites")); | ||
| 483 | for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { | ||
| 484 | SetArrayIndex(i); | ||
| 485 | WriteSetting(std::string("program_id"), UISettings::values.favorited_ids[i]); | ||
| 486 | } | ||
| 487 | EndArray(); // favorites | ||
| 488 | |||
| 489 | EndGroup(); | ||
| 490 | } | ||
| 491 | |||
| 492 | void QtConfig::SaveUILayoutValues() { | ||
| 493 | BeginGroup(Settings::TranslateCategory(Settings::Category::UiLayout)); | ||
| 494 | |||
| 495 | WriteCategory(Settings::Category::UiLayout); | ||
| 496 | |||
| 497 | EndGroup(); | ||
| 498 | } | ||
| 499 | |||
| 500 | void QtConfig::SaveMultiplayerValues() { | ||
| 501 | BeginGroup(std::string("Multiplayer")); | ||
| 502 | |||
| 503 | WriteCategory(Settings::Category::Multiplayer); | ||
| 504 | |||
| 505 | // Write ban list | ||
| 506 | BeginArray(std::string("username_ban_list")); | ||
| 507 | for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.first.size(); ++i) { | ||
| 508 | SetArrayIndex(static_cast<int>(i)); | ||
| 509 | WriteSetting(std::string("username"), UISettings::values.multiplayer_ban_list.first[i]); | ||
| 510 | } | ||
| 511 | EndArray(); // username_ban_list | ||
| 512 | |||
| 513 | BeginArray(std::string("ip_ban_list")); | ||
| 514 | for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.second.size(); ++i) { | ||
| 515 | SetArrayIndex(static_cast<int>(i)); | ||
| 516 | WriteSetting(std::string("ip"), UISettings::values.multiplayer_ban_list.second[i]); | ||
| 517 | } | ||
| 518 | EndArray(); // ip_ban_list | ||
| 519 | |||
| 520 | EndGroup(); | ||
| 521 | } | ||
| 522 | |||
| 523 | std::vector<Settings::BasicSetting*>& QtConfig::FindRelevantList(Settings::Category category) { | ||
| 524 | auto& map = Settings::values.linkage.by_category; | ||
| 525 | if (map.contains(category)) { | ||
| 526 | return Settings::values.linkage.by_category[category]; | ||
| 527 | } | ||
| 528 | return UISettings::values.linkage.by_category[category]; | ||
| 529 | } | ||
| 530 | |||
| 531 | void QtConfig::ReadQtControlPlayerValues(std::size_t player_index) { | ||
| 532 | BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); | ||
| 533 | |||
| 534 | ReadPlayerValues(player_index); | ||
| 535 | ReadQtPlayerValues(player_index); | ||
| 536 | |||
| 537 | EndGroup(); | ||
| 538 | } | ||
| 539 | |||
| 540 | void QtConfig::SaveQtControlPlayerValues(std::size_t player_index) { | ||
| 541 | BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); | ||
| 542 | |||
| 543 | SavePlayerValues(player_index); | ||
| 544 | SaveQtPlayerValues(player_index); | ||
| 545 | |||
| 546 | EndGroup(); | ||
| 547 | |||
| 548 | WriteToIni(); | ||
| 549 | } | ||
diff --git a/src/yuzu/configuration/qt_config.h b/src/yuzu/configuration/qt_config.h new file mode 100644 index 000000000..dc2dceb4d --- /dev/null +++ b/src/yuzu/configuration/qt_config.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <QMetaType> | ||
| 7 | |||
| 8 | #include "frontend_common/config.h" | ||
| 9 | |||
| 10 | class QtConfig final : public Config { | ||
| 11 | public: | ||
| 12 | explicit QtConfig(const std::string& config_name = "qt-config", | ||
| 13 | ConfigType config_type = ConfigType::GlobalConfig); | ||
| 14 | ~QtConfig() override; | ||
| 15 | |||
| 16 | void ReloadAllValues() override; | ||
| 17 | void SaveAllValues() override; | ||
| 18 | |||
| 19 | void ReadQtControlPlayerValues(std::size_t player_index); | ||
| 20 | void SaveQtControlPlayerValues(std::size_t player_index); | ||
| 21 | |||
| 22 | protected: | ||
| 23 | void ReadQtValues(); | ||
| 24 | void ReadQtPlayerValues(std::size_t player_index); | ||
| 25 | void ReadQtControlValues(); | ||
| 26 | void ReadHidbusValues() override; | ||
| 27 | void ReadDebugControlValues() override; | ||
| 28 | void ReadPathValues() override; | ||
| 29 | void ReadShortcutValues() override; | ||
| 30 | void ReadUIValues() override; | ||
| 31 | void ReadUIGamelistValues() override; | ||
| 32 | void ReadUILayoutValues() override; | ||
| 33 | void ReadMultiplayerValues() override; | ||
| 34 | |||
| 35 | void SaveQtValues(); | ||
| 36 | void SaveQtPlayerValues(std::size_t player_index); | ||
| 37 | void SaveQtControlValues(); | ||
| 38 | void SaveHidbusValues() override; | ||
| 39 | void SaveDebugControlValues() override; | ||
| 40 | void SavePathValues() override; | ||
| 41 | void SaveShortcutValues() override; | ||
| 42 | void SaveUIValues() override; | ||
| 43 | void SaveUIGamelistValues() override; | ||
| 44 | void SaveUILayoutValues() override; | ||
| 45 | void SaveMultiplayerValues() override; | ||
| 46 | |||
| 47 | std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override; | ||
| 48 | |||
| 49 | public: | ||
| 50 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; | ||
| 51 | static const std::array<int, Settings::NativeMotion::NumMotions> default_motions; | ||
| 52 | static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs; | ||
| 53 | static const std::array<int, 2> default_stick_mod; | ||
| 54 | static const std::array<int, 2> default_ringcon_analogs; | ||
| 55 | }; | ||
diff --git a/src/yuzu/configuration/shared_translation.h b/src/yuzu/configuration/shared_translation.h index 99a0e808c..d5fc3b8de 100644 --- a/src/yuzu/configuration/shared_translation.h +++ b/src/yuzu/configuration/shared_translation.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | #include <QString> | 11 | #include <QString> |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/settings.h" | ||
| 13 | 14 | ||
| 14 | class QWidget; | 15 | class QWidget; |
| 15 | 16 | ||
| @@ -22,4 +23,46 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent); | |||
| 22 | 23 | ||
| 23 | std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent); | 24 | std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent); |
| 24 | 25 | ||
| 26 | static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map = { | ||
| 27 | {Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))}, | ||
| 28 | {Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))}, | ||
| 29 | {Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))}, | ||
| 30 | }; | ||
| 31 | |||
| 32 | static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map = { | ||
| 33 | {Settings::ScalingFilter::NearestNeighbor, | ||
| 34 | QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))}, | ||
| 35 | {Settings::ScalingFilter::Bilinear, | ||
| 36 | QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))}, | ||
| 37 | {Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))}, | ||
| 38 | {Settings::ScalingFilter::Gaussian, | ||
| 39 | QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))}, | ||
| 40 | {Settings::ScalingFilter::ScaleForce, | ||
| 41 | QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))}, | ||
| 42 | {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))}, | ||
| 43 | }; | ||
| 44 | |||
| 45 | static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map = { | ||
| 46 | {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))}, | ||
| 47 | {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))}, | ||
| 48 | }; | ||
| 49 | |||
| 50 | static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map = { | ||
| 51 | {Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))}, | ||
| 52 | {Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))}, | ||
| 53 | {Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))}, | ||
| 54 | }; | ||
| 55 | |||
| 56 | static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map = { | ||
| 57 | {Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))}, | ||
| 58 | {Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))}, | ||
| 59 | {Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))}, | ||
| 60 | }; | ||
| 61 | |||
| 62 | static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map = { | ||
| 63 | {Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))}, | ||
| 64 | {Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))}, | ||
| 65 | {Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))}, | ||
| 66 | }; | ||
| 67 | |||
| 25 | } // namespace ConfigurationShared | 68 | } // namespace ConfigurationShared |
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 7049c57b6..6d227ef8d 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp | |||
| @@ -36,10 +36,8 @@ constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{ | |||
| 36 | 36 | ||
| 37 | bool IsDarkTheme() { | 37 | bool IsDarkTheme() { |
| 38 | const auto& theme = UISettings::values.theme; | 38 | const auto& theme = UISettings::values.theme; |
| 39 | return theme == QStringLiteral("qdarkstyle") || | 39 | return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") || |
| 40 | theme == QStringLiteral("qdarkstyle_midnight_blue") || | 40 | theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue"); |
| 41 | theme == QStringLiteral("colorful_dark") || | ||
| 42 | theme == QStringLiteral("colorful_midnight_blue"); | ||
| 43 | } | 41 | } |
| 44 | 42 | ||
| 45 | } // namespace | 43 | } // namespace |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index f294dc23d..59b317135 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -278,7 +278,7 @@ void GameList::OnUpdateThemedIcons() { | |||
| 278 | case GameListItemType::CustomDir: { | 278 | case GameListItemType::CustomDir: { |
| 279 | const UISettings::GameDir& game_dir = | 279 | const UISettings::GameDir& game_dir = |
| 280 | UISettings::values.game_dirs[child->data(GameListDir::GameDirRole).toInt()]; | 280 | UISettings::values.game_dirs[child->data(GameListDir::GameDirRole).toInt()]; |
| 281 | const QString icon_name = QFileInfo::exists(game_dir.path) | 281 | const QString icon_name = QFileInfo::exists(QString::fromStdString(game_dir.path)) |
| 282 | ? QStringLiteral("folder") | 282 | ? QStringLiteral("folder") |
| 283 | : QStringLiteral("bad_folder"); | 283 | : QStringLiteral("bad_folder"); |
| 284 | child->setData( | 284 | child->setData( |
| @@ -727,7 +727,8 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) { | |||
| 727 | }); | 727 | }); |
| 728 | 728 | ||
| 729 | connect(open_directory_location, &QAction::triggered, [this, game_dir_index] { | 729 | connect(open_directory_location, &QAction::triggered, [this, game_dir_index] { |
| 730 | emit OpenDirectory(UISettings::values.game_dirs[game_dir_index].path); | 730 | emit OpenDirectory( |
| 731 | QString::fromStdString(UISettings::values.game_dirs[game_dir_index].path)); | ||
| 731 | }); | 732 | }); |
| 732 | } | 733 | } |
| 733 | 734 | ||
| @@ -869,7 +870,7 @@ const QStringList GameList::supported_file_extensions = { | |||
| 869 | QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")}; | 870 | QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")}; |
| 870 | 871 | ||
| 871 | void GameList::RefreshGameDirectory() { | 872 | void GameList::RefreshGameDirectory() { |
| 872 | if (!UISettings::values.game_dirs.isEmpty() && current_worker != nullptr) { | 873 | if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) { |
| 873 | LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list."); | 874 | LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list."); |
| 874 | PopulateAsync(UISettings::values.game_dirs); | 875 | PopulateAsync(UISettings::values.game_dirs); |
| 875 | } | 876 | } |
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index 86a0c41d9..c330b574f 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h | |||
| @@ -286,13 +286,13 @@ public: | |||
| 286 | setData(QObject::tr("System Titles"), Qt::DisplayRole); | 286 | setData(QObject::tr("System Titles"), Qt::DisplayRole); |
| 287 | break; | 287 | break; |
| 288 | case GameListItemType::CustomDir: { | 288 | case GameListItemType::CustomDir: { |
| 289 | const QString icon_name = QFileInfo::exists(game_dir->path) | 289 | const QString path = QString::fromStdString(game_dir->path); |
| 290 | ? QStringLiteral("folder") | 290 | const QString icon_name = |
| 291 | : QStringLiteral("bad_folder"); | 291 | QFileInfo::exists(path) ? QStringLiteral("folder") : QStringLiteral("bad_folder"); |
| 292 | setData(QIcon::fromTheme(icon_name).pixmap(icon_size).scaled( | 292 | setData(QIcon::fromTheme(icon_name).pixmap(icon_size).scaled( |
| 293 | icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), | 293 | icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), |
| 294 | Qt::DecorationRole); | 294 | Qt::DecorationRole); |
| 295 | setData(game_dir->path, Qt::DisplayRole); | 295 | setData(path, Qt::DisplayRole); |
| 296 | break; | 296 | break; |
| 297 | } | 297 | } |
| 298 | default: | 298 | default: |
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 307eac02d..dc006832e 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp | |||
| @@ -456,26 +456,26 @@ void GameListWorker::run() { | |||
| 456 | break; | 456 | break; |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | if (game_dir.path == QStringLiteral("SDMC")) { | 459 | if (game_dir.path == std::string("SDMC")) { |
| 460 | auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir); | 460 | auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir); |
| 461 | DirEntryReady(game_list_dir); | 461 | DirEntryReady(game_list_dir); |
| 462 | AddTitlesToGameList(game_list_dir); | 462 | AddTitlesToGameList(game_list_dir); |
| 463 | } else if (game_dir.path == QStringLiteral("UserNAND")) { | 463 | } else if (game_dir.path == std::string("UserNAND")) { |
| 464 | auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir); | 464 | auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir); |
| 465 | DirEntryReady(game_list_dir); | 465 | DirEntryReady(game_list_dir); |
| 466 | AddTitlesToGameList(game_list_dir); | 466 | AddTitlesToGameList(game_list_dir); |
| 467 | } else if (game_dir.path == QStringLiteral("SysNAND")) { | 467 | } else if (game_dir.path == std::string("SysNAND")) { |
| 468 | auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir); | 468 | auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir); |
| 469 | DirEntryReady(game_list_dir); | 469 | DirEntryReady(game_list_dir); |
| 470 | AddTitlesToGameList(game_list_dir); | 470 | AddTitlesToGameList(game_list_dir); |
| 471 | } else { | 471 | } else { |
| 472 | watch_list.append(game_dir.path); | 472 | watch_list.append(QString::fromStdString(game_dir.path)); |
| 473 | auto* const game_list_dir = new GameListDir(game_dir); | 473 | auto* const game_list_dir = new GameListDir(game_dir); |
| 474 | DirEntryReady(game_list_dir); | 474 | DirEntryReady(game_list_dir); |
| 475 | ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(), | 475 | ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan, |
| 476 | game_dir.deep_scan, game_list_dir); | 476 | game_list_dir); |
| 477 | ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(), | 477 | ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path, game_dir.deep_scan, |
| 478 | game_dir.deep_scan, game_list_dir); | 478 | game_list_dir); |
| 479 | } | 479 | } |
| 480 | } | 480 | } |
| 481 | 481 | ||
diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp index 6530186c1..eebfbf155 100644 --- a/src/yuzu/hotkeys.cpp +++ b/src/yuzu/hotkeys.cpp | |||
| @@ -19,7 +19,7 @@ void HotkeyRegistry::SaveHotkeys() { | |||
| 19 | for (const auto& hotkey : group.second) { | 19 | for (const auto& hotkey : group.second) { |
| 20 | UISettings::values.shortcuts.push_back( | 20 | UISettings::values.shortcuts.push_back( |
| 21 | {hotkey.first, group.first, | 21 | {hotkey.first, group.first, |
| 22 | UISettings::ContextualShortcut({hotkey.second.keyseq.toString(), | 22 | UISettings::ContextualShortcut({hotkey.second.keyseq.toString().toStdString(), |
| 23 | hotkey.second.controller_keyseq, | 23 | hotkey.second.controller_keyseq, |
| 24 | hotkey.second.context, hotkey.second.repeat})}); | 24 | hotkey.second.context, hotkey.second.repeat})}); |
| 25 | } | 25 | } |
| @@ -31,12 +31,12 @@ void HotkeyRegistry::LoadHotkeys() { | |||
| 31 | // beginGroup() | 31 | // beginGroup() |
| 32 | for (auto shortcut : UISettings::values.shortcuts) { | 32 | for (auto shortcut : UISettings::values.shortcuts) { |
| 33 | Hotkey& hk = hotkey_groups[shortcut.group][shortcut.name]; | 33 | Hotkey& hk = hotkey_groups[shortcut.group][shortcut.name]; |
| 34 | if (!shortcut.shortcut.keyseq.isEmpty()) { | 34 | if (!shortcut.shortcut.keyseq.empty()) { |
| 35 | hk.keyseq = | 35 | hk.keyseq = QKeySequence::fromString(QString::fromStdString(shortcut.shortcut.keyseq), |
| 36 | QKeySequence::fromString(shortcut.shortcut.keyseq, QKeySequence::NativeText); | 36 | QKeySequence::NativeText); |
| 37 | hk.context = static_cast<Qt::ShortcutContext>(shortcut.shortcut.context); | 37 | hk.context = static_cast<Qt::ShortcutContext>(shortcut.shortcut.context); |
| 38 | } | 38 | } |
| 39 | if (!shortcut.shortcut.controller_keyseq.isEmpty()) { | 39 | if (!shortcut.shortcut.controller_keyseq.empty()) { |
| 40 | hk.controller_keyseq = shortcut.shortcut.controller_keyseq; | 40 | hk.controller_keyseq = shortcut.shortcut.controller_keyseq; |
| 41 | } | 41 | } |
| 42 | if (hk.shortcut) { | 42 | if (hk.shortcut) { |
| @@ -51,7 +51,8 @@ void HotkeyRegistry::LoadHotkeys() { | |||
| 51 | } | 51 | } |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) { | 54 | QShortcut* HotkeyRegistry::GetHotkey(const std::string& group, const std::string& action, |
| 55 | QWidget* widget) { | ||
| 55 | Hotkey& hk = hotkey_groups[group][action]; | 56 | Hotkey& hk = hotkey_groups[group][action]; |
| 56 | 57 | ||
| 57 | if (!hk.shortcut) { | 58 | if (!hk.shortcut) { |
| @@ -62,7 +63,8 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action | |||
| 62 | return hk.shortcut; | 63 | return hk.shortcut; |
| 63 | } | 64 | } |
| 64 | 65 | ||
| 65 | ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, const QString& action, | 66 | ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const std::string& group, |
| 67 | const std::string& action, | ||
| 66 | Core::HID::EmulatedController* controller) { | 68 | Core::HID::EmulatedController* controller) { |
| 67 | Hotkey& hk = hotkey_groups[group][action]; | 69 | Hotkey& hk = hotkey_groups[group][action]; |
| 68 | 70 | ||
| @@ -74,12 +76,12 @@ ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, co | |||
| 74 | return hk.controller_shortcut; | 76 | return hk.controller_shortcut; |
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | QKeySequence HotkeyRegistry::GetKeySequence(const QString& group, const QString& action) { | 79 | QKeySequence HotkeyRegistry::GetKeySequence(const std::string& group, const std::string& action) { |
| 78 | return hotkey_groups[group][action].keyseq; | 80 | return hotkey_groups[group][action].keyseq; |
| 79 | } | 81 | } |
| 80 | 82 | ||
| 81 | Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const QString& group, | 83 | Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const std::string& group, |
| 82 | const QString& action) { | 84 | const std::string& action) { |
| 83 | return hotkey_groups[group][action].context; | 85 | return hotkey_groups[group][action].context; |
| 84 | } | 86 | } |
| 85 | 87 | ||
| @@ -101,10 +103,10 @@ void ControllerShortcut::SetKey(const ControllerButtonSequence& buttons) { | |||
| 101 | button_sequence = buttons; | 103 | button_sequence = buttons; |
| 102 | } | 104 | } |
| 103 | 105 | ||
| 104 | void ControllerShortcut::SetKey(const QString& buttons_shortcut) { | 106 | void ControllerShortcut::SetKey(const std::string& buttons_shortcut) { |
| 105 | ControllerButtonSequence sequence{}; | 107 | ControllerButtonSequence sequence{}; |
| 106 | name = buttons_shortcut.toStdString(); | 108 | name = buttons_shortcut; |
| 107 | std::istringstream command_line(buttons_shortcut.toStdString()); | 109 | std::istringstream command_line(buttons_shortcut); |
| 108 | std::string line; | 110 | std::string line; |
| 109 | while (std::getline(command_line, line, '+')) { | 111 | while (std::getline(command_line, line, '+')) { |
| 110 | if (line.empty()) { | 112 | if (line.empty()) { |
diff --git a/src/yuzu/hotkeys.h b/src/yuzu/hotkeys.h index 56eee8d82..e11332d2e 100644 --- a/src/yuzu/hotkeys.h +++ b/src/yuzu/hotkeys.h | |||
| @@ -33,7 +33,7 @@ public: | |||
| 33 | ~ControllerShortcut(); | 33 | ~ControllerShortcut(); |
| 34 | 34 | ||
| 35 | void SetKey(const ControllerButtonSequence& buttons); | 35 | void SetKey(const ControllerButtonSequence& buttons); |
| 36 | void SetKey(const QString& buttons_shortcut); | 36 | void SetKey(const std::string& buttons_shortcut); |
| 37 | 37 | ||
| 38 | ControllerButtonSequence ButtonSequence() const; | 38 | ControllerButtonSequence ButtonSequence() const; |
| 39 | 39 | ||
| @@ -88,8 +88,8 @@ public: | |||
| 88 | * will be the same. Thus, you shouldn't rely on the caller really being the | 88 | * will be the same. Thus, you shouldn't rely on the caller really being the |
| 89 | * QShortcut's parent. | 89 | * QShortcut's parent. |
| 90 | */ | 90 | */ |
| 91 | QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget); | 91 | QShortcut* GetHotkey(const std::string& group, const std::string& action, QWidget* widget); |
| 92 | ControllerShortcut* GetControllerHotkey(const QString& group, const QString& action, | 92 | ControllerShortcut* GetControllerHotkey(const std::string& group, const std::string& action, |
| 93 | Core::HID::EmulatedController* controller); | 93 | Core::HID::EmulatedController* controller); |
| 94 | 94 | ||
| 95 | /** | 95 | /** |
| @@ -98,7 +98,7 @@ public: | |||
| 98 | * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger"). | 98 | * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger"). |
| 99 | * @param action Name of the action (e.g. "Start Emulation", "Load Image"). | 99 | * @param action Name of the action (e.g. "Start Emulation", "Load Image"). |
| 100 | */ | 100 | */ |
| 101 | QKeySequence GetKeySequence(const QString& group, const QString& action); | 101 | QKeySequence GetKeySequence(const std::string& group, const std::string& action); |
| 102 | 102 | ||
| 103 | /** | 103 | /** |
| 104 | * Returns a Qt::ShortcutContext object who can be connected to other | 104 | * Returns a Qt::ShortcutContext object who can be connected to other |
| @@ -108,20 +108,20 @@ public: | |||
| 108 | * "Debugger"). | 108 | * "Debugger"). |
| 109 | * @param action Name of the action (e.g. "Start Emulation", "Load Image"). | 109 | * @param action Name of the action (e.g. "Start Emulation", "Load Image"). |
| 110 | */ | 110 | */ |
| 111 | Qt::ShortcutContext GetShortcutContext(const QString& group, const QString& action); | 111 | Qt::ShortcutContext GetShortcutContext(const std::string& group, const std::string& action); |
| 112 | 112 | ||
| 113 | private: | 113 | private: |
| 114 | struct Hotkey { | 114 | struct Hotkey { |
| 115 | QKeySequence keyseq; | 115 | QKeySequence keyseq; |
| 116 | QString controller_keyseq; | 116 | std::string controller_keyseq; |
| 117 | QShortcut* shortcut = nullptr; | 117 | QShortcut* shortcut = nullptr; |
| 118 | ControllerShortcut* controller_shortcut = nullptr; | 118 | ControllerShortcut* controller_shortcut = nullptr; |
| 119 | Qt::ShortcutContext context = Qt::WindowShortcut; | 119 | Qt::ShortcutContext context = Qt::WindowShortcut; |
| 120 | bool repeat; | 120 | bool repeat; |
| 121 | }; | 121 | }; |
| 122 | 122 | ||
| 123 | using HotkeyMap = std::map<QString, Hotkey>; | 123 | using HotkeyMap = std::map<std::string, Hotkey>; |
| 124 | using HotkeyGroupMap = std::map<QString, HotkeyMap>; | 124 | using HotkeyGroupMap = std::map<std::string, HotkeyMap>; |
| 125 | 125 | ||
| 126 | HotkeyGroupMap hotkey_groups; | 126 | HotkeyGroupMap hotkey_groups; |
| 127 | }; | 127 | }; |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f22db233b..defe45198 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -128,6 +128,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 128 | #include "core/loader/loader.h" | 128 | #include "core/loader/loader.h" |
| 129 | #include "core/perf_stats.h" | 129 | #include "core/perf_stats.h" |
| 130 | #include "core/telemetry_session.h" | 130 | #include "core/telemetry_session.h" |
| 131 | #include "frontend_common/config.h" | ||
| 131 | #include "input_common/drivers/tas_input.h" | 132 | #include "input_common/drivers/tas_input.h" |
| 132 | #include "input_common/drivers/virtual_amiibo.h" | 133 | #include "input_common/drivers/virtual_amiibo.h" |
| 133 | #include "input_common/main.h" | 134 | #include "input_common/main.h" |
| @@ -140,9 +141,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 140 | #include "yuzu/bootmanager.h" | 141 | #include "yuzu/bootmanager.h" |
| 141 | #include "yuzu/compatdb.h" | 142 | #include "yuzu/compatdb.h" |
| 142 | #include "yuzu/compatibility_list.h" | 143 | #include "yuzu/compatibility_list.h" |
| 143 | #include "yuzu/configuration/config.h" | ||
| 144 | #include "yuzu/configuration/configure_dialog.h" | 144 | #include "yuzu/configuration/configure_dialog.h" |
| 145 | #include "yuzu/configuration/configure_input_per_game.h" | 145 | #include "yuzu/configuration/configure_input_per_game.h" |
| 146 | #include "yuzu/configuration/qt_config.h" | ||
| 146 | #include "yuzu/debugger/console.h" | 147 | #include "yuzu/debugger/console.h" |
| 147 | #include "yuzu/debugger/controller.h" | 148 | #include "yuzu/debugger/controller.h" |
| 148 | #include "yuzu/debugger/profiler.h" | 149 | #include "yuzu/debugger/profiler.h" |
| @@ -311,7 +312,7 @@ bool GMainWindow::CheckDarkMode() { | |||
| 311 | #endif // __unix__ | 312 | #endif // __unix__ |
| 312 | } | 313 | } |
| 313 | 314 | ||
| 314 | GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan) | 315 | GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan) |
| 315 | : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()}, | 316 | : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()}, |
| 316 | input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, config{std::move(config_)}, | 317 | input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, config{std::move(config_)}, |
| 317 | vfs{std::make_shared<FileSys::RealVfsFilesystem>()}, | 318 | vfs{std::make_shared<FileSys::RealVfsFilesystem>()}, |
| @@ -676,7 +677,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers( | |||
| 676 | // Don't forget to apply settings. | 677 | // Don't forget to apply settings. |
| 677 | system->HIDCore().DisableAllControllerConfiguration(); | 678 | system->HIDCore().DisableAllControllerConfiguration(); |
| 678 | system->ApplySettings(); | 679 | system->ApplySettings(); |
| 679 | config->Save(); | 680 | config->SaveAllValues(); |
| 680 | 681 | ||
| 681 | UpdateStatusButtons(); | 682 | UpdateStatusButtons(); |
| 682 | 683 | ||
| @@ -1129,7 +1130,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 1129 | connect(aa_status_button, &QPushButton::customContextMenuRequested, | 1130 | connect(aa_status_button, &QPushButton::customContextMenuRequested, |
| 1130 | [this](const QPoint& menu_location) { | 1131 | [this](const QPoint& menu_location) { |
| 1131 | QMenu context_menu; | 1132 | QMenu context_menu; |
| 1132 | for (auto const& aa_text_pair : Config::anti_aliasing_texts_map) { | 1133 | for (auto const& aa_text_pair : ConfigurationShared::anti_aliasing_texts_map) { |
| 1133 | context_menu.addAction(aa_text_pair.second, [this, aa_text_pair] { | 1134 | context_menu.addAction(aa_text_pair.second, [this, aa_text_pair] { |
| 1134 | Settings::values.anti_aliasing.SetValue(aa_text_pair.first); | 1135 | Settings::values.anti_aliasing.SetValue(aa_text_pair.first); |
| 1135 | UpdateAAText(); | 1136 | UpdateAAText(); |
| @@ -1153,7 +1154,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 1153 | connect(filter_status_button, &QPushButton::customContextMenuRequested, | 1154 | connect(filter_status_button, &QPushButton::customContextMenuRequested, |
| 1154 | [this](const QPoint& menu_location) { | 1155 | [this](const QPoint& menu_location) { |
| 1155 | QMenu context_menu; | 1156 | QMenu context_menu; |
| 1156 | for (auto const& filter_text_pair : Config::scaling_filter_texts_map) { | 1157 | for (auto const& filter_text_pair : ConfigurationShared::scaling_filter_texts_map) { |
| 1157 | context_menu.addAction(filter_text_pair.second, [this, filter_text_pair] { | 1158 | context_menu.addAction(filter_text_pair.second, [this, filter_text_pair] { |
| 1158 | Settings::values.scaling_filter.SetValue(filter_text_pair.first); | 1159 | Settings::values.scaling_filter.SetValue(filter_text_pair.first); |
| 1159 | UpdateFilterText(); | 1160 | UpdateFilterText(); |
| @@ -1176,7 +1177,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 1176 | [this](const QPoint& menu_location) { | 1177 | [this](const QPoint& menu_location) { |
| 1177 | QMenu context_menu; | 1178 | QMenu context_menu; |
| 1178 | 1179 | ||
| 1179 | for (auto const& pair : Config::use_docked_mode_texts_map) { | 1180 | for (auto const& pair : ConfigurationShared::use_docked_mode_texts_map) { |
| 1180 | context_menu.addAction(pair.second, [this, &pair] { | 1181 | context_menu.addAction(pair.second, [this, &pair] { |
| 1181 | if (pair.first != Settings::values.use_docked_mode.GetValue()) { | 1182 | if (pair.first != Settings::values.use_docked_mode.GetValue()) { |
| 1182 | OnToggleDockedMode(); | 1183 | OnToggleDockedMode(); |
| @@ -1200,7 +1201,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 1200 | [this](const QPoint& menu_location) { | 1201 | [this](const QPoint& menu_location) { |
| 1201 | QMenu context_menu; | 1202 | QMenu context_menu; |
| 1202 | 1203 | ||
| 1203 | for (auto const& gpu_accuracy_pair : Config::gpu_accuracy_texts_map) { | 1204 | for (auto const& gpu_accuracy_pair : ConfigurationShared::gpu_accuracy_texts_map) { |
| 1204 | if (gpu_accuracy_pair.first == Settings::GpuAccuracy::Extreme) { | 1205 | if (gpu_accuracy_pair.first == Settings::GpuAccuracy::Extreme) { |
| 1205 | continue; | 1206 | continue; |
| 1206 | } | 1207 | } |
| @@ -1229,7 +1230,8 @@ void GMainWindow::InitializeWidgets() { | |||
| 1229 | [this](const QPoint& menu_location) { | 1230 | [this](const QPoint& menu_location) { |
| 1230 | QMenu context_menu; | 1231 | QMenu context_menu; |
| 1231 | 1232 | ||
| 1232 | for (auto const& renderer_backend_pair : Config::renderer_backend_texts_map) { | 1233 | for (auto const& renderer_backend_pair : |
| 1234 | ConfigurationShared::renderer_backend_texts_map) { | ||
| 1233 | if (renderer_backend_pair.first == Settings::RendererBackend::Null) { | 1235 | if (renderer_backend_pair.first == Settings::RendererBackend::Null) { |
| 1234 | continue; | 1236 | continue; |
| 1235 | } | 1237 | } |
| @@ -1294,16 +1296,17 @@ void GMainWindow::InitializeRecentFileMenuActions() { | |||
| 1294 | 1296 | ||
| 1295 | void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name, | 1297 | void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name, |
| 1296 | const bool tas_allowed) { | 1298 | const bool tas_allowed) { |
| 1297 | static const QString main_window = QStringLiteral("Main Window"); | 1299 | static const auto main_window = std::string("Main Window"); |
| 1298 | action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name)); | 1300 | action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name.toStdString())); |
| 1299 | action->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, action_name)); | 1301 | action->setShortcutContext( |
| 1302 | hotkey_registry.GetShortcutContext(main_window, action_name.toStdString())); | ||
| 1300 | action->setAutoRepeat(false); | 1303 | action->setAutoRepeat(false); |
| 1301 | 1304 | ||
| 1302 | this->addAction(action); | 1305 | this->addAction(action); |
| 1303 | 1306 | ||
| 1304 | auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); | 1307 | auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); |
| 1305 | const auto* controller_hotkey = | 1308 | const auto* controller_hotkey = |
| 1306 | hotkey_registry.GetControllerHotkey(main_window, action_name, controller); | 1309 | hotkey_registry.GetControllerHotkey(main_window, action_name.toStdString(), controller); |
| 1307 | connect( | 1310 | connect( |
| 1308 | controller_hotkey, &ControllerShortcut::Activated, this, | 1311 | controller_hotkey, &ControllerShortcut::Activated, this, |
| 1309 | [action, tas_allowed, this] { | 1312 | [action, tas_allowed, this] { |
| @@ -1335,10 +1338,11 @@ void GMainWindow::InitializeHotkeys() { | |||
| 1335 | 1338 | ||
| 1336 | static const QString main_window = QStringLiteral("Main Window"); | 1339 | static const QString main_window = QStringLiteral("Main Window"); |
| 1337 | const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) { | 1340 | const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) { |
| 1338 | const auto* hotkey = hotkey_registry.GetHotkey(main_window, action_name, this); | 1341 | const auto* hotkey = |
| 1342 | hotkey_registry.GetHotkey(main_window.toStdString(), action_name.toStdString(), this); | ||
| 1339 | auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); | 1343 | auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); |
| 1340 | const auto* controller_hotkey = | 1344 | const auto* controller_hotkey = hotkey_registry.GetControllerHotkey( |
| 1341 | hotkey_registry.GetControllerHotkey(main_window, action_name, controller); | 1345 | main_window.toStdString(), action_name.toStdString(), controller); |
| 1342 | connect(hotkey, &QShortcut::activated, this, function); | 1346 | connect(hotkey, &QShortcut::activated, this, function); |
| 1343 | connect(controller_hotkey, &ControllerShortcut::Activated, this, function, | 1347 | connect(controller_hotkey, &ControllerShortcut::Activated, this, function, |
| 1344 | Qt::QueuedConnection); | 1348 | Qt::QueuedConnection); |
| @@ -1918,7 +1922,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1918 | // Save configurations | 1922 | // Save configurations |
| 1919 | UpdateUISettings(); | 1923 | UpdateUISettings(); |
| 1920 | game_list->SaveInterfaceLayout(); | 1924 | game_list->SaveInterfaceLayout(); |
| 1921 | config->Save(); | 1925 | config->SaveAllValues(); |
| 1922 | 1926 | ||
| 1923 | u64 title_id{0}; | 1927 | u64 title_id{0}; |
| 1924 | 1928 | ||
| @@ -1936,7 +1940,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1936 | const auto config_file_name = title_id == 0 | 1940 | const auto config_file_name = title_id == 0 |
| 1937 | ? Common::FS::PathToUTF8String(file_path.filename()) | 1941 | ? Common::FS::PathToUTF8String(file_path.filename()) |
| 1938 | : fmt::format("{:016X}", title_id); | 1942 | : fmt::format("{:016X}", title_id); |
| 1939 | Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig); | 1943 | QtConfig per_game_config(config_file_name, Config::ConfigType::PerGameConfig); |
| 1940 | system->HIDCore().ReloadInputDevices(); | 1944 | system->HIDCore().ReloadInputDevices(); |
| 1941 | system->ApplySettings(); | 1945 | system->ApplySettings(); |
| 1942 | } | 1946 | } |
| @@ -3135,7 +3139,7 @@ void GMainWindow::OnGameListAddDirectory() { | |||
| 3135 | return; | 3139 | return; |
| 3136 | } | 3140 | } |
| 3137 | 3141 | ||
| 3138 | UISettings::GameDir game_dir{dir_path, false, true}; | 3142 | UISettings::GameDir game_dir{dir_path.toStdString(), false, true}; |
| 3139 | if (!UISettings::values.game_dirs.contains(game_dir)) { | 3143 | if (!UISettings::values.game_dirs.contains(game_dir)) { |
| 3140 | UISettings::values.game_dirs.append(game_dir); | 3144 | UISettings::values.game_dirs.append(game_dir); |
| 3141 | game_list->PopulateAsync(UISettings::values.game_dirs); | 3145 | game_list->PopulateAsync(UISettings::values.game_dirs); |
| @@ -3181,14 +3185,14 @@ void GMainWindow::OnMenuLoadFile() { | |||
| 3181 | "%1 is an identifier for the Switch executable file extensions.") | 3185 | "%1 is an identifier for the Switch executable file extensions.") |
| 3182 | .arg(extensions); | 3186 | .arg(extensions); |
| 3183 | const QString filename = QFileDialog::getOpenFileName( | 3187 | const QString filename = QFileDialog::getOpenFileName( |
| 3184 | this, tr("Load File"), UISettings::values.roms_path, file_filter); | 3188 | this, tr("Load File"), QString::fromStdString(UISettings::values.roms_path), file_filter); |
| 3185 | is_load_file_select_active = false; | 3189 | is_load_file_select_active = false; |
| 3186 | 3190 | ||
| 3187 | if (filename.isEmpty()) { | 3191 | if (filename.isEmpty()) { |
| 3188 | return; | 3192 | return; |
| 3189 | } | 3193 | } |
| 3190 | 3194 | ||
| 3191 | UISettings::values.roms_path = QFileInfo(filename).path(); | 3195 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 3192 | BootGame(filename); | 3196 | BootGame(filename); |
| 3193 | } | 3197 | } |
| 3194 | 3198 | ||
| @@ -3221,7 +3225,8 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3221 | "Image (*.xci)"); | 3225 | "Image (*.xci)"); |
| 3222 | 3226 | ||
| 3223 | QStringList filenames = QFileDialog::getOpenFileNames( | 3227 | QStringList filenames = QFileDialog::getOpenFileNames( |
| 3224 | this, tr("Install Files"), UISettings::values.roms_path, file_filter); | 3228 | this, tr("Install Files"), QString::fromStdString(UISettings::values.roms_path), |
| 3229 | file_filter); | ||
| 3225 | 3230 | ||
| 3226 | if (filenames.isEmpty()) { | 3231 | if (filenames.isEmpty()) { |
| 3227 | return; | 3232 | return; |
| @@ -3239,7 +3244,7 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3239 | } | 3244 | } |
| 3240 | 3245 | ||
| 3241 | // Save folder location of the first selected file | 3246 | // Save folder location of the first selected file |
| 3242 | UISettings::values.roms_path = QFileInfo(filenames[0]).path(); | 3247 | UISettings::values.roms_path = QFileInfo(filenames[0]).path().toStdString(); |
| 3243 | 3248 | ||
| 3244 | int remaining = filenames.size(); | 3249 | int remaining = filenames.size(); |
| 3245 | 3250 | ||
| @@ -3584,7 +3589,7 @@ void GMainWindow::OnExit() { | |||
| 3584 | 3589 | ||
| 3585 | void GMainWindow::OnSaveConfig() { | 3590 | void GMainWindow::OnSaveConfig() { |
| 3586 | system->ApplySettings(); | 3591 | system->ApplySettings(); |
| 3587 | config->Save(); | 3592 | config->SaveAllValues(); |
| 3588 | } | 3593 | } |
| 3589 | 3594 | ||
| 3590 | void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { | 3595 | void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { |
| @@ -3840,7 +3845,7 @@ void GMainWindow::OnConfigure() { | |||
| 3840 | 3845 | ||
| 3841 | Settings::values.disabled_addons.clear(); | 3846 | Settings::values.disabled_addons.clear(); |
| 3842 | 3847 | ||
| 3843 | config = std::make_unique<Config>(); | 3848 | config = std::make_unique<QtConfig>(); |
| 3844 | UISettings::values.reset_to_defaults = false; | 3849 | UISettings::values.reset_to_defaults = false; |
| 3845 | 3850 | ||
| 3846 | UISettings::values.game_dirs = std::move(old_game_dirs); | 3851 | UISettings::values.game_dirs = std::move(old_game_dirs); |
| @@ -3875,7 +3880,7 @@ void GMainWindow::OnConfigure() { | |||
| 3875 | 3880 | ||
| 3876 | UISettings::values.configuration_applied = false; | 3881 | UISettings::values.configuration_applied = false; |
| 3877 | 3882 | ||
| 3878 | config->Save(); | 3883 | config->SaveAllValues(); |
| 3879 | 3884 | ||
| 3880 | if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) { | 3885 | if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) { |
| 3881 | render_window->installEventFilter(render_window); | 3886 | render_window->installEventFilter(render_window); |
| @@ -4091,7 +4096,7 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file | |||
| 4091 | UISettings::values.configuration_applied = false; | 4096 | UISettings::values.configuration_applied = false; |
| 4092 | 4097 | ||
| 4093 | if (!is_powered_on) { | 4098 | if (!is_powered_on) { |
| 4094 | config->Save(); | 4099 | config->SaveAllValues(); |
| 4095 | } | 4100 | } |
| 4096 | } | 4101 | } |
| 4097 | 4102 | ||
| @@ -4324,7 +4329,7 @@ void GMainWindow::OnAlbum() { | |||
| 4324 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::PhotoViewer); | 4329 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::PhotoViewer); |
| 4325 | 4330 | ||
| 4326 | const auto filename = QString::fromStdString(album_nca->GetFullPath()); | 4331 | const auto filename = QString::fromStdString(album_nca->GetFullPath()); |
| 4327 | UISettings::values.roms_path = QFileInfo(filename).path(); | 4332 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 4328 | BootGame(filename, AlbumId); | 4333 | BootGame(filename, AlbumId); |
| 4329 | } | 4334 | } |
| 4330 | 4335 | ||
| @@ -4348,7 +4353,7 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { | |||
| 4348 | system->GetAppletManager().SetCabinetMode(mode); | 4353 | system->GetAppletManager().SetCabinetMode(mode); |
| 4349 | 4354 | ||
| 4350 | const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); | 4355 | const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); |
| 4351 | UISettings::values.roms_path = QFileInfo(filename).path(); | 4356 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 4352 | BootGame(filename, CabinetId); | 4357 | BootGame(filename, CabinetId); |
| 4353 | } | 4358 | } |
| 4354 | 4359 | ||
| @@ -4371,7 +4376,7 @@ void GMainWindow::OnMiiEdit() { | |||
| 4371 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit); | 4376 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit); |
| 4372 | 4377 | ||
| 4373 | const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); | 4378 | const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); |
| 4374 | UISettings::values.roms_path = QFileInfo(filename).path(); | 4379 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 4375 | BootGame(filename, MiiEditId); | 4380 | BootGame(filename, MiiEditId); |
| 4376 | } | 4381 | } |
| 4377 | 4382 | ||
| @@ -4396,7 +4401,7 @@ void GMainWindow::OnOpenControllerMenu() { | |||
| 4396 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Controller); | 4401 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Controller); |
| 4397 | 4402 | ||
| 4398 | const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath())); | 4403 | const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath())); |
| 4399 | UISettings::values.roms_path = QFileInfo(filename).path(); | 4404 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 4400 | BootGame(filename, ControllerAppletId); | 4405 | BootGame(filename, ControllerAppletId); |
| 4401 | } | 4406 | } |
| 4402 | 4407 | ||
| @@ -4590,7 +4595,8 @@ void GMainWindow::UpdateStatusBar() { | |||
| 4590 | 4595 | ||
| 4591 | void GMainWindow::UpdateGPUAccuracyButton() { | 4596 | void GMainWindow::UpdateGPUAccuracyButton() { |
| 4592 | const auto gpu_accuracy = Settings::values.gpu_accuracy.GetValue(); | 4597 | const auto gpu_accuracy = Settings::values.gpu_accuracy.GetValue(); |
| 4593 | const auto gpu_accuracy_text = Config::gpu_accuracy_texts_map.find(gpu_accuracy)->second; | 4598 | const auto gpu_accuracy_text = |
| 4599 | ConfigurationShared::gpu_accuracy_texts_map.find(gpu_accuracy)->second; | ||
| 4594 | gpu_accuracy_button->setText(gpu_accuracy_text.toUpper()); | 4600 | gpu_accuracy_button->setText(gpu_accuracy_text.toUpper()); |
| 4595 | gpu_accuracy_button->setChecked(gpu_accuracy != Settings::GpuAccuracy::Normal); | 4601 | gpu_accuracy_button->setChecked(gpu_accuracy != Settings::GpuAccuracy::Normal); |
| 4596 | } | 4602 | } |
| @@ -4599,31 +4605,32 @@ void GMainWindow::UpdateDockedButton() { | |||
| 4599 | const auto console_mode = Settings::values.use_docked_mode.GetValue(); | 4605 | const auto console_mode = Settings::values.use_docked_mode.GetValue(); |
| 4600 | dock_status_button->setChecked(Settings::IsDockedMode()); | 4606 | dock_status_button->setChecked(Settings::IsDockedMode()); |
| 4601 | dock_status_button->setText( | 4607 | dock_status_button->setText( |
| 4602 | Config::use_docked_mode_texts_map.find(console_mode)->second.toUpper()); | 4608 | ConfigurationShared::use_docked_mode_texts_map.find(console_mode)->second.toUpper()); |
| 4603 | } | 4609 | } |
| 4604 | 4610 | ||
| 4605 | void GMainWindow::UpdateAPIText() { | 4611 | void GMainWindow::UpdateAPIText() { |
| 4606 | const auto api = Settings::values.renderer_backend.GetValue(); | 4612 | const auto api = Settings::values.renderer_backend.GetValue(); |
| 4607 | const auto renderer_status_text = Config::renderer_backend_texts_map.find(api)->second; | 4613 | const auto renderer_status_text = |
| 4614 | ConfigurationShared::renderer_backend_texts_map.find(api)->second; | ||
| 4608 | renderer_status_button->setText( | 4615 | renderer_status_button->setText( |
| 4609 | api == Settings::RendererBackend::OpenGL | 4616 | api == Settings::RendererBackend::OpenGL |
| 4610 | ? tr("%1 %2").arg( | 4617 | ? tr("%1 %2").arg(renderer_status_text.toUpper(), |
| 4611 | renderer_status_text.toUpper(), | 4618 | ConfigurationShared::shader_backend_texts_map |
| 4612 | Config::shader_backend_texts_map.find(Settings::values.shader_backend.GetValue()) | 4619 | .find(Settings::values.shader_backend.GetValue()) |
| 4613 | ->second) | 4620 | ->second) |
| 4614 | : renderer_status_text.toUpper()); | 4621 | : renderer_status_text.toUpper()); |
| 4615 | } | 4622 | } |
| 4616 | 4623 | ||
| 4617 | void GMainWindow::UpdateFilterText() { | 4624 | void GMainWindow::UpdateFilterText() { |
| 4618 | const auto filter = Settings::values.scaling_filter.GetValue(); | 4625 | const auto filter = Settings::values.scaling_filter.GetValue(); |
| 4619 | const auto filter_text = Config::scaling_filter_texts_map.find(filter)->second; | 4626 | const auto filter_text = ConfigurationShared::scaling_filter_texts_map.find(filter)->second; |
| 4620 | filter_status_button->setText(filter == Settings::ScalingFilter::Fsr ? tr("FSR") | 4627 | filter_status_button->setText(filter == Settings::ScalingFilter::Fsr ? tr("FSR") |
| 4621 | : filter_text.toUpper()); | 4628 | : filter_text.toUpper()); |
| 4622 | } | 4629 | } |
| 4623 | 4630 | ||
| 4624 | void GMainWindow::UpdateAAText() { | 4631 | void GMainWindow::UpdateAAText() { |
| 4625 | const auto aa_mode = Settings::values.anti_aliasing.GetValue(); | 4632 | const auto aa_mode = Settings::values.anti_aliasing.GetValue(); |
| 4626 | const auto aa_text = Config::anti_aliasing_texts_map.find(aa_mode)->second; | 4633 | const auto aa_text = ConfigurationShared::anti_aliasing_texts_map.find(aa_mode)->second; |
| 4627 | aa_status_button->setText(aa_mode == Settings::AntiAliasing::None | 4634 | aa_status_button->setText(aa_mode == Settings::AntiAliasing::None |
| 4628 | ? QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "NO AA")) | 4635 | ? QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "NO AA")) |
| 4629 | : aa_text.toUpper()); | 4636 | : aa_text.toUpper()); |
| @@ -4926,6 +4933,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { | |||
| 4926 | 4933 | ||
| 4927 | UpdateUISettings(); | 4934 | UpdateUISettings(); |
| 4928 | game_list->SaveInterfaceLayout(); | 4935 | game_list->SaveInterfaceLayout(); |
| 4936 | UISettings::SaveWindowState(); | ||
| 4929 | hotkey_registry.SaveHotkeys(); | 4937 | hotkey_registry.SaveHotkeys(); |
| 4930 | 4938 | ||
| 4931 | // Unload controllers early | 4939 | // Unload controllers early |
| @@ -5080,9 +5088,9 @@ static void AdjustLinkColor() { | |||
| 5080 | } | 5088 | } |
| 5081 | 5089 | ||
| 5082 | void GMainWindow::UpdateUITheme() { | 5090 | void GMainWindow::UpdateUITheme() { |
| 5083 | const QString default_theme = | 5091 | const QString default_theme = QString::fromUtf8( |
| 5084 | QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second); | 5092 | UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second); |
| 5085 | QString current_theme = UISettings::values.theme; | 5093 | QString current_theme = QString::fromStdString(UISettings::values.theme); |
| 5086 | 5094 | ||
| 5087 | if (current_theme.isEmpty()) { | 5095 | if (current_theme.isEmpty()) { |
| 5088 | current_theme = default_theme; | 5096 | current_theme = default_theme; |
| @@ -5110,7 +5118,7 @@ void GMainWindow::UpdateUITheme() { | |||
| 5110 | QFile f(theme_uri); | 5118 | QFile f(theme_uri); |
| 5111 | if (!f.open(QFile::ReadOnly | QFile::Text)) { | 5119 | if (!f.open(QFile::ReadOnly | QFile::Text)) { |
| 5112 | LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme", | 5120 | LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme", |
| 5113 | UISettings::values.theme.toStdString()); | 5121 | UISettings::values.theme); |
| 5114 | current_theme = default_theme; | 5122 | current_theme = default_theme; |
| 5115 | } | 5123 | } |
| 5116 | } | 5124 | } |
| @@ -5123,7 +5131,7 @@ void GMainWindow::UpdateUITheme() { | |||
| 5123 | setStyleSheet(ts.readAll()); | 5131 | setStyleSheet(ts.readAll()); |
| 5124 | } else { | 5132 | } else { |
| 5125 | LOG_ERROR(Frontend, "Unable to set style \"{}\", stylesheet file not found", | 5133 | LOG_ERROR(Frontend, "Unable to set style \"{}\", stylesheet file not found", |
| 5126 | UISettings::values.theme.toStdString()); | 5134 | UISettings::values.theme); |
| 5127 | qApp->setStyleSheet({}); | 5135 | qApp->setStyleSheet({}); |
| 5128 | setStyleSheet({}); | 5136 | setStyleSheet({}); |
| 5129 | } | 5137 | } |
| @@ -5132,27 +5140,28 @@ void GMainWindow::UpdateUITheme() { | |||
| 5132 | void GMainWindow::LoadTranslation() { | 5140 | void GMainWindow::LoadTranslation() { |
| 5133 | bool loaded; | 5141 | bool loaded; |
| 5134 | 5142 | ||
| 5135 | if (UISettings::values.language.isEmpty()) { | 5143 | if (UISettings::values.language.empty()) { |
| 5136 | // If the selected language is empty, use system locale | 5144 | // If the selected language is empty, use system locale |
| 5137 | loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/")); | 5145 | loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/")); |
| 5138 | } else { | 5146 | } else { |
| 5139 | // Otherwise load from the specified file | 5147 | // Otherwise load from the specified file |
| 5140 | loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/")); | 5148 | loaded = translator.load(QString::fromStdString(UISettings::values.language), |
| 5149 | QStringLiteral(":/languages/")); | ||
| 5141 | } | 5150 | } |
| 5142 | 5151 | ||
| 5143 | if (loaded) { | 5152 | if (loaded) { |
| 5144 | qApp->installTranslator(&translator); | 5153 | qApp->installTranslator(&translator); |
| 5145 | } else { | 5154 | } else { |
| 5146 | UISettings::values.language = QStringLiteral("en"); | 5155 | UISettings::values.language = std::string("en"); |
| 5147 | } | 5156 | } |
| 5148 | } | 5157 | } |
| 5149 | 5158 | ||
| 5150 | void GMainWindow::OnLanguageChanged(const QString& locale) { | 5159 | void GMainWindow::OnLanguageChanged(const QString& locale) { |
| 5151 | if (UISettings::values.language != QStringLiteral("en")) { | 5160 | if (UISettings::values.language != std::string("en")) { |
| 5152 | qApp->removeTranslator(&translator); | 5161 | qApp->removeTranslator(&translator); |
| 5153 | } | 5162 | } |
| 5154 | 5163 | ||
| 5155 | UISettings::values.language = locale; | 5164 | UISettings::values.language = locale.toStdString(); |
| 5156 | LoadTranslation(); | 5165 | LoadTranslation(); |
| 5157 | ui->retranslateUi(this); | 5166 | ui->retranslateUi(this); |
| 5158 | multiplayer_state->retranslateUi(); | 5167 | multiplayer_state->retranslateUi(); |
| @@ -5178,7 +5187,7 @@ void GMainWindow::changeEvent(QEvent* event) { | |||
| 5178 | // UpdateUITheme is a decent work around | 5187 | // UpdateUITheme is a decent work around |
| 5179 | if (event->type() == QEvent::PaletteChange) { | 5188 | if (event->type() == QEvent::PaletteChange) { |
| 5180 | const QPalette test_palette(qApp->palette()); | 5189 | const QPalette test_palette(qApp->palette()); |
| 5181 | const QString current_theme = UISettings::values.theme; | 5190 | const QString current_theme = QString::fromStdString(UISettings::values.theme); |
| 5182 | // Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too | 5191 | // Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too |
| 5183 | static QColor last_window_color; | 5192 | static QColor last_window_color; |
| 5184 | const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window); | 5193 | const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window); |
| @@ -5272,7 +5281,8 @@ static void SetHighDPIAttributes() { | |||
| 5272 | } | 5281 | } |
| 5273 | 5282 | ||
| 5274 | int main(int argc, char* argv[]) { | 5283 | int main(int argc, char* argv[]) { |
| 5275 | std::unique_ptr<Config> config = std::make_unique<Config>(); | 5284 | std::unique_ptr<QtConfig> config = std::make_unique<QtConfig>(); |
| 5285 | UISettings::RestoreWindowState(config); | ||
| 5276 | bool has_broken_vulkan = false; | 5286 | bool has_broken_vulkan = false; |
| 5277 | bool is_child = false; | 5287 | bool is_child = false; |
| 5278 | if (CheckEnvVars(&is_child)) { | 5288 | if (CheckEnvVars(&is_child)) { |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 49ee1e1d2..c989c079d 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #include "common/announce_multiplayer_room.h" | 16 | #include "common/announce_multiplayer_room.h" |
| 17 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 18 | #include "configuration/qt_config.h" | ||
| 18 | #include "input_common/drivers/tas_input.h" | 19 | #include "input_common/drivers/tas_input.h" |
| 19 | #include "yuzu/compatibility_list.h" | 20 | #include "yuzu/compatibility_list.h" |
| 20 | #include "yuzu/hotkeys.h" | 21 | #include "yuzu/hotkeys.h" |
| @@ -26,7 +27,7 @@ | |||
| 26 | #include <QtDBus/QtDBus> | 27 | #include <QtDBus/QtDBus> |
| 27 | #endif | 28 | #endif |
| 28 | 29 | ||
| 29 | class Config; | 30 | class QtConfig; |
| 30 | class ClickableLabel; | 31 | class ClickableLabel; |
| 31 | class EmuThread; | 32 | class EmuThread; |
| 32 | class GameList; | 33 | class GameList; |
| @@ -185,7 +186,7 @@ class GMainWindow : public QMainWindow { | |||
| 185 | public: | 186 | public: |
| 186 | void filterBarSetChecked(bool state); | 187 | void filterBarSetChecked(bool state); |
| 187 | void UpdateUITheme(); | 188 | void UpdateUITheme(); |
| 188 | explicit GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan); | 189 | explicit GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan); |
| 189 | ~GMainWindow() override; | 190 | ~GMainWindow() override; |
| 190 | 191 | ||
| 191 | bool DropAction(QDropEvent* event); | 192 | bool DropAction(QDropEvent* event); |
| @@ -521,7 +522,7 @@ private: | |||
| 521 | QSlider* volume_slider = nullptr; | 522 | QSlider* volume_slider = nullptr; |
| 522 | QTimer status_bar_update_timer; | 523 | QTimer status_bar_update_timer; |
| 523 | 524 | ||
| 524 | std::unique_ptr<Config> config; | 525 | std::unique_ptr<QtConfig> config; |
| 525 | 526 | ||
| 526 | // Whether emulation is currently running in yuzu. | 527 | // Whether emulation is currently running in yuzu. |
| 527 | bool emulation_running = false; | 528 | bool emulation_running = false; |
diff --git a/src/yuzu/uisettings.cpp b/src/yuzu/uisettings.cpp index 1c833767b..7bb7e95af 100644 --- a/src/yuzu/uisettings.cpp +++ b/src/yuzu/uisettings.cpp | |||
| @@ -1,6 +1,9 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2016 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2016 Citra Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <QSettings> | ||
| 5 | #include "common/fs/fs.h" | ||
| 6 | #include "common/fs/path_util.h" | ||
| 4 | #include "yuzu/uisettings.h" | 7 | #include "yuzu/uisettings.h" |
| 5 | 8 | ||
| 6 | #ifndef CANNOT_EXPLICITLY_INSTANTIATE | 9 | #ifndef CANNOT_EXPLICITLY_INSTANTIATE |
| @@ -15,6 +18,8 @@ template class Setting<unsigned long long>; | |||
| 15 | } // namespace Settings | 18 | } // namespace Settings |
| 16 | #endif | 19 | #endif |
| 17 | 20 | ||
| 21 | namespace FS = Common::FS; | ||
| 22 | |||
| 18 | namespace UISettings { | 23 | namespace UISettings { |
| 19 | 24 | ||
| 20 | const Themes themes{{ | 25 | const Themes themes{{ |
| @@ -28,10 +33,8 @@ const Themes themes{{ | |||
| 28 | 33 | ||
| 29 | bool IsDarkTheme() { | 34 | bool IsDarkTheme() { |
| 30 | const auto& theme = UISettings::values.theme; | 35 | const auto& theme = UISettings::values.theme; |
| 31 | return theme == QStringLiteral("qdarkstyle") || | 36 | return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") || |
| 32 | theme == QStringLiteral("qdarkstyle_midnight_blue") || | 37 | theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue"); |
| 33 | theme == QStringLiteral("colorful_dark") || | ||
| 34 | theme == QStringLiteral("colorful_midnight_blue"); | ||
| 35 | } | 38 | } |
| 36 | 39 | ||
| 37 | Values values = {}; | 40 | Values values = {}; |
| @@ -52,4 +55,58 @@ u32 CalculateWidth(u32 height, Settings::AspectRatio ratio) { | |||
| 52 | return height * 16 / 9; | 55 | return height * 16 / 9; |
| 53 | } | 56 | } |
| 54 | 57 | ||
| 58 | void SaveWindowState() { | ||
| 59 | const auto window_state_config_loc = | ||
| 60 | FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini"); | ||
| 61 | |||
| 62 | void(FS::CreateParentDir(window_state_config_loc)); | ||
| 63 | QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat); | ||
| 64 | |||
| 65 | config.setValue(QStringLiteral("geometry"), values.geometry); | ||
| 66 | config.setValue(QStringLiteral("state"), values.state); | ||
| 67 | config.setValue(QStringLiteral("geometryRenderWindow"), values.renderwindow_geometry); | ||
| 68 | config.setValue(QStringLiteral("gameListHeaderState"), values.gamelist_header_state); | ||
| 69 | config.setValue(QStringLiteral("microProfileDialogGeometry"), values.microprofile_geometry); | ||
| 70 | |||
| 71 | config.sync(); | ||
| 72 | } | ||
| 73 | |||
| 74 | void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig) { | ||
| 75 | const auto window_state_config_loc = | ||
| 76 | FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini"); | ||
| 77 | |||
| 78 | // Migrate window state from old location | ||
| 79 | if (!FS::Exists(window_state_config_loc) && qtConfig->Exists("UI", "UILayout\\geometry")) { | ||
| 80 | const auto config_loc = | ||
| 81 | FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "qt-config.ini"); | ||
| 82 | QSettings config(QString::fromStdString(config_loc), QSettings::IniFormat); | ||
| 83 | |||
| 84 | config.beginGroup(QStringLiteral("UI")); | ||
| 85 | config.beginGroup(QStringLiteral("UILayout")); | ||
| 86 | values.geometry = config.value(QStringLiteral("geometry")).toByteArray(); | ||
| 87 | values.state = config.value(QStringLiteral("state")).toByteArray(); | ||
| 88 | values.renderwindow_geometry = | ||
| 89 | config.value(QStringLiteral("geometryRenderWindow")).toByteArray(); | ||
| 90 | values.gamelist_header_state = | ||
| 91 | config.value(QStringLiteral("gameListHeaderState")).toByteArray(); | ||
| 92 | values.microprofile_geometry = | ||
| 93 | config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray(); | ||
| 94 | config.endGroup(); | ||
| 95 | config.endGroup(); | ||
| 96 | return; | ||
| 97 | } | ||
| 98 | |||
| 99 | void(FS::CreateParentDir(window_state_config_loc)); | ||
| 100 | const QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat); | ||
| 101 | |||
| 102 | values.geometry = config.value(QStringLiteral("geometry")).toByteArray(); | ||
| 103 | values.state = config.value(QStringLiteral("state")).toByteArray(); | ||
| 104 | values.renderwindow_geometry = | ||
| 105 | config.value(QStringLiteral("geometryRenderWindow")).toByteArray(); | ||
| 106 | values.gamelist_header_state = | ||
| 107 | config.value(QStringLiteral("gameListHeaderState")).toByteArray(); | ||
| 108 | values.microprofile_geometry = | ||
| 109 | config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray(); | ||
| 110 | } | ||
| 111 | |||
| 55 | } // namespace UISettings | 112 | } // namespace UISettings |
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 3485a6347..549a39e1b 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/settings.h" | 15 | #include "common/settings.h" |
| 16 | #include "common/settings_enums.h" | 16 | #include "common/settings_enums.h" |
| 17 | #include "configuration/qt_config.h" | ||
| 17 | 18 | ||
| 18 | using Settings::Category; | 19 | using Settings::Category; |
| 19 | using Settings::ConfirmStop; | 20 | using Settings::ConfirmStop; |
| @@ -37,15 +38,15 @@ namespace UISettings { | |||
| 37 | bool IsDarkTheme(); | 38 | bool IsDarkTheme(); |
| 38 | 39 | ||
| 39 | struct ContextualShortcut { | 40 | struct ContextualShortcut { |
| 40 | QString keyseq; | 41 | std::string keyseq; |
| 41 | QString controller_keyseq; | 42 | std::string controller_keyseq; |
| 42 | int context; | 43 | int context; |
| 43 | bool repeat; | 44 | bool repeat; |
| 44 | }; | 45 | }; |
| 45 | 46 | ||
| 46 | struct Shortcut { | 47 | struct Shortcut { |
| 47 | QString name; | 48 | std::string name; |
| 48 | QString group; | 49 | std::string group; |
| 49 | ContextualShortcut shortcut; | 50 | ContextualShortcut shortcut; |
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| @@ -58,11 +59,19 @@ enum class Theme { | |||
| 58 | MidnightBlueColorful, | 59 | MidnightBlueColorful, |
| 59 | }; | 60 | }; |
| 60 | 61 | ||
| 62 | static constexpr Theme default_theme{ | ||
| 63 | #ifdef _WIN32 | ||
| 64 | Theme::DarkColorful | ||
| 65 | #else | ||
| 66 | Theme::DefaultColorful | ||
| 67 | #endif | ||
| 68 | }; | ||
| 69 | |||
| 61 | using Themes = std::array<std::pair<const char*, const char*>, 6>; | 70 | using Themes = std::array<std::pair<const char*, const char*>, 6>; |
| 62 | extern const Themes themes; | 71 | extern const Themes themes; |
| 63 | 72 | ||
| 64 | struct GameDir { | 73 | struct GameDir { |
| 65 | QString path; | 74 | std::string path; |
| 66 | bool deep_scan = false; | 75 | bool deep_scan = false; |
| 67 | bool expanded = false; | 76 | bool expanded = false; |
| 68 | bool operator==(const GameDir& rhs) const { | 77 | bool operator==(const GameDir& rhs) const { |
| @@ -144,15 +153,15 @@ struct Values { | |||
| 144 | Category::Screenshots}; | 153 | Category::Screenshots}; |
| 145 | Setting<u32> screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots}; | 154 | Setting<u32> screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots}; |
| 146 | 155 | ||
| 147 | QString roms_path; | 156 | std::string roms_path; |
| 148 | QString symbols_path; | 157 | std::string symbols_path; |
| 149 | QString game_dir_deprecated; | 158 | std::string game_dir_deprecated; |
| 150 | bool game_dir_deprecated_deepscan; | 159 | bool game_dir_deprecated_deepscan; |
| 151 | QVector<UISettings::GameDir> game_dirs; | 160 | QVector<GameDir> game_dirs; |
| 152 | QStringList recent_files; | 161 | QStringList recent_files; |
| 153 | QString language; | 162 | std::string language; |
| 154 | 163 | ||
| 155 | QString theme; | 164 | std::string theme; |
| 156 | 165 | ||
| 157 | // Shortcut name <Shortcut, context> | 166 | // Shortcut name <Shortcut, context> |
| 158 | std::vector<Shortcut> shortcuts; | 167 | std::vector<Shortcut> shortcuts; |
| @@ -206,6 +215,54 @@ extern Values values; | |||
| 206 | 215 | ||
| 207 | u32 CalculateWidth(u32 height, Settings::AspectRatio ratio); | 216 | u32 CalculateWidth(u32 height, Settings::AspectRatio ratio); |
| 208 | 217 | ||
| 218 | void SaveWindowState(); | ||
| 219 | void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig); | ||
| 220 | |||
| 221 | // This shouldn't have anything except static initializers (no functions). So | ||
| 222 | // QKeySequence(...).toString() is NOT ALLOWED HERE. | ||
| 223 | // This must be in alphabetical order according to action name as it must have the same order as | ||
| 224 | // UISetting::values.shortcuts, which is alphabetically ordered. | ||
| 225 | // clang-format off | ||
| 226 | const std::array<Shortcut, 23> default_hotkeys{{ | ||
| 227 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}}, | ||
| 228 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}}, | ||
| 229 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}}, | ||
| 230 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+P"), std::string("Screenshot"), Qt::WidgetWithChildrenShortcut, false}}, | ||
| 231 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F8"), std::string("Home+L"), Qt::ApplicationShortcut, false}}, | ||
| 232 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F10"), std::string("Home+X"), Qt::ApplicationShortcut, false}}, | ||
| 233 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F9"), std::string("Home+R"), Qt::ApplicationShortcut, false}}, | ||
| 234 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F4"), std::string("Home+Plus"), Qt::WindowShortcut, false}}, | ||
| 235 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Esc"), std::string(""), Qt::WindowShortcut, false}}, | ||
| 236 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+Q"), std::string("Home+Minus"), Qt::WindowShortcut, false}}, | ||
| 237 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}}, | ||
| 238 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}}, | ||
| 239 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}}, | ||
| 240 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F6"), std::string("R+Plus+Minus"), Qt::WindowShortcut, false}}, | ||
| 241 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F5"), std::string("L+Plus+Minus"), Qt::WindowShortcut, false}}, | ||
| 242 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F7"), std::string(""), Qt::ApplicationShortcut, false}}, | ||
| 243 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F6"), std::string(""), Qt::ApplicationShortcut, false}}, | ||
| 244 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F5"), std::string(""), Qt::ApplicationShortcut, false}}, | ||
| 245 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F"), std::string(""), Qt::WindowShortcut, false}}, | ||
| 246 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+U"), std::string("Home+Y"), Qt::ApplicationShortcut, false}}, | ||
| 247 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F9"), std::string(""), Qt::ApplicationShortcut, false}}, | ||
| 248 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string(""), std::string(""), Qt::ApplicationShortcut, false}}, | ||
| 249 | {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+S"), std::string(""), Qt::WindowShortcut, false}}, | ||
| 250 | }}; | ||
| 251 | // clang-format on | ||
| 252 | |||
| 209 | } // namespace UISettings | 253 | } // namespace UISettings |
| 210 | 254 | ||
| 211 | Q_DECLARE_METATYPE(UISettings::GameDir*); | 255 | Q_DECLARE_METATYPE(UISettings::GameDir*); |
| 256 | |||
| 257 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT | ||
| 258 | Q_DECLARE_METATYPE(Settings::CpuAccuracy); | ||
| 259 | Q_DECLARE_METATYPE(Settings::GpuAccuracy); | ||
| 260 | Q_DECLARE_METATYPE(Settings::FullscreenMode); | ||
| 261 | Q_DECLARE_METATYPE(Settings::NvdecEmulation); | ||
| 262 | Q_DECLARE_METATYPE(Settings::ResolutionSetup); | ||
| 263 | Q_DECLARE_METATYPE(Settings::ScalingFilter); | ||
| 264 | Q_DECLARE_METATYPE(Settings::AntiAliasing); | ||
| 265 | Q_DECLARE_METATYPE(Settings::RendererBackend); | ||
| 266 | Q_DECLARE_METATYPE(Settings::ShaderBackend); | ||
| 267 | Q_DECLARE_METATYPE(Settings::AstcRecompression); | ||
| 268 | Q_DECLARE_METATYPE(Settings::AstcDecodeMode); | ||
diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index 46eddf423..fbeba8813 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt | |||
| @@ -13,9 +13,6 @@ function(create_resource file output filename) | |||
| 13 | endfunction() | 13 | endfunction() |
| 14 | 14 | ||
| 15 | add_executable(yuzu-cmd | 15 | add_executable(yuzu-cmd |
| 16 | config.cpp | ||
| 17 | config.h | ||
| 18 | default_ini.h | ||
| 19 | emu_window/emu_window_sdl2.cpp | 16 | emu_window/emu_window_sdl2.cpp |
| 20 | emu_window/emu_window_sdl2.h | 17 | emu_window/emu_window_sdl2.h |
| 21 | emu_window/emu_window_sdl2_gl.cpp | 18 | emu_window/emu_window_sdl2_gl.cpp |
| @@ -25,14 +22,16 @@ add_executable(yuzu-cmd | |||
| 25 | emu_window/emu_window_sdl2_vk.cpp | 22 | emu_window/emu_window_sdl2_vk.cpp |
| 26 | emu_window/emu_window_sdl2_vk.h | 23 | emu_window/emu_window_sdl2_vk.h |
| 27 | precompiled_headers.h | 24 | precompiled_headers.h |
| 25 | sdl_config.cpp | ||
| 26 | sdl_config.h | ||
| 28 | yuzu.cpp | 27 | yuzu.cpp |
| 29 | yuzu.rc | 28 | yuzu.rc |
| 30 | ) | 29 | ) |
| 31 | 30 | ||
| 32 | create_target_directory_groups(yuzu-cmd) | 31 | create_target_directory_groups(yuzu-cmd) |
| 33 | 32 | ||
| 34 | target_link_libraries(yuzu-cmd PRIVATE common core input_common) | 33 | target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common) |
| 35 | target_link_libraries(yuzu-cmd PRIVATE inih::INIReader glad) | 34 | target_link_libraries(yuzu-cmd PRIVATE glad) |
| 36 | if (MSVC) | 35 | if (MSVC) |
| 37 | target_link_libraries(yuzu-cmd PRIVATE getopt) | 36 | target_link_libraries(yuzu-cmd PRIVATE getopt) |
| 38 | endif() | 37 | endif() |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp deleted file mode 100644 index 0d25ff400..000000000 --- a/src/yuzu_cmd/config.cpp +++ /dev/null | |||
| @@ -1,279 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2014 Citra Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <memory> | ||
| 5 | #include <optional> | ||
| 6 | #include <sstream> | ||
| 7 | #include <INIReader.h> | ||
| 8 | #include <SDL.h> | ||
| 9 | #include "common/fs/file.h" | ||
| 10 | #include "common/fs/fs.h" | ||
| 11 | #include "common/fs/path_util.h" | ||
| 12 | #include "common/logging/log.h" | ||
| 13 | #include "common/settings.h" | ||
| 14 | #include "core/hle/service/acc/profile_manager.h" | ||
| 15 | #include "input_common/main.h" | ||
| 16 | #include "yuzu_cmd/config.h" | ||
| 17 | #include "yuzu_cmd/default_ini.h" | ||
| 18 | |||
| 19 | namespace FS = Common::FS; | ||
| 20 | |||
| 21 | const std::filesystem::path default_config_path = | ||
| 22 | FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini"; | ||
| 23 | |||
| 24 | Config::Config(std::optional<std::filesystem::path> config_path) | ||
| 25 | : sdl2_config_loc{config_path.value_or(default_config_path)}, | ||
| 26 | sdl2_config{std::make_unique<INIReader>(FS::PathToUTF8String(sdl2_config_loc))} { | ||
| 27 | Reload(); | ||
| 28 | } | ||
| 29 | |||
| 30 | Config::~Config() = default; | ||
| 31 | |||
| 32 | bool Config::LoadINI(const std::string& default_contents, bool retry) { | ||
| 33 | const auto config_loc_str = FS::PathToUTF8String(sdl2_config_loc); | ||
| 34 | if (sdl2_config->ParseError() < 0) { | ||
| 35 | if (retry) { | ||
| 36 | LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", | ||
| 37 | config_loc_str); | ||
| 38 | |||
| 39 | void(FS::CreateParentDir(sdl2_config_loc)); | ||
| 40 | void(FS::WriteStringToFile(sdl2_config_loc, FS::FileType::TextFile, default_contents)); | ||
| 41 | |||
| 42 | sdl2_config = std::make_unique<INIReader>(config_loc_str); | ||
| 43 | |||
| 44 | return LoadINI(default_contents, false); | ||
| 45 | } | ||
| 46 | LOG_ERROR(Config, "Failed."); | ||
| 47 | return false; | ||
| 48 | } | ||
| 49 | LOG_INFO(Config, "Successfully loaded {}", config_loc_str); | ||
| 50 | return true; | ||
| 51 | } | ||
| 52 | |||
| 53 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons = { | ||
| 54 | SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T, | ||
| 55 | SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W, | ||
| 56 | SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B, | ||
| 57 | }; | ||
| 58 | |||
| 59 | static const std::array<int, Settings::NativeMotion::NumMotions> default_motions = { | ||
| 60 | SDL_SCANCODE_7, | ||
| 61 | SDL_SCANCODE_8, | ||
| 62 | }; | ||
| 63 | |||
| 64 | static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs{{ | ||
| 65 | { | ||
| 66 | SDL_SCANCODE_UP, | ||
| 67 | SDL_SCANCODE_DOWN, | ||
| 68 | SDL_SCANCODE_LEFT, | ||
| 69 | SDL_SCANCODE_RIGHT, | ||
| 70 | SDL_SCANCODE_D, | ||
| 71 | }, | ||
| 72 | { | ||
| 73 | SDL_SCANCODE_I, | ||
| 74 | SDL_SCANCODE_K, | ||
| 75 | SDL_SCANCODE_J, | ||
| 76 | SDL_SCANCODE_L, | ||
| 77 | SDL_SCANCODE_D, | ||
| 78 | }, | ||
| 79 | }}; | ||
| 80 | |||
| 81 | template <> | ||
| 82 | void Config::ReadSetting(const std::string& group, Settings::Setting<std::string>& setting) { | ||
| 83 | std::string setting_value = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault()); | ||
| 84 | if (setting_value.empty()) { | ||
| 85 | setting_value = setting.GetDefault(); | ||
| 86 | } | ||
| 87 | setting = std::move(setting_value); | ||
| 88 | } | ||
| 89 | |||
| 90 | template <> | ||
| 91 | void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) { | ||
| 92 | setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault()); | ||
| 93 | } | ||
| 94 | |||
| 95 | template <typename Type, bool ranged> | ||
| 96 | void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) { | ||
| 97 | setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(), | ||
| 98 | static_cast<long>(setting.GetDefault()))); | ||
| 99 | } | ||
| 100 | |||
| 101 | void Config::ReadCategory(Settings::Category category) { | ||
| 102 | for (const auto setting : Settings::values.linkage.by_category[category]) { | ||
| 103 | const char* category_name = [&]() { | ||
| 104 | if (category == Settings::Category::Controls) { | ||
| 105 | // For compatibility with older configs | ||
| 106 | return "ControlsGeneral"; | ||
| 107 | } else { | ||
| 108 | return Settings::TranslateCategory(category); | ||
| 109 | } | ||
| 110 | }(); | ||
| 111 | std::string setting_value = | ||
| 112 | sdl2_config->Get(category_name, setting->GetLabel(), setting->DefaultToString()); | ||
| 113 | setting->LoadString(setting_value); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | void Config::ReadValues() { | ||
| 118 | // Controls | ||
| 119 | ReadCategory(Settings::Category::Controls); | ||
| 120 | |||
| 121 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | ||
| 122 | auto& player = Settings::values.players.GetValue()[p]; | ||
| 123 | |||
| 124 | const auto group = fmt::format("ControlsP{}", p); | ||
| 125 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 126 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 127 | player.buttons[i] = | ||
| 128 | sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param); | ||
| 129 | if (player.buttons[i].empty()) { | ||
| 130 | player.buttons[i] = default_param; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 135 | std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 136 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 137 | default_analogs[i][3], default_analogs[i][4], 0.5f); | ||
| 138 | player.analogs[i] = | ||
| 139 | sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param); | ||
| 140 | if (player.analogs[i].empty()) { | ||
| 141 | player.analogs[i] = default_param; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | ||
| 146 | const std::string default_param = | ||
| 147 | InputCommon::GenerateKeyboardParam(default_motions[i]); | ||
| 148 | auto& player_motions = player.motions[i]; | ||
| 149 | |||
| 150 | player_motions = | ||
| 151 | sdl2_config->Get(group, Settings::NativeMotion::mapping[i], default_param); | ||
| 152 | if (player_motions.empty()) { | ||
| 153 | player_motions = default_param; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | player.connected = sdl2_config->GetBoolean(group, "connected", false); | ||
| 158 | } | ||
| 159 | |||
| 160 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 161 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 162 | Settings::values.debug_pad_buttons[i] = sdl2_config->Get( | ||
| 163 | "ControlsGeneral", std::string("debug_pad_") + Settings::NativeButton::mapping[i], | ||
| 164 | default_param); | ||
| 165 | if (Settings::values.debug_pad_buttons[i].empty()) | ||
| 166 | Settings::values.debug_pad_buttons[i] = default_param; | ||
| 167 | } | ||
| 168 | |||
| 169 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 170 | std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 171 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 172 | default_analogs[i][3], default_analogs[i][4], 0.5f); | ||
| 173 | Settings::values.debug_pad_analogs[i] = sdl2_config->Get( | ||
| 174 | "ControlsGeneral", std::string("debug_pad_") + Settings::NativeAnalog::mapping[i], | ||
| 175 | default_param); | ||
| 176 | if (Settings::values.debug_pad_analogs[i].empty()) | ||
| 177 | Settings::values.debug_pad_analogs[i] = default_param; | ||
| 178 | } | ||
| 179 | |||
| 180 | Settings::values.touchscreen.enabled = | ||
| 181 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); | ||
| 182 | Settings::values.touchscreen.rotation_angle = | ||
| 183 | sdl2_config->GetInteger("ControlsGeneral", "touch_angle", 0); | ||
| 184 | Settings::values.touchscreen.diameter_x = | ||
| 185 | sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_x", 15); | ||
| 186 | Settings::values.touchscreen.diameter_y = | ||
| 187 | sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_y", 15); | ||
| 188 | |||
| 189 | int num_touch_from_button_maps = | ||
| 190 | sdl2_config->GetInteger("ControlsGeneral", "touch_from_button_map", 0); | ||
| 191 | if (num_touch_from_button_maps > 0) { | ||
| 192 | for (int i = 0; i < num_touch_from_button_maps; ++i) { | ||
| 193 | Settings::TouchFromButtonMap map; | ||
| 194 | map.name = sdl2_config->Get("ControlsGeneral", | ||
| 195 | std::string("touch_from_button_maps_") + std::to_string(i) + | ||
| 196 | std::string("_name"), | ||
| 197 | "default"); | ||
| 198 | const int num_touch_maps = sdl2_config->GetInteger( | ||
| 199 | "ControlsGeneral", | ||
| 200 | std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"), | ||
| 201 | 0); | ||
| 202 | map.buttons.reserve(num_touch_maps); | ||
| 203 | |||
| 204 | for (int j = 0; j < num_touch_maps; ++j) { | ||
| 205 | std::string touch_mapping = | ||
| 206 | sdl2_config->Get("ControlsGeneral", | ||
| 207 | std::string("touch_from_button_maps_") + std::to_string(i) + | ||
| 208 | std::string("_bind_") + std::to_string(j), | ||
| 209 | ""); | ||
| 210 | map.buttons.emplace_back(std::move(touch_mapping)); | ||
| 211 | } | ||
| 212 | |||
| 213 | Settings::values.touch_from_button_maps.emplace_back(std::move(map)); | ||
| 214 | } | ||
| 215 | } else { | ||
| 216 | Settings::values.touch_from_button_maps.emplace_back( | ||
| 217 | Settings::TouchFromButtonMap{"default", {}}); | ||
| 218 | num_touch_from_button_maps = 1; | ||
| 219 | } | ||
| 220 | Settings::values.touch_from_button_map_index = std::clamp( | ||
| 221 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); | ||
| 222 | |||
| 223 | ReadCategory(Settings::Category::Audio); | ||
| 224 | ReadCategory(Settings::Category::Core); | ||
| 225 | ReadCategory(Settings::Category::Cpu); | ||
| 226 | ReadCategory(Settings::Category::CpuDebug); | ||
| 227 | ReadCategory(Settings::Category::CpuUnsafe); | ||
| 228 | ReadCategory(Settings::Category::Renderer); | ||
| 229 | ReadCategory(Settings::Category::RendererAdvanced); | ||
| 230 | ReadCategory(Settings::Category::RendererDebug); | ||
| 231 | ReadCategory(Settings::Category::System); | ||
| 232 | ReadCategory(Settings::Category::SystemAudio); | ||
| 233 | ReadCategory(Settings::Category::DataStorage); | ||
| 234 | ReadCategory(Settings::Category::Debugging); | ||
| 235 | ReadCategory(Settings::Category::DebuggingGraphics); | ||
| 236 | ReadCategory(Settings::Category::Miscellaneous); | ||
| 237 | ReadCategory(Settings::Category::Network); | ||
| 238 | ReadCategory(Settings::Category::WebService); | ||
| 239 | |||
| 240 | // Data Storage | ||
| 241 | FS::SetYuzuPath(FS::YuzuPath::NANDDir, | ||
| 242 | sdl2_config->Get("Data Storage", "nand_directory", | ||
| 243 | FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); | ||
| 244 | FS::SetYuzuPath(FS::YuzuPath::SDMCDir, | ||
| 245 | sdl2_config->Get("Data Storage", "sdmc_directory", | ||
| 246 | FS::GetYuzuPathString(FS::YuzuPath::SDMCDir))); | ||
| 247 | FS::SetYuzuPath(FS::YuzuPath::LoadDir, | ||
| 248 | sdl2_config->Get("Data Storage", "load_directory", | ||
| 249 | FS::GetYuzuPathString(FS::YuzuPath::LoadDir))); | ||
| 250 | FS::SetYuzuPath(FS::YuzuPath::DumpDir, | ||
| 251 | sdl2_config->Get("Data Storage", "dump_directory", | ||
| 252 | FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); | ||
| 253 | |||
| 254 | // Debugging | ||
| 255 | Settings::values.record_frame_times = | ||
| 256 | sdl2_config->GetBoolean("Debugging", "record_frame_times", false); | ||
| 257 | |||
| 258 | const auto title_list = sdl2_config->Get("AddOns", "title_ids", ""); | ||
| 259 | std::stringstream ss(title_list); | ||
| 260 | std::string line; | ||
| 261 | while (std::getline(ss, line, '|')) { | ||
| 262 | const auto title_id = std::strtoul(line.c_str(), nullptr, 16); | ||
| 263 | const auto disabled_list = sdl2_config->Get("AddOns", "disabled_" + line, ""); | ||
| 264 | |||
| 265 | std::stringstream inner_ss(disabled_list); | ||
| 266 | std::string inner_line; | ||
| 267 | std::vector<std::string> out; | ||
| 268 | while (std::getline(inner_ss, inner_line, '|')) { | ||
| 269 | out.push_back(inner_line); | ||
| 270 | } | ||
| 271 | |||
| 272 | Settings::values.disabled_addons.insert_or_assign(title_id, out); | ||
| 273 | } | ||
| 274 | } | ||
| 275 | |||
| 276 | void Config::Reload() { | ||
| 277 | LoadINI(DefaultINI::sdl2_config_file); | ||
| 278 | ReadValues(); | ||
| 279 | } | ||
diff --git a/src/yuzu_cmd/config.h b/src/yuzu_cmd/config.h deleted file mode 100644 index 512591a39..000000000 --- a/src/yuzu_cmd/config.h +++ /dev/null | |||
| @@ -1,38 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2014 Citra Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <filesystem> | ||
| 7 | #include <memory> | ||
| 8 | #include <optional> | ||
| 9 | #include <string> | ||
| 10 | |||
| 11 | #include "common/settings.h" | ||
| 12 | |||
| 13 | class INIReader; | ||
| 14 | |||
| 15 | class Config { | ||
| 16 | std::filesystem::path sdl2_config_loc; | ||
| 17 | std::unique_ptr<INIReader> sdl2_config; | ||
| 18 | |||
| 19 | bool LoadINI(const std::string& default_contents = "", bool retry = true); | ||
| 20 | void ReadValues(); | ||
| 21 | |||
| 22 | public: | ||
| 23 | explicit Config(std::optional<std::filesystem::path> config_path); | ||
| 24 | ~Config(); | ||
| 25 | |||
| 26 | void Reload(); | ||
| 27 | |||
| 28 | private: | ||
| 29 | /** | ||
| 30 | * Applies a value read from the sdl2_config to a Setting. | ||
| 31 | * | ||
| 32 | * @param group The name of the INI group | ||
| 33 | * @param setting The yuzu setting to modify | ||
| 34 | */ | ||
| 35 | template <typename Type, bool ranged> | ||
| 36 | void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting); | ||
| 37 | void ReadCategory(Settings::Category category); | ||
| 38 | }; | ||
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h deleted file mode 100644 index 119e22183..000000000 --- a/src/yuzu_cmd/default_ini.h +++ /dev/null | |||
| @@ -1,553 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2014 Citra Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | namespace DefaultINI { | ||
| 7 | |||
| 8 | const char* sdl2_config_file = | ||
| 9 | R"( | ||
| 10 | [ControlsP0] | ||
| 11 | # The input devices and parameters for each Switch native input | ||
| 12 | # The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ... | ||
| 13 | # It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..." | ||
| 14 | # Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values | ||
| 15 | |||
| 16 | # Indicates if this player should be connected at boot | ||
| 17 | # 0 (default): Disabled, 1: Enabled | ||
| 18 | connected= | ||
| 19 | |||
| 20 | # for button input, the following devices are available: | ||
| 21 | # - "keyboard" (default) for keyboard input. Required parameters: | ||
| 22 | # - "code": the code of the key to bind | ||
| 23 | # - "sdl" for joystick input using SDL. Required parameters: | ||
| 24 | # - "guid": SDL identification GUID of the joystick | ||
| 25 | # - "port": the index of the joystick to bind | ||
| 26 | # - "button"(optional): the index of the button to bind | ||
| 27 | # - "hat"(optional): the index of the hat to bind as direction buttons | ||
| 28 | # - "axis"(optional): the index of the axis to bind | ||
| 29 | # - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right" | ||
| 30 | # - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is | ||
| 31 | # triggered if the axis value crosses | ||
| 32 | # - "direction"(only used for axis): "+" means the button is triggered when the axis value | ||
| 33 | # is greater than the threshold; "-" means the button is triggered when the axis value | ||
| 34 | # is smaller than the threshold | ||
| 35 | button_a= | ||
| 36 | button_b= | ||
| 37 | button_x= | ||
| 38 | button_y= | ||
| 39 | button_lstick= | ||
| 40 | button_rstick= | ||
| 41 | button_l= | ||
| 42 | button_r= | ||
| 43 | button_zl= | ||
| 44 | button_zr= | ||
| 45 | button_plus= | ||
| 46 | button_minus= | ||
| 47 | button_dleft= | ||
| 48 | button_dup= | ||
| 49 | button_dright= | ||
| 50 | button_ddown= | ||
| 51 | button_lstick_left= | ||
| 52 | button_lstick_up= | ||
| 53 | button_lstick_right= | ||
| 54 | button_lstick_down= | ||
| 55 | button_sl= | ||
| 56 | button_sr= | ||
| 57 | button_home= | ||
| 58 | button_screenshot= | ||
| 59 | |||
| 60 | # for analog input, the following devices are available: | ||
| 61 | # - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters: | ||
| 62 | # - "up", "down", "left", "right": sub-devices for each direction. | ||
| 63 | # Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00" | ||
| 64 | # - "modifier": sub-devices as a modifier. | ||
| 65 | # - "modifier_scale": a float number representing the applied modifier scale to the analog input. | ||
| 66 | # Must be in range of 0.0-1.0. Defaults to 0.5 | ||
| 67 | # - "sdl" for joystick input using SDL. Required parameters: | ||
| 68 | # - "guid": SDL identification GUID of the joystick | ||
| 69 | # - "port": the index of the joystick to bind | ||
| 70 | # - "axis_x": the index of the axis to bind as x-axis (default to 0) | ||
| 71 | # - "axis_y": the index of the axis to bind as y-axis (default to 1) | ||
| 72 | lstick= | ||
| 73 | rstick= | ||
| 74 | |||
| 75 | # for motion input, the following devices are available: | ||
| 76 | # - "keyboard" (default) for emulating random motion input from buttons. Required parameters: | ||
| 77 | # - "code": the code of the key to bind | ||
| 78 | # - "sdl" for motion input using SDL. Required parameters: | ||
| 79 | # - "guid": SDL identification GUID of the joystick | ||
| 80 | # - "port": the index of the joystick to bind | ||
| 81 | # - "motion": the index of the motion sensor to bind | ||
| 82 | # - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters: | ||
| 83 | # - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001" | ||
| 84 | # - "port": the port of the cemu hook server | ||
| 85 | # - "pad": the index of the joystick | ||
| 86 | # - "motion": the index of the motion sensor of the joystick to bind | ||
| 87 | motionleft= | ||
| 88 | motionright= | ||
| 89 | |||
| 90 | [ControlsGeneral] | ||
| 91 | # To use the debug_pad, prepend `debug_pad_` before each button setting above. | ||
| 92 | # i.e. debug_pad_button_a= | ||
| 93 | |||
| 94 | # Enable debug pad inputs to the guest | ||
| 95 | # 0 (default): Disabled, 1: Enabled | ||
| 96 | debug_pad_enabled = | ||
| 97 | |||
| 98 | # Enable sdl raw input. Allows to configure up to 8 xinput controllers. | ||
| 99 | # 0 (default): Disabled, 1: Enabled | ||
| 100 | enable_raw_input = | ||
| 101 | |||
| 102 | # Enable yuzu joycon driver instead of SDL drive. | ||
| 103 | # 0: Disabled, 1 (default): Enabled | ||
| 104 | enable_joycon_driver = | ||
| 105 | |||
| 106 | # Emulates an analog input from buttons. Allowing to dial any angle. | ||
| 107 | # 0 (default): Disabled, 1: Enabled | ||
| 108 | emulate_analog_keyboard = | ||
| 109 | |||
| 110 | # Whether to enable or disable vibration | ||
| 111 | # 0: Disabled, 1 (default): Enabled | ||
| 112 | vibration_enabled= | ||
| 113 | |||
| 114 | # Whether to enable or disable accurate vibrations | ||
| 115 | # 0 (default): Disabled, 1: Enabled | ||
| 116 | enable_accurate_vibrations= | ||
| 117 | |||
| 118 | # Enables controller motion inputs | ||
| 119 | # 0: Disabled, 1 (default): Enabled | ||
| 120 | motion_enabled = | ||
| 121 | |||
| 122 | # Defines the udp device's touch screen coordinate system for cemuhookudp devices | ||
| 123 | # - "min_x", "min_y", "max_x", "max_y" | ||
| 124 | touch_device= | ||
| 125 | |||
| 126 | # for mapping buttons to touch inputs. | ||
| 127 | #touch_from_button_map=1 | ||
| 128 | #touch_from_button_maps_0_name=default | ||
| 129 | #touch_from_button_maps_0_count=2 | ||
| 130 | #touch_from_button_maps_0_bind_0=foo | ||
| 131 | #touch_from_button_maps_0_bind_1=bar | ||
| 132 | # etc. | ||
| 133 | |||
| 134 | # List of Cemuhook UDP servers, delimited by ','. | ||
| 135 | # Default: 127.0.0.1:26760 | ||
| 136 | # Example: 127.0.0.1:26760,123.4.5.67:26761 | ||
| 137 | udp_input_servers = | ||
| 138 | |||
| 139 | # Enable controlling an axis via a mouse input. | ||
| 140 | # 0 (default): Off, 1: On | ||
| 141 | mouse_panning = | ||
| 142 | |||
| 143 | # Set mouse panning horizontal sensitivity. | ||
| 144 | # Default: 50.0 | ||
| 145 | mouse_panning_x_sensitivity = | ||
| 146 | |||
| 147 | # Set mouse panning vertical sensitivity. | ||
| 148 | # Default: 50.0 | ||
| 149 | mouse_panning_y_sensitivity = | ||
| 150 | |||
| 151 | # Set mouse panning deadzone horizontal counterweight. | ||
| 152 | # Default: 0.0 | ||
| 153 | mouse_panning_deadzone_x_counterweight = | ||
| 154 | |||
| 155 | # Set mouse panning deadzone vertical counterweight. | ||
| 156 | # Default: 0.0 | ||
| 157 | mouse_panning_deadzone_y_counterweight = | ||
| 158 | |||
| 159 | # Set mouse panning stick decay strength. | ||
| 160 | # Default: 22.0 | ||
| 161 | mouse_panning_decay_strength = | ||
| 162 | |||
| 163 | # Set mouse panning stick minimum decay. | ||
| 164 | # Default: 5.0 | ||
| 165 | mouse_panning_minimum_decay = | ||
| 166 | |||
| 167 | # Emulate an analog control stick from keyboard inputs. | ||
| 168 | # 0 (default): Disabled, 1: Enabled | ||
| 169 | emulate_analog_keyboard = | ||
| 170 | |||
| 171 | # Enable mouse inputs to the guest | ||
| 172 | # 0 (default): Disabled, 1: Enabled | ||
| 173 | mouse_enabled = | ||
| 174 | |||
| 175 | # Enable keyboard inputs to the guest | ||
| 176 | # 0 (default): Disabled, 1: Enabled | ||
| 177 | keyboard_enabled = | ||
| 178 | |||
| 179 | )" | ||
| 180 | R"( | ||
| 181 | [Core] | ||
| 182 | # Whether to use multi-core for CPU emulation | ||
| 183 | # 0: Disabled, 1 (default): Enabled | ||
| 184 | use_multi_core = | ||
| 185 | |||
| 186 | # Enable unsafe extended guest system memory layout (8GB DRAM) | ||
| 187 | # 0 (default): Disabled, 1: Enabled | ||
| 188 | use_unsafe_extended_memory_layout = | ||
| 189 | |||
| 190 | [Cpu] | ||
| 191 | # Adjusts various optimizations. | ||
| 192 | # Auto-select mode enables choice unsafe optimizations. | ||
| 193 | # Accurate enables only safe optimizations. | ||
| 194 | # Unsafe allows any unsafe optimizations. | ||
| 195 | # 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations | ||
| 196 | cpu_accuracy = | ||
| 197 | |||
| 198 | # Allow disabling safe optimizations. | ||
| 199 | # 0 (default): Disabled, 1: Enabled | ||
| 200 | cpu_debug_mode = | ||
| 201 | |||
| 202 | # Enable inline page tables optimization (faster guest memory access) | ||
| 203 | # 0: Disabled, 1 (default): Enabled | ||
| 204 | cpuopt_page_tables = | ||
| 205 | |||
| 206 | # Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps) | ||
| 207 | # 0: Disabled, 1 (default): Enabled | ||
| 208 | cpuopt_block_linking = | ||
| 209 | |||
| 210 | # Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns) | ||
| 211 | # 0: Disabled, 1 (default): Enabled | ||
| 212 | cpuopt_return_stack_buffer = | ||
| 213 | |||
| 214 | # Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture) | ||
| 215 | # 0: Disabled, 1 (default): Enabled | ||
| 216 | cpuopt_fast_dispatcher = | ||
| 217 | |||
| 218 | # Enable context elimination CPU Optimization (reduce host memory use for guest context) | ||
| 219 | # 0: Disabled, 1 (default): Enabled | ||
| 220 | cpuopt_context_elimination = | ||
| 221 | |||
| 222 | # Enable constant propagation CPU optimization (basic IR optimization) | ||
| 223 | # 0: Disabled, 1 (default): Enabled | ||
| 224 | cpuopt_const_prop = | ||
| 225 | |||
| 226 | # Enable miscellaneous CPU optimizations (basic IR optimization) | ||
| 227 | # 0: Disabled, 1 (default): Enabled | ||
| 228 | cpuopt_misc_ir = | ||
| 229 | |||
| 230 | # Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access) | ||
| 231 | # 0: Disabled, 1 (default): Enabled | ||
| 232 | cpuopt_reduce_misalign_checks = | ||
| 233 | |||
| 234 | # Enable Host MMU Emulation (faster guest memory access) | ||
| 235 | # 0: Disabled, 1 (default): Enabled | ||
| 236 | cpuopt_fastmem = | ||
| 237 | |||
| 238 | # Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access) | ||
| 239 | # 0: Disabled, 1 (default): Enabled | ||
| 240 | cpuopt_fastmem_exclusives = | ||
| 241 | |||
| 242 | # Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access) | ||
| 243 | # 0: Disabled, 1 (default): Enabled | ||
| 244 | cpuopt_recompile_exclusives = | ||
| 245 | |||
| 246 | # Enable optimization to ignore invalid memory accesses (faster guest memory access) | ||
| 247 | # 0: Disabled, 1 (default): Enabled | ||
| 248 | cpuopt_ignore_memory_aborts = | ||
| 249 | |||
| 250 | # Enable unfuse FMA (improve performance on CPUs without FMA) | ||
| 251 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 252 | # 0: Disabled, 1 (default): Enabled | ||
| 253 | cpuopt_unsafe_unfuse_fma = | ||
| 254 | |||
| 255 | # Enable faster FRSQRTE and FRECPE | ||
| 256 | # Only enabled if cpu_accuracy is set to Unsafe. | ||
| 257 | # 0: Disabled, 1 (default): Enabled | ||
| 258 | cpuopt_unsafe_reduce_fp_error = | ||
| 259 | |||
| 260 | # Enable faster ASIMD instructions (32 bits only) | ||
| 261 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 262 | # 0: Disabled, 1 (default): Enabled | ||
| 263 | cpuopt_unsafe_ignore_standard_fpcr = | ||
| 264 | |||
| 265 | # Enable inaccurate NaN handling | ||
| 266 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 267 | # 0: Disabled, 1 (default): Enabled | ||
| 268 | cpuopt_unsafe_inaccurate_nan = | ||
| 269 | |||
| 270 | # Disable address space checks (64 bits only) | ||
| 271 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 272 | # 0: Disabled, 1 (default): Enabled | ||
| 273 | cpuopt_unsafe_fastmem_check = | ||
| 274 | |||
| 275 | # Enable faster exclusive instructions | ||
| 276 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | ||
| 277 | # 0: Disabled, 1 (default): Enabled | ||
| 278 | cpuopt_unsafe_ignore_global_monitor = | ||
| 279 | |||
| 280 | )" | ||
| 281 | R"( | ||
| 282 | [Renderer] | ||
| 283 | # Which backend API to use. | ||
| 284 | # 0: OpenGL, 1 (default): Vulkan | ||
| 285 | backend = | ||
| 286 | |||
| 287 | # Whether to enable asynchronous presentation (Vulkan only) | ||
| 288 | # 0 (default): Off, 1: On | ||
| 289 | async_presentation = | ||
| 290 | |||
| 291 | # Enable graphics API debugging mode. | ||
| 292 | # 0 (default): Disabled, 1: Enabled | ||
| 293 | debug = | ||
| 294 | |||
| 295 | # Enable shader feedback. | ||
| 296 | # 0 (default): Disabled, 1: Enabled | ||
| 297 | renderer_shader_feedback = | ||
| 298 | |||
| 299 | # Enable Nsight Aftermath crash dumps | ||
| 300 | # 0 (default): Disabled, 1: Enabled | ||
| 301 | nsight_aftermath = | ||
| 302 | |||
| 303 | # Disable shader loop safety checks, executing the shader without loop logic changes | ||
| 304 | # 0 (default): Disabled, 1: Enabled | ||
| 305 | disable_shader_loop_safety_checks = | ||
| 306 | |||
| 307 | # Which Vulkan physical device to use (defaults to 0) | ||
| 308 | vulkan_device = | ||
| 309 | |||
| 310 | # 0: 0.5x (360p/540p) [EXPERIMENTAL] | ||
| 311 | # 1: 0.75x (540p/810p) [EXPERIMENTAL] | ||
| 312 | # 2 (default): 1x (720p/1080p) | ||
| 313 | # 3: 1.5x (1080p/1620p) [EXPERIMENTAL] | ||
| 314 | # 4: 2x (1440p/2160p) | ||
| 315 | # 5: 3x (2160p/3240p) | ||
| 316 | # 6: 4x (2880p/4320p) | ||
| 317 | # 7: 5x (3600p/5400p) | ||
| 318 | # 8: 6x (4320p/6480p) | ||
| 319 | # 9: 7x (5040p/7560p) | ||
| 320 | # 10: 8x (5760/8640p) | ||
| 321 | resolution_setup = | ||
| 322 | |||
| 323 | # Pixel filter to use when up- or down-sampling rendered frames. | ||
| 324 | # 0: Nearest Neighbor | ||
| 325 | # 1 (default): Bilinear | ||
| 326 | # 2: Bicubic | ||
| 327 | # 3: Gaussian | ||
| 328 | # 4: ScaleForce | ||
| 329 | # 5: AMD FidelityFX™️ Super Resolution | ||
| 330 | scaling_filter = | ||
| 331 | |||
| 332 | # Anti-Aliasing (AA) | ||
| 333 | # 0 (default): None, 1: FXAA, 2: SMAA | ||
| 334 | anti_aliasing = | ||
| 335 | |||
| 336 | # Whether to use fullscreen or borderless window mode | ||
| 337 | # 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen | ||
| 338 | fullscreen_mode = | ||
| 339 | |||
| 340 | # Aspect ratio | ||
| 341 | # 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Force 16:10, 4: Stretch to Window | ||
| 342 | aspect_ratio = | ||
| 343 | |||
| 344 | # Anisotropic filtering | ||
| 345 | # 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x | ||
| 346 | max_anisotropy = | ||
| 347 | |||
| 348 | # Whether to enable VSync or not. | ||
| 349 | # OpenGL: Values other than 0 enable VSync | ||
| 350 | # Vulkan: FIFO is selected if the requested mode is not supported by the driver. | ||
| 351 | # FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate. | ||
| 352 | # FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down. | ||
| 353 | # Mailbox can have lower latency than FIFO and does not tear but may drop frames. | ||
| 354 | # Immediate (no synchronization) just presents whatever is available and can exhibit tearing. | ||
| 355 | # 0: Immediate (Off), 1: Mailbox, 2 (Default): FIFO (On), 3: FIFO Relaxed | ||
| 356 | use_vsync = | ||
| 357 | |||
| 358 | # Selects the OpenGL shader backend. NV_gpu_program5 is required for GLASM. If NV_gpu_program5 is | ||
| 359 | # not available and GLASM is selected, GLSL will be used. | ||
| 360 | # 0: GLSL, 1 (default): GLASM, 2: SPIR-V | ||
| 361 | shader_backend = | ||
| 362 | |||
| 363 | # Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory. | ||
| 364 | # 0: Off, 1 (default): On | ||
| 365 | use_reactive_flushing = | ||
| 366 | |||
| 367 | # Whether to allow asynchronous shader building. | ||
| 368 | # 0 (default): Off, 1: On | ||
| 369 | use_asynchronous_shaders = | ||
| 370 | |||
| 371 | # NVDEC emulation. | ||
| 372 | # 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding | ||
| 373 | nvdec_emulation = | ||
| 374 | |||
| 375 | # Accelerate ASTC texture decoding. | ||
| 376 | # 0: Off, 1 (default): On | ||
| 377 | accelerate_astc = | ||
| 378 | |||
| 379 | # Decode ASTC textures asynchronously. | ||
| 380 | # 0 (default): Off, 1: On | ||
| 381 | async_astc = | ||
| 382 | |||
| 383 | # Recompress ASTC textures to a different format. | ||
| 384 | # 0 (default): Uncompressed, 1: BC1 (Low quality), 2: BC3: (Medium quality) | ||
| 385 | async_astc = | ||
| 386 | |||
| 387 | # Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value | ||
| 388 | # 0: Off, 1: On (default) | ||
| 389 | use_speed_limit = | ||
| 390 | |||
| 391 | # Limits the speed of the game to run no faster than this value as a percentage of target speed | ||
| 392 | # 1 - 9999: Speed limit as a percentage of target game speed. 100 (default) | ||
| 393 | speed_limit = | ||
| 394 | |||
| 395 | # Whether to use disk based shader cache | ||
| 396 | # 0: Off, 1 (default): On | ||
| 397 | use_disk_shader_cache = | ||
| 398 | |||
| 399 | # Which gpu accuracy level to use | ||
| 400 | # 0: Normal, 1 (default): High, 2: Extreme (Very slow) | ||
| 401 | gpu_accuracy = | ||
| 402 | |||
| 403 | # Whether to use asynchronous GPU emulation | ||
| 404 | # 0 : Off (slow), 1 (default): On (fast) | ||
| 405 | use_asynchronous_gpu_emulation = | ||
| 406 | |||
| 407 | # Inform the guest that GPU operations completed more quickly than they did. | ||
| 408 | # 0: Off, 1 (default): On | ||
| 409 | use_fast_gpu_time = | ||
| 410 | |||
| 411 | # Whether to use garbage collection or not for GPU caches. | ||
| 412 | # 0 (default): Off, 1: On | ||
| 413 | use_caches_gc = | ||
| 414 | |||
| 415 | # The clear color for the renderer. What shows up on the sides of the bottom screen. | ||
| 416 | # Must be in range of 0-255. Defaults to 0 for all. | ||
| 417 | bg_red = | ||
| 418 | bg_blue = | ||
| 419 | bg_green = | ||
| 420 | |||
| 421 | )" | ||
| 422 | R"( | ||
| 423 | [Audio] | ||
| 424 | # Which audio output engine to use. | ||
| 425 | # auto (default): Auto-select | ||
| 426 | # cubeb: Cubeb audio engine (if available) | ||
| 427 | # sdl2: SDL2 audio engine (if available) | ||
| 428 | # null: No audio output | ||
| 429 | output_engine = | ||
| 430 | |||
| 431 | # Which audio device to use. | ||
| 432 | # auto (default): Auto-select | ||
| 433 | output_device = | ||
| 434 | |||
| 435 | # Output volume. | ||
| 436 | # 100 (default): 100%, 0; mute | ||
| 437 | volume = | ||
| 438 | |||
| 439 | [Data Storage] | ||
| 440 | # Whether to create a virtual SD card. | ||
| 441 | # 1 (default): Yes, 0: No | ||
| 442 | use_virtual_sd = | ||
| 443 | |||
| 444 | # Whether or not to enable gamecard emulation | ||
| 445 | # 1: Yes, 0 (default): No | ||
| 446 | gamecard_inserted = | ||
| 447 | |||
| 448 | # Whether or not the gamecard should be emulated as the current game | ||
| 449 | # If 'gamecard_inserted' is 0 this setting is irrelevant | ||
| 450 | # 1: Yes, 0 (default): No | ||
| 451 | gamecard_current_game = | ||
| 452 | |||
| 453 | # Path to an XCI file to use as the gamecard | ||
| 454 | # If 'gamecard_inserted' is 0 this setting is irrelevant | ||
| 455 | # If 'gamecard_current_game' is 1 this setting is irrelevant | ||
| 456 | gamecard_path = | ||
| 457 | |||
| 458 | [System] | ||
| 459 | # Whether the system is docked | ||
| 460 | # 1 (default): Yes, 0: No | ||
| 461 | use_docked_mode = | ||
| 462 | |||
| 463 | # Sets the seed for the RNG generator built into the switch | ||
| 464 | # rng_seed will be ignored and randomly generated if rng_seed_enabled is false | ||
| 465 | rng_seed_enabled = | ||
| 466 | rng_seed = | ||
| 467 | |||
| 468 | # Sets the current time (in seconds since 12:00 AM Jan 1, 1970) that will be used by the time service | ||
| 469 | # This will auto-increment, with the time set being the time the game is started | ||
| 470 | # This override will only occur if custom_rtc_enabled is true, otherwise the current time is used | ||
| 471 | custom_rtc_enabled = | ||
| 472 | custom_rtc = | ||
| 473 | |||
| 474 | # Sets the systems language index | ||
| 475 | # 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese, | ||
| 476 | # 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French, | ||
| 477 | # 14: Latin American Spanish, 15: Simplified Chinese, 16: Traditional Chinese, 17: Brazilian Portuguese | ||
| 478 | language_index = | ||
| 479 | |||
| 480 | # The system region that yuzu will use during emulation | ||
| 481 | # -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan | ||
| 482 | region_index = | ||
| 483 | |||
| 484 | # The system time zone that yuzu will use during emulation | ||
| 485 | # 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone | ||
| 486 | time_zone_index = | ||
| 487 | |||
| 488 | # Sets the sound output mode. | ||
| 489 | # 0: Mono, 1 (default): Stereo, 2: Surround | ||
| 490 | sound_index = | ||
| 491 | |||
| 492 | [Miscellaneous] | ||
| 493 | # A filter which removes logs below a certain logging level. | ||
| 494 | # Examples: *:Debug Kernel.SVC:Trace Service.*:Critical | ||
| 495 | log_filter = *:Trace | ||
| 496 | |||
| 497 | # Use developer keys | ||
| 498 | # 0 (default): Disabled, 1: Enabled | ||
| 499 | use_dev_keys = | ||
| 500 | |||
| 501 | [Debugging] | ||
| 502 | # Record frame time data, can be found in the log directory. Boolean value | ||
| 503 | record_frame_times = | ||
| 504 | # Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them | ||
| 505 | dump_exefs=false | ||
| 506 | # Determines whether or not yuzu will dump all NSOs it attempts to load while loading them | ||
| 507 | dump_nso=false | ||
| 508 | # Determines whether or not yuzu will save the filesystem access log. | ||
| 509 | enable_fs_access_log=false | ||
| 510 | # Enables verbose reporting services | ||
| 511 | reporting_services = | ||
| 512 | # Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode | ||
| 513 | # false: Retail/Normal Mode (default), true: Kiosk Mode | ||
| 514 | quest_flag = | ||
| 515 | # Determines whether debug asserts should be enabled, which will throw an exception on asserts. | ||
| 516 | # false: Disabled (default), true: Enabled | ||
| 517 | use_debug_asserts = | ||
| 518 | # Determines whether unimplemented HLE service calls should be automatically stubbed. | ||
| 519 | # false: Disabled (default), true: Enabled | ||
| 520 | use_auto_stub = | ||
| 521 | # Enables/Disables the macro JIT compiler | ||
| 522 | disable_macro_jit=false | ||
| 523 | # Determines whether to enable the GDB stub and wait for the debugger to attach before running. | ||
| 524 | # false: Disabled (default), true: Enabled | ||
| 525 | use_gdbstub=false | ||
| 526 | # The port to use for the GDB server, if it is enabled. | ||
| 527 | gdbstub_port=6543 | ||
| 528 | |||
| 529 | [WebService] | ||
| 530 | # Whether or not to enable telemetry | ||
| 531 | # 0: No, 1 (default): Yes | ||
| 532 | enable_telemetry = | ||
| 533 | # URL for Web API | ||
| 534 | web_api_url = https://api.yuzu-emu.org | ||
| 535 | # Username and token for yuzu Web Service | ||
| 536 | # See https://profile.yuzu-emu.org/ for more info | ||
| 537 | yuzu_username = | ||
| 538 | yuzu_token = | ||
| 539 | |||
| 540 | [Network] | ||
| 541 | # Name of the network interface device to use with yuzu LAN play. | ||
| 542 | # e.g. On *nix: 'enp7s0', 'wlp6s0u1u3u3', 'lo' | ||
| 543 | # e.g. On Windows: 'Ethernet', 'Wi-Fi' | ||
| 544 | network_interface = | ||
| 545 | |||
| 546 | [AddOns] | ||
| 547 | # Used to disable add-ons | ||
| 548 | # List of title IDs of games that will have add-ons disabled (separated by '|'): | ||
| 549 | title_ids = | ||
| 550 | # For each title ID, have a key/value pair called `disabled_<title_id>` equal to the names of the add-ons to disable (sep. by '|') | ||
| 551 | # e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey | ||
| 552 | )"; | ||
| 553 | } // namespace DefaultINI | ||
diff --git a/src/yuzu_cmd/sdl_config.cpp b/src/yuzu_cmd/sdl_config.cpp new file mode 100644 index 000000000..39fd8050c --- /dev/null +++ b/src/yuzu_cmd/sdl_config.cpp | |||
| @@ -0,0 +1,257 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | // SDL will break our main function in yuzu-cmd if we don't define this before adding SDL.h | ||
| 5 | #define SDL_MAIN_HANDLED | ||
| 6 | #include <SDL.h> | ||
| 7 | |||
| 8 | #include "input_common/main.h" | ||
| 9 | #include "sdl_config.h" | ||
| 10 | |||
| 11 | const std::array<int, Settings::NativeButton::NumButtons> SdlConfig::default_buttons = { | ||
| 12 | SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T, | ||
| 13 | SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W, | ||
| 14 | SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B, | ||
| 15 | }; | ||
| 16 | |||
| 17 | const std::array<int, Settings::NativeMotion::NumMotions> SdlConfig::default_motions = { | ||
| 18 | SDL_SCANCODE_7, | ||
| 19 | SDL_SCANCODE_8, | ||
| 20 | }; | ||
| 21 | |||
| 22 | const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> SdlConfig::default_analogs{ | ||
| 23 | { | ||
| 24 | { | ||
| 25 | SDL_SCANCODE_UP, | ||
| 26 | SDL_SCANCODE_DOWN, | ||
| 27 | SDL_SCANCODE_LEFT, | ||
| 28 | SDL_SCANCODE_RIGHT, | ||
| 29 | }, | ||
| 30 | { | ||
| 31 | SDL_SCANCODE_I, | ||
| 32 | SDL_SCANCODE_K, | ||
| 33 | SDL_SCANCODE_J, | ||
| 34 | SDL_SCANCODE_L, | ||
| 35 | }, | ||
| 36 | }}; | ||
| 37 | |||
| 38 | const std::array<int, 2> SdlConfig::default_stick_mod = { | ||
| 39 | SDL_SCANCODE_D, | ||
| 40 | 0, | ||
| 41 | }; | ||
| 42 | |||
| 43 | const std::array<int, 2> SdlConfig::default_ringcon_analogs{{ | ||
| 44 | 0, | ||
| 45 | 0, | ||
| 46 | }}; | ||
| 47 | |||
| 48 | SdlConfig::SdlConfig(const std::optional<std::string> config_path) { | ||
| 49 | Initialize(config_path); | ||
| 50 | ReadSdlValues(); | ||
| 51 | SaveSdlValues(); | ||
| 52 | } | ||
| 53 | |||
| 54 | SdlConfig::~SdlConfig() { | ||
| 55 | if (global) { | ||
| 56 | SdlConfig::SaveAllValues(); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | void SdlConfig::ReloadAllValues() { | ||
| 61 | Reload(); | ||
| 62 | ReadSdlValues(); | ||
| 63 | SaveSdlValues(); | ||
| 64 | } | ||
| 65 | |||
| 66 | void SdlConfig::SaveAllValues() { | ||
| 67 | Save(); | ||
| 68 | SaveSdlValues(); | ||
| 69 | } | ||
| 70 | |||
| 71 | void SdlConfig::ReadSdlValues() { | ||
| 72 | ReadSdlControlValues(); | ||
| 73 | } | ||
| 74 | |||
| 75 | void SdlConfig::ReadSdlControlValues() { | ||
| 76 | BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); | ||
| 77 | |||
| 78 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 79 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | ||
| 80 | ReadSdlPlayerValues(p); | ||
| 81 | } | ||
| 82 | if (IsCustomConfig()) { | ||
| 83 | EndGroup(); | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | ReadDebugControlValues(); | ||
| 87 | ReadHidbusValues(); | ||
| 88 | |||
| 89 | EndGroup(); | ||
| 90 | } | ||
| 91 | |||
| 92 | void SdlConfig::ReadSdlPlayerValues(const std::size_t player_index) { | ||
| 93 | std::string player_prefix; | ||
| 94 | if (type != ConfigType::InputProfile) { | ||
| 95 | player_prefix.append("player_").append(ToString(player_index)).append("_"); | ||
| 96 | } | ||
| 97 | |||
| 98 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 99 | if (IsCustomConfig()) { | ||
| 100 | const auto profile_name = | ||
| 101 | ReadStringSetting(std::string(player_prefix).append("profile_name")); | ||
| 102 | if (profile_name.empty()) { | ||
| 103 | // Use the global input config | ||
| 104 | player = Settings::values.players.GetValue(true)[player_index]; | ||
| 105 | return; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 110 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 111 | auto& player_buttons = player.buttons[i]; | ||
| 112 | |||
| 113 | player_buttons = ReadStringSetting( | ||
| 114 | std::string(player_prefix).append(Settings::NativeButton::mapping[i]), default_param); | ||
| 115 | if (player_buttons.empty()) { | ||
| 116 | player_buttons = default_param; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 121 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 122 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 123 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 124 | auto& player_analogs = player.analogs[i]; | ||
| 125 | |||
| 126 | player_analogs = ReadStringSetting( | ||
| 127 | std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), default_param); | ||
| 128 | if (player_analogs.empty()) { | ||
| 129 | player_analogs = default_param; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | ||
| 134 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); | ||
| 135 | auto& player_motions = player.motions[i]; | ||
| 136 | |||
| 137 | player_motions = ReadStringSetting( | ||
| 138 | std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), default_param); | ||
| 139 | if (player_motions.empty()) { | ||
| 140 | player_motions = default_param; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | void SdlConfig::ReadDebugControlValues() { | ||
| 146 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 147 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 148 | auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; | ||
| 149 | debug_pad_buttons = ReadStringSetting( | ||
| 150 | std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), default_param); | ||
| 151 | if (debug_pad_buttons.empty()) { | ||
| 152 | debug_pad_buttons = default_param; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 156 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 157 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 158 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 159 | auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; | ||
| 160 | debug_pad_analogs = ReadStringSetting( | ||
| 161 | std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), default_param); | ||
| 162 | if (debug_pad_analogs.empty()) { | ||
| 163 | debug_pad_analogs = default_param; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | void SdlConfig::ReadHidbusValues() { | ||
| 169 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 170 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); | ||
| 171 | auto& ringcon_analogs = Settings::values.ringcon_analogs; | ||
| 172 | |||
| 173 | ringcon_analogs = ReadStringSetting(std::string("ring_controller"), default_param); | ||
| 174 | if (ringcon_analogs.empty()) { | ||
| 175 | ringcon_analogs = default_param; | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | void SdlConfig::SaveSdlValues() { | ||
| 180 | SaveSdlControlValues(); | ||
| 181 | |||
| 182 | WriteToIni(); | ||
| 183 | } | ||
| 184 | |||
| 185 | void SdlConfig::SaveSdlControlValues() { | ||
| 186 | BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); | ||
| 187 | |||
| 188 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 189 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | ||
| 190 | SaveSdlPlayerValues(p); | ||
| 191 | } | ||
| 192 | if (IsCustomConfig()) { | ||
| 193 | EndGroup(); | ||
| 194 | return; | ||
| 195 | } | ||
| 196 | SaveDebugControlValues(); | ||
| 197 | SaveHidbusValues(); | ||
| 198 | |||
| 199 | EndGroup(); | ||
| 200 | } | ||
| 201 | |||
| 202 | void SdlConfig::SaveSdlPlayerValues(const std::size_t player_index) { | ||
| 203 | std::string player_prefix; | ||
| 204 | if (type != ConfigType::InputProfile) { | ||
| 205 | player_prefix = std::string("player_").append(ToString(player_index)).append("_"); | ||
| 206 | } | ||
| 207 | |||
| 208 | const auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 209 | if (IsCustomConfig() && player.profile_name.empty()) { | ||
| 210 | // No custom profile selected | ||
| 211 | return; | ||
| 212 | } | ||
| 213 | |||
| 214 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 215 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 216 | WriteSetting(std::string(player_prefix).append(Settings::NativeButton::mapping[i]), | ||
| 217 | player.buttons[i], std::make_optional(default_param)); | ||
| 218 | } | ||
| 219 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 220 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 221 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 222 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 223 | WriteSetting(std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), | ||
| 224 | player.analogs[i], std::make_optional(default_param)); | ||
| 225 | } | ||
| 226 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | ||
| 227 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); | ||
| 228 | WriteSetting(std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), | ||
| 229 | player.motions[i], std::make_optional(default_param)); | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | void SdlConfig::SaveDebugControlValues() { | ||
| 234 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | ||
| 235 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | ||
| 236 | WriteSetting(std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), | ||
| 237 | Settings::values.debug_pad_buttons[i], std::make_optional(default_param)); | ||
| 238 | } | ||
| 239 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | ||
| 240 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 241 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | ||
| 242 | default_analogs[i][3], default_stick_mod[i], 0.5f); | ||
| 243 | WriteSetting(std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), | ||
| 244 | Settings::values.debug_pad_analogs[i], std::make_optional(default_param)); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | void SdlConfig::SaveHidbusValues() { | ||
| 249 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | ||
| 250 | 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); | ||
| 251 | WriteSetting(std::string("ring_controller"), Settings::values.ringcon_analogs, | ||
| 252 | std::make_optional(default_param)); | ||
| 253 | } | ||
| 254 | |||
| 255 | std::vector<Settings::BasicSetting*>& SdlConfig::FindRelevantList(Settings::Category category) { | ||
| 256 | return Settings::values.linkage.by_category[category]; | ||
| 257 | } | ||
diff --git a/src/yuzu_cmd/sdl_config.h b/src/yuzu_cmd/sdl_config.h new file mode 100644 index 000000000..1fd1c692d --- /dev/null +++ b/src/yuzu_cmd/sdl_config.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "frontend_common/config.h" | ||
| 7 | |||
| 8 | class SdlConfig final : public Config { | ||
| 9 | public: | ||
| 10 | explicit SdlConfig(std::optional<std::string> config_path); | ||
| 11 | ~SdlConfig() override; | ||
| 12 | |||
| 13 | void ReloadAllValues() override; | ||
| 14 | void SaveAllValues() override; | ||
| 15 | |||
| 16 | protected: | ||
| 17 | void ReadSdlValues(); | ||
| 18 | void ReadSdlPlayerValues(std::size_t player_index); | ||
| 19 | void ReadSdlControlValues(); | ||
| 20 | void ReadHidbusValues() override; | ||
| 21 | void ReadDebugControlValues() override; | ||
| 22 | void ReadPathValues() override {} | ||
| 23 | void ReadShortcutValues() override {} | ||
| 24 | void ReadUIValues() override {} | ||
| 25 | void ReadUIGamelistValues() override {} | ||
| 26 | void ReadUILayoutValues() override {} | ||
| 27 | void ReadMultiplayerValues() override {} | ||
| 28 | |||
| 29 | void SaveSdlValues(); | ||
| 30 | void SaveSdlPlayerValues(std::size_t player_index); | ||
| 31 | void SaveSdlControlValues(); | ||
| 32 | void SaveHidbusValues() override; | ||
| 33 | void SaveDebugControlValues() override; | ||
| 34 | void SavePathValues() override {} | ||
| 35 | void SaveShortcutValues() override {} | ||
| 36 | void SaveUIValues() override {} | ||
| 37 | void SaveUIGamelistValues() override {} | ||
| 38 | void SaveUILayoutValues() override {} | ||
| 39 | void SaveMultiplayerValues() override {} | ||
| 40 | |||
| 41 | std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override; | ||
| 42 | |||
| 43 | public: | ||
| 44 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; | ||
| 45 | static const std::array<int, Settings::NativeMotion::NumMotions> default_motions; | ||
| 46 | static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs; | ||
| 47 | static const std::array<int, 2> default_stick_mod; | ||
| 48 | static const std::array<int, 2> default_ringcon_analogs; | ||
| 49 | }; | ||
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 087cfaa26..0416d5951 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -29,10 +29,11 @@ | |||
| 29 | #include "core/hle/service/filesystem/filesystem.h" | 29 | #include "core/hle/service/filesystem/filesystem.h" |
| 30 | #include "core/loader/loader.h" | 30 | #include "core/loader/loader.h" |
| 31 | #include "core/telemetry_session.h" | 31 | #include "core/telemetry_session.h" |
| 32 | #include "frontend_common/config.h" | ||
| 32 | #include "input_common/main.h" | 33 | #include "input_common/main.h" |
| 33 | #include "network/network.h" | 34 | #include "network/network.h" |
| 35 | #include "sdl_config.h" | ||
| 34 | #include "video_core/renderer_base.h" | 36 | #include "video_core/renderer_base.h" |
| 35 | #include "yuzu_cmd/config.h" | ||
| 36 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 37 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 37 | #include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" | 38 | #include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" |
| 38 | #include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" | 39 | #include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" |
| @@ -300,7 +301,7 @@ int main(int argc, char** argv) { | |||
| 300 | } | 301 | } |
| 301 | } | 302 | } |
| 302 | 303 | ||
| 303 | Config config{config_path}; | 304 | SdlConfig config{config_path}; |
| 304 | 305 | ||
| 305 | // apply the log_filter setting | 306 | // apply the log_filter setting |
| 306 | // the logger was initialized before and doesn't pick up the filter on its own | 307 | // the logger was initialized before and doesn't pick up the filter on its own |