summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/android/app/build.gradle.kts1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt42
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt24
-rw-r--r--src/android/app/src/main/jni/CMakeLists.txt11
-rw-r--r--src/android/app/src/main/jni/android_config.cpp70
-rw-r--r--src/android/app/src/main/jni/android_config.h41
-rw-r--r--src/android/app/src/main/jni/android_settings.cpp (renamed from src/android/app/src/main/jni/uisettings.cpp)2
-rw-r--r--src/android/app/src/main/jni/android_settings.h (renamed from src/android/app/src/main/jni/uisettings.h)0
-rw-r--r--src/android/app/src/main/jni/config.cpp330
-rw-r--r--src/android/app/src/main/jni/config.h47
-rw-r--r--src/android/app/src/main/jni/default_ini.h511
-rw-r--r--src/android/app/src/main/jni/native.cpp15
-rw-r--r--src/android/app/src/main/jni/native_config.cpp23
-rw-r--r--src/common/settings.cpp4
-rw-r--r--src/common/settings.h42
-rw-r--r--src/core/CMakeLists.txt9
-rw-r--r--src/core/hid/emulated_controller.cpp17
-rw-r--r--src/core/hid/hid_core.cpp5
-rw-r--r--src/core/hid/hid_types.h80
-rw-r--r--src/core/hid/input_interpreter.cpp4
-rw-r--r--src/core/hid/input_interpreter.h4
-rw-r--r--src/core/hle/service/hid/controllers/console_six_axis.cpp42
-rw-r--r--src/core/hle/service/hid/controllers/console_six_axis.h43
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.cpp10
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h6
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp54
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h6
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp10
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h6
-rw-r--r--src/core/hle/service/hid/controllers/mouse.cpp11
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h6
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp586
-rw-r--r--src/core/hle/service/hid/controllers/npad.h126
-rw-r--r--src/core/hle/service/hid/controllers/palma.cpp86
-rw-r--r--src/core/hle/service/hid/controllers/palma.h8
-rw-r--r--src/core/hle/service/hid/controllers/seven_six_axis.cpp (renamed from src/core/hle/service/hid/controllers/console_sixaxis.cpp)38
-rw-r--r--src/core/hle/service/hid/controllers/seven_six_axis.h (renamed from src/core/hle/service/hid/controllers/console_sixaxis.h)31
-rw-r--r--src/core/hle/service/hid/controllers/six_axis.cpp413
-rw-r--r--src/core/hle/service/hid/controllers/six_axis.h111
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp11
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.h6
-rw-r--r--src/core/hle/service/hid/controllers/xpad.cpp11
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h6
-rw-r--r--src/core/hle/service/hid/hid_server.cpp437
-rw-r--r--src/core/hle/service/hid/hid_system_server.cpp424
-rw-r--r--src/core/hle/service/hid/hid_util.h146
-rw-r--r--src/core/hle/service/hid/irs.cpp5
-rw-r--r--src/core/hle/service/hid/resource_manager.cpp155
-rw-r--r--src/core/hle/service/hid/resource_manager.h119
-rw-r--r--src/core/hle/service/nfc/common/device_manager.cpp3
-rw-r--r--src/core/memory/cheat_engine.cpp5
-rw-r--r--src/frontend_common/CMakeLists.txt10
-rw-r--r--src/frontend_common/config.cpp1008
-rw-r--r--src/frontend_common/config.h210
-rw-r--r--src/video_core/query_cache/query_cache.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp18
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h1
-rw-r--r--src/yuzu/CMakeLists.txt6
-rw-r--r--src/yuzu/configuration/config.cpp1309
-rw-r--r--src/yuzu/configuration/config.h179
-rw-r--r--src/yuzu/configuration/configure_camera.cpp2
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp1
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp36
-rw-r--r--src/yuzu/configuration/configure_input_per_game.cpp6
-rw-r--r--src/yuzu/configuration/configure_input_per_game.h5
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp11
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp7
-rw-r--r--src/yuzu/configuration/configure_per_game.h5
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp1
-rw-r--r--src/yuzu/configuration/configure_ringcon.cpp4
-rw-r--r--src/yuzu/configuration/configure_system.cpp1
-rw-r--r--src/yuzu/configuration/configure_touchscreen_advanced.cpp2
-rw-r--r--src/yuzu/configuration/configure_ui.cpp7
-rw-r--r--src/yuzu/configuration/input_profiles.cpp10
-rw-r--r--src/yuzu/configuration/input_profiles.h4
-rw-r--r--src/yuzu/configuration/qt_config.cpp549
-rw-r--r--src/yuzu/configuration/qt_config.h55
-rw-r--r--src/yuzu/configuration/shared_translation.h43
-rw-r--r--src/yuzu/debugger/wait_tree.cpp6
-rw-r--r--src/yuzu/game_list.cpp7
-rw-r--r--src/yuzu/game_list_p.h8
-rw-r--r--src/yuzu/game_list_worker.cpp16
-rw-r--r--src/yuzu/hotkeys.cpp28
-rw-r--r--src/yuzu/hotkeys.h16
-rw-r--r--src/yuzu/main.cpp112
-rw-r--r--src/yuzu/main.h7
-rw-r--r--src/yuzu/uisettings.cpp65
-rw-r--r--src/yuzu/uisettings.h79
-rw-r--r--src/yuzu_cmd/CMakeLists.txt9
-rw-r--r--src/yuzu_cmd/config.cpp279
-rw-r--r--src/yuzu_cmd/config.h38
-rw-r--r--src/yuzu_cmd/default_ini.h553
-rw-r--r--src/yuzu_cmd/sdl_config.cpp257
-rw-r--r--src/yuzu_cmd/sdl_config.h49
-rw-r--r--src/yuzu_cmd/yuzu.cpp5
101 files changed, 4333 insertions, 4910 deletions
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)
187add_subdirectory(video_core) 187add_subdirectory(video_core)
188add_subdirectory(network) 188add_subdirectory(network)
189add_subdirectory(input_common) 189add_subdirectory(input_common)
190add_subdirectory(frontend_common)
190add_subdirectory(shader_recompiler) 191add_subdirectory(shader_recompiler)
191 192
192if (YUZU_ROOM) 193if (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
7import android.widget.Toast 7import android.widget.Toast
8import org.yuzu.yuzu_emu.R 8import org.yuzu.yuzu_emu.R
9import org.yuzu.yuzu_emu.YuzuApplication 9import org.yuzu.yuzu_emu.YuzuApplication
10import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile 10import org.yuzu.yuzu_emu.utils.NativeConfig
11 11
12object Settings { 12object 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
21import com.google.android.material.color.MaterialColors 21import com.google.android.material.color.MaterialColors
22import kotlinx.coroutines.flow.collectLatest 22import kotlinx.coroutines.flow.collectLatest
23import kotlinx.coroutines.launch 23import kotlinx.coroutines.launch
24import org.yuzu.yuzu_emu.NativeLibrary
25import java.io.IOException 24import java.io.IOException
26import org.yuzu.yuzu_emu.R 25import org.yuzu.yuzu_emu.R
27import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding 26import 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
4package org.yuzu.yuzu_emu.features.settings.utils 4package org.yuzu.yuzu_emu.features.settings.utils
5 5
6import android.widget.Toast
7import java.io.* 6import java.io.*
8import org.ini4j.Wini
9import org.yuzu.yuzu_emu.R
10import org.yuzu.yuzu_emu.YuzuApplication
11import org.yuzu.yuzu_emu.features.settings.model.*
12import org.yuzu.yuzu_emu.utils.DirectoryInitialization 7import org.yuzu.yuzu_emu.utils.DirectoryInitialization
13import org.yuzu.yuzu_emu.utils.Log
14import 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
19object SettingsFile { 12object 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 @@
4package org.yuzu.yuzu_emu.utils 4package org.yuzu.yuzu_emu.utils
5 5
6object NativeConfig { 6object 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
24set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) 23set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
25 24
26target_link_libraries(yuzu-android PRIVATE audio_core common core input_common) 25target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common)
27target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics log) 26target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
28if (ARCHITECTURE_arm64) 27if (ARCHITECTURE_arm64)
29 target_link_libraries(yuzu-android PRIVATE adrenotools) 28 target_link_libraries(yuzu-android PRIVATE adrenotools)
30endif() 29endif()
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
8AndroidConfig::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
17AndroidConfig::~AndroidConfig() {
18 if (global) {
19 AndroidConfig::SaveAllValues();
20 }
21}
22
23void AndroidConfig::ReloadAllValues() {
24 Reload();
25 ReadAndroidValues();
26 SaveAndroidValues();
27}
28
29void AndroidConfig::SaveAllValues() {
30 Save();
31 SaveAndroidValues();
32}
33
34void AndroidConfig::ReadAndroidValues() {
35 if (global) {
36 ReadAndroidUIValues();
37 }
38}
39
40void AndroidConfig::ReadAndroidUIValues() {
41 BeginGroup(Settings::TranslateCategory(Settings::Category::Android));
42
43 ReadCategory(Settings::Category::Android);
44
45 EndGroup();
46}
47
48void AndroidConfig::SaveAndroidValues() {
49 if (global) {
50 SaveAndroidUIValues();
51 }
52
53 WriteToIni();
54}
55
56void AndroidConfig::SaveAndroidUIValues() {
57 BeginGroup(Settings::TranslateCategory(Settings::Category::Android));
58
59 WriteCategory(Settings::Category::Android);
60
61 EndGroup();
62}
63
64std::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
8class AndroidConfig final : public Config {
9public:
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
17protected:
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
6namespace AndroidSettings { 6namespace 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
21namespace FS = Common::FS;
22
23Config::Config(const std::string& config_name, ConfigType config_type)
24 : type(config_type), global{config_type == ConfigType::GlobalConfig} {
25 Initialize(config_name);
26}
27
28Config::~Config() = default;
29
30bool 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
53template <>
54void 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
62template <>
63void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) {
64 setting = config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
65}
66
67template <typename Type, bool ranged>
68void 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
73void 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
312void 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
13class INIReader;
14
15class Config {
16 bool LoadINI(const std::string& default_contents = "", bool retry = true);
17
18public:
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
31private:
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
6namespace DefaultINI {
7
8const 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
17connected=
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
34button_a=
35button_b=
36button_x=
37button_y=
38button_lstick=
39button_rstick=
40button_l=
41button_r=
42button_zl=
43button_zr=
44button_plus=
45button_minus=
46button_dleft=
47button_dup=
48button_dright=
49button_ddown=
50button_lstick_left=
51button_lstick_up=
52button_lstick_right=
53button_lstick_down=
54button_sl=
55button_sr=
56button_home=
57button_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)
71lstick=
72rstick=
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
86motionleft=
87motionright=
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
95debug_pad_enabled =
96
97# Whether to enable or disable vibration
98# 0: Disabled, 1 (default): Enabled
99vibration_enabled=
100
101# Whether to enable or disable accurate vibrations
102# 0 (default): Disabled, 1: Enabled
103enable_accurate_vibrations=
104
105# Enables controller motion inputs
106# 0: Disabled, 1 (default): Enabled
107motion_enabled =
108
109# Defines the udp device's touch screen coordinate system for cemuhookudp devices
110# - "min_x", "min_y", "max_x", "max_y"
111touch_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
124udp_input_servers =
125
126# Enable controlling an axis via a mouse input.
127# 0 (default): Off, 1: On
128mouse_panning =
129
130# Set mouse sensitivity.
131# Default: 1.0
132mouse_panning_sensitivity =
133
134# Emulate an analog control stick from keyboard inputs.
135# 0 (default): Disabled, 1: Enabled
136emulate_analog_keyboard =
137
138# Enable mouse inputs to the guest
139# 0 (default): Disabled, 1: Enabled
140mouse_enabled =
141
142# Enable keyboard inputs to the guest
143# 0 (default): Disabled, 1: Enabled
144keyboard_enabled =
145
146[Core]
147# Whether to use multi-core for CPU emulation
148# 0: Disabled, 1 (default): Enabled
149use_multi_core =
150
151# Enable unsafe extended guest system memory layout (8GB DRAM)
152# 0 (default): Disabled, 1: Enabled
153use_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
161cpu_accuracy =
162
163# Allow disabling safe optimizations.
164# 0 (default): Disabled, 1: Enabled
165cpu_debug_mode =
166
167# Enable inline page tables optimization (faster guest memory access)
168# 0: Disabled, 1 (default): Enabled
169cpuopt_page_tables =
170
171# Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps)
172# 0: Disabled, 1 (default): Enabled
173cpuopt_block_linking =
174
175# Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns)
176# 0: Disabled, 1 (default): Enabled
177cpuopt_return_stack_buffer =
178
179# Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture)
180# 0: Disabled, 1 (default): Enabled
181cpuopt_fast_dispatcher =
182
183# Enable context elimination CPU Optimization (reduce host memory use for guest context)
184# 0: Disabled, 1 (default): Enabled
185cpuopt_context_elimination =
186
187# Enable constant propagation CPU optimization (basic IR optimization)
188# 0: Disabled, 1 (default): Enabled
189cpuopt_const_prop =
190
191# Enable miscellaneous CPU optimizations (basic IR optimization)
192# 0: Disabled, 1 (default): Enabled
193cpuopt_misc_ir =
194
195# Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access)
196# 0: Disabled, 1 (default): Enabled
197cpuopt_reduce_misalign_checks =
198
199# Enable Host MMU Emulation (faster guest memory access)
200# 0: Disabled, 1 (default): Enabled
201cpuopt_fastmem =
202
203# Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access)
204# 0: Disabled, 1 (default): Enabled
205cpuopt_fastmem_exclusives =
206
207# Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access)
208# 0: Disabled, 1 (default): Enabled
209cpuopt_recompile_exclusives =
210
211# Enable optimization to ignore invalid memory accesses (faster guest memory access)
212# 0: Disabled, 1 (default): Enabled
213cpuopt_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
218cpuopt_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
223cpuopt_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
228cpuopt_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
233cpuopt_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
238cpuopt_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
243cpuopt_unsafe_ignore_global_monitor =
244
245[Renderer]
246# Which backend API to use.
247# 0: OpenGL (unsupported), 1 (default): Vulkan, 2: Null
248backend =
249
250# Whether to enable asynchronous presentation (Vulkan only)
251# 0: Off, 1 (default): On
252async_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
256force_max_clock =
257
258# Enable graphics API debugging mode.
259# 0 (default): Disabled, 1: Enabled
260debug =
261
262# Enable shader feedback.
263# 0 (default): Disabled, 1: Enabled
264renderer_shader_feedback =
265
266# Enable Nsight Aftermath crash dumps
267# 0 (default): Disabled, 1: Enabled
268nsight_aftermath =
269
270# Disable shader loop safety checks, executing the shader without loop logic changes
271# 0 (default): Disabled, 1: Enabled
272disable_shader_loop_safety_checks =
273
274# Which Vulkan physical device to use (defaults to 0)
275vulkan_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)
285resolution_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]
294scaling_filter =
295
296# Anti-Aliasing (AA)
297# 0 (default): None, 1: FXAA
298anti_aliasing =
299
300# Whether to use fullscreen or borderless window mode
301# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen
302fullscreen_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
306aspect_ratio =
307
308# Anisotropic filtering
309# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x
310max_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
320use_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
325shader_backend =
326
327# Whether to allow asynchronous shader building.
328# 0 (default): Off, 1: On
329use_asynchronous_shaders =
330
331# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.
332# 0 (default): Off, 1: On
333use_reactive_flushing =
334
335# NVDEC emulation.
336# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding
337nvdec_emulation =
338
339# Accelerate ASTC texture decoding.
340# 0 (default): Off, 1: On
341accelerate_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)
345use_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)
349speed_limit =
350
351# Whether to use disk based shader cache
352# 0: Off, 1 (default): On
353use_disk_shader_cache =
354
355# Which gpu accuracy level to use
356# 0 (default): Normal, 1: High, 2: Extreme (Very slow)
357gpu_accuracy =
358
359# Whether to use asynchronous GPU emulation
360# 0 : Off (slow), 1 (default): On (fast)
361use_asynchronous_gpu_emulation =
362
363# Inform the guest that GPU operations completed more quickly than they did.
364# 0: Off, 1 (default): On
365use_fast_gpu_time =
366
367# Force unmodified buffers to be flushed, which can cost performance.
368# 0: Off (default), 1: On
369use_pessimistic_flushes =
370
371# Whether to use garbage collection or not for GPU caches.
372# 0 (default): Off, 1: On
373use_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.
377bg_red =
378bg_blue =
379bg_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
387output_engine =
388
389# Which audio device to use.
390# auto (default): Auto-select
391output_device =
392
393# Output volume.
394# 100 (default): 100%, 0; mute
395volume =
396
397[Data Storage]
398# Whether to create a virtual SD card.
399# 1: Yes, 0 (default): No
400use_virtual_sd =
401
402# Whether or not to enable gamecard emulation
403# 1: Yes, 0 (default): No
404gamecard_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
409gamecard_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
414gamecard_path =
415
416[System]
417# Whether the system is docked
418# 1 (default): Yes, 0: No
419use_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
423rng_seed_enabled =
424rng_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
429custom_rtc_enabled =
430custom_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
436language_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
440region_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
444time_zone_index =
445
446# Sets the sound output mode.
447# 0: Mono, 1 (default): Stereo, 2: Surround
448sound_index =
449
450[Miscellaneous]
451# A filter which removes logs below a certain logging level.
452# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
453log_filter = *:Trace
454
455# Use developer keys
456# 0 (default): Disabled, 1: Enabled
457use_dev_keys =
458
459[Debugging]
460# Record frame time data, can be found in the log directory. Boolean value
461record_frame_times =
462# Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them
463dump_exefs=false
464# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
465dump_nso=false
466# Determines whether or not yuzu will save the filesystem access log.
467enable_fs_access_log=false
468# Enables verbose reporting services
469reporting_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
472quest_flag =
473# Determines whether debug asserts should be enabled, which will throw an exception on asserts.
474# false: Disabled (default), true: Enabled
475use_debug_asserts =
476# Determines whether unimplemented HLE service calls should be automatically stubbed.
477# false: Disabled (default), true: Enabled
478use_auto_stub =
479# Enables/Disables the macro JIT compiler
480disable_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
483use_gdbstub=false
484# The port to use for the GDB server, if it is enabled.
485gdbstub_port=6543
486
487[WebService]
488# Whether or not to enable telemetry
489# 0: No, 1 (default): Yes
490enable_telemetry =
491# URL for Web API
492web_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
495yuzu_username =
496yuzu_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'
502network_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 '|'):
507title_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
665void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz, 665void 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
680void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2Ljava_lang_String_2Z( 678void 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
683void Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadSettings(JNIEnv* env, jclass clazz) {
684 Config{};
685}
686
687void 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
694jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jclass clazz) { 681jdoubleArray 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" 15std::unique_ptr<AndroidConfig> config;
13 16
14template <typename T> 17template <typename T>
15Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) { 18Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
@@ -28,6 +31,22 @@ Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
28 31
29extern "C" { 32extern "C" {
30 33
34void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_initializeConfig(JNIEnv* env, jobject obj) {
35 config = std::make_unique<AndroidConfig>();
36}
37
38void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_unloadConfig(JNIEnv* env, jobject obj) {
39 config.reset();
40}
41
42void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_reloadSettings(JNIEnv* env, jobject obj) {
43 config->AndroidConfig::ReloadAllValues();
44}
45
46void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_saveSettings(JNIEnv* env, jobject obj) {
47 config->AndroidConfig::SaveAllValues();
48}
49
31jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getBoolean(JNIEnv* env, jobject obj, 50jboolean 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/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 597890655..66c10fc3f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -529,6 +529,7 @@ add_library(core STATIC
529 hle/service/hid/hid_server.h 529 hle/service/hid/hid_server.h
530 hle/service/hid/hid_system_server.cpp 530 hle/service/hid/hid_system_server.cpp
531 hle/service/hid/hid_system_server.h 531 hle/service/hid/hid_system_server.h
532 hle/service/hid/hid_util.h
532 hle/service/hid/hidbus.cpp 533 hle/service/hid/hidbus.cpp
533 hle/service/hid/hidbus.h 534 hle/service/hid/hidbus.h
534 hle/service/hid/irs.cpp 535 hle/service/hid/irs.cpp
@@ -540,8 +541,8 @@ add_library(core STATIC
540 hle/service/hid/xcd.cpp 541 hle/service/hid/xcd.cpp
541 hle/service/hid/xcd.h 542 hle/service/hid/xcd.h
542 hle/service/hid/errors.h 543 hle/service/hid/errors.h
543 hle/service/hid/controllers/console_sixaxis.cpp 544 hle/service/hid/controllers/console_six_axis.cpp
544 hle/service/hid/controllers/console_sixaxis.h 545 hle/service/hid/controllers/console_six_axis.h
545 hle/service/hid/controllers/controller_base.cpp 546 hle/service/hid/controllers/controller_base.cpp
546 hle/service/hid/controllers/controller_base.h 547 hle/service/hid/controllers/controller_base.h
547 hle/service/hid/controllers/debug_pad.cpp 548 hle/service/hid/controllers/debug_pad.cpp
@@ -556,6 +557,10 @@ add_library(core STATIC
556 hle/service/hid/controllers/npad.h 557 hle/service/hid/controllers/npad.h
557 hle/service/hid/controllers/palma.cpp 558 hle/service/hid/controllers/palma.cpp
558 hle/service/hid/controllers/palma.h 559 hle/service/hid/controllers/palma.h
560 hle/service/hid/controllers/seven_six_axis.cpp
561 hle/service/hid/controllers/seven_six_axis.h
562 hle/service/hid/controllers/six_axis.cpp
563 hle/service/hid/controllers/six_axis.h
559 hle/service/hid/controllers/stubbed.cpp 564 hle/service/hid/controllers/stubbed.cpp
560 hle/service/hid/controllers/stubbed.h 565 hle/service/hid/controllers/stubbed.h
561 hle/service/hid/controllers/touchscreen.cpp 566 hle/service/hid/controllers/touchscreen.cpp
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index a6c4ccbbc..a6e681e15 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -8,6 +8,7 @@
8#include "common/thread.h" 8#include "common/thread.h"
9#include "core/hid/emulated_controller.h" 9#include "core/hid/emulated_controller.h"
10#include "core/hid/input_converter.h" 10#include "core/hid/input_converter.h"
11#include "core/hle/service/hid/hid_util.h"
11 12
12namespace Core::HID { 13namespace Core::HID {
13constexpr s32 HID_JOYSTICK_MAX = 0x7fff; 14constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
@@ -82,7 +83,7 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleInde
82} 83}
83 84
84void EmulatedController::ReloadFromSettings() { 85void EmulatedController::ReloadFromSettings() {
85 const auto player_index = NpadIdTypeToIndex(npad_id_type); 86 const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
86 const auto& player = Settings::values.players.GetValue()[player_index]; 87 const auto& player = Settings::values.players.GetValue()[player_index];
87 88
88 for (std::size_t index = 0; index < player.buttons.size(); ++index) { 89 for (std::size_t index = 0; index < player.buttons.size(); ++index) {
@@ -118,7 +119,7 @@ void EmulatedController::ReloadFromSettings() {
118} 119}
119 120
120void EmulatedController::ReloadColorsFromSettings() { 121void EmulatedController::ReloadColorsFromSettings() {
121 const auto player_index = NpadIdTypeToIndex(npad_id_type); 122 const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
122 const auto& player = Settings::values.players.GetValue()[player_index]; 123 const auto& player = Settings::values.players.GetValue()[player_index];
123 124
124 // Avoid updating colors if overridden by physical controller 125 // Avoid updating colors if overridden by physical controller
@@ -215,7 +216,7 @@ void EmulatedController::LoadDevices() {
215} 216}
216 217
217void EmulatedController::LoadTASParams() { 218void EmulatedController::LoadTASParams() {
218 const auto player_index = NpadIdTypeToIndex(npad_id_type); 219 const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
219 Common::ParamPackage common_params{}; 220 Common::ParamPackage common_params{};
220 common_params.Set("engine", "tas"); 221 common_params.Set("engine", "tas");
221 common_params.Set("port", static_cast<int>(player_index)); 222 common_params.Set("port", static_cast<int>(player_index));
@@ -264,7 +265,7 @@ void EmulatedController::LoadTASParams() {
264} 265}
265 266
266void EmulatedController::LoadVirtualGamepadParams() { 267void EmulatedController::LoadVirtualGamepadParams() {
267 const auto player_index = NpadIdTypeToIndex(npad_id_type); 268 const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
268 Common::ParamPackage common_params{}; 269 Common::ParamPackage common_params{};
269 common_params.Set("engine", "virtual_gamepad"); 270 common_params.Set("engine", "virtual_gamepad");
270 common_params.Set("port", static_cast<int>(player_index)); 271 common_params.Set("port", static_cast<int>(player_index));
@@ -617,7 +618,7 @@ bool EmulatedController::IsConfiguring() const {
617} 618}
618 619
619void EmulatedController::SaveCurrentConfig() { 620void EmulatedController::SaveCurrentConfig() {
620 const auto player_index = NpadIdTypeToIndex(npad_id_type); 621 const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
621 auto& player = Settings::values.players.GetValue()[player_index]; 622 auto& player = Settings::values.players.GetValue()[player_index];
622 player.connected = is_connected; 623 player.connected = is_connected;
623 player.controller_type = MapNPadToSettingsType(npad_type); 624 player.controller_type = MapNPadToSettingsType(npad_type);
@@ -1217,7 +1218,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
1217 if (!output_devices[device_index]) { 1218 if (!output_devices[device_index]) {
1218 return false; 1219 return false;
1219 } 1220 }
1220 const auto player_index = NpadIdTypeToIndex(npad_id_type); 1221 const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
1221 const auto& player = Settings::values.players.GetValue()[player_index]; 1222 const auto& player = Settings::values.players.GetValue()[player_index];
1222 const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; 1223 const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f;
1223 1224
@@ -1243,7 +1244,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
1243} 1244}
1244 1245
1245bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { 1246bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
1246 const auto player_index = NpadIdTypeToIndex(npad_id_type); 1247 const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
1247 const auto& player = Settings::values.players.GetValue()[player_index]; 1248 const auto& player = Settings::values.players.GetValue()[player_index];
1248 1249
1249 if (!is_initalized) { 1250 if (!is_initalized) {
@@ -1698,7 +1699,7 @@ void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
1698 } 1699 }
1699 if (is_connected) { 1700 if (is_connected) {
1700 LOG_WARNING(Service_HID, "Controller {} type changed while it's connected", 1701 LOG_WARNING(Service_HID, "Controller {} type changed while it's connected",
1701 NpadIdTypeToIndex(npad_id_type)); 1702 Service::HID::NpadIdTypeToIndex(npad_id_type));
1702 } 1703 }
1703 npad_type = npad_type_; 1704 npad_type = npad_type_;
1704} 1705}
diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp
index cf53c04d9..2cf25a870 100644
--- a/src/core/hid/hid_core.cpp
+++ b/src/core/hid/hid_core.cpp
@@ -6,6 +6,7 @@
6#include "core/hid/emulated_controller.h" 6#include "core/hid/emulated_controller.h"
7#include "core/hid/emulated_devices.h" 7#include "core/hid/emulated_devices.h"
8#include "core/hid/hid_core.h" 8#include "core/hid/hid_core.h"
9#include "core/hle/service/hid/hid_util.h"
9 10
10namespace Core::HID { 11namespace Core::HID {
11 12
@@ -98,11 +99,11 @@ const EmulatedDevices* HIDCore::GetEmulatedDevices() const {
98} 99}
99 100
100EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) { 101EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) {
101 return GetEmulatedController(IndexToNpadIdType(index)); 102 return GetEmulatedController(Service::HID::IndexToNpadIdType(index));
102} 103}
103 104
104const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) const { 105const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) const {
105 return GetEmulatedController(IndexToNpadIdType(index)); 106 return GetEmulatedController(Service::HID::IndexToNpadIdType(index));
106} 107}
107 108
108void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) { 109void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) {
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 70fcc6b69..4bf285f36 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -8,6 +8,7 @@
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "common/point.h" 9#include "common/point.h"
10#include "common/uuid.h" 10#include "common/uuid.h"
11#include "common/vector_math.h"
11 12
12namespace Core::HID { 13namespace Core::HID {
13 14
@@ -598,6 +599,29 @@ struct SixAxisSensorIcInformation {
598static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8, 599static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8,
599 "SixAxisSensorIcInformation is an invalid size"); 600 "SixAxisSensorIcInformation is an invalid size");
600 601
602// This is nn::hid::SixAxisSensorAttribute
603struct SixAxisSensorAttribute {
604 union {
605 u32 raw{};
606 BitField<0, 1, u32> is_connected;
607 BitField<1, 1, u32> is_interpolated;
608 };
609};
610static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size");
611
612// This is nn::hid::SixAxisSensorState
613struct SixAxisSensorState {
614 s64 delta_time{};
615 s64 sampling_number{};
616 Common::Vec3f accel{};
617 Common::Vec3f gyro{};
618 Common::Vec3f rotation{};
619 std::array<Common::Vec3f, 3> orientation{};
620 SixAxisSensorAttribute attribute{};
621 INSERT_PADDING_BYTES(4); // Reserved
622};
623static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size");
624
601// This is nn::hid::VibrationDeviceHandle 625// This is nn::hid::VibrationDeviceHandle
602struct VibrationDeviceHandle { 626struct VibrationDeviceHandle {
603 NpadStyleIndex npad_type{NpadStyleIndex::None}; 627 NpadStyleIndex npad_type{NpadStyleIndex::None};
@@ -708,60 +732,4 @@ struct UniquePadId {
708}; 732};
709static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size"); 733static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size");
710 734
711/// Converts a NpadIdType to an array index.
712constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
713 switch (npad_id_type) {
714 case NpadIdType::Player1:
715 return 0;
716 case NpadIdType::Player2:
717 return 1;
718 case NpadIdType::Player3:
719 return 2;
720 case NpadIdType::Player4:
721 return 3;
722 case NpadIdType::Player5:
723 return 4;
724 case NpadIdType::Player6:
725 return 5;
726 case NpadIdType::Player7:
727 return 6;
728 case NpadIdType::Player8:
729 return 7;
730 case NpadIdType::Handheld:
731 return 8;
732 case NpadIdType::Other:
733 return 9;
734 default:
735 return 0;
736 }
737}
738
739/// Converts an array index to a NpadIdType
740constexpr NpadIdType IndexToNpadIdType(size_t index) {
741 switch (index) {
742 case 0:
743 return NpadIdType::Player1;
744 case 1:
745 return NpadIdType::Player2;
746 case 2:
747 return NpadIdType::Player3;
748 case 3:
749 return NpadIdType::Player4;
750 case 4:
751 return NpadIdType::Player5;
752 case 5:
753 return NpadIdType::Player6;
754 case 6:
755 return NpadIdType::Player7;
756 case 7:
757 return NpadIdType::Player8;
758 case 8:
759 return NpadIdType::Handheld;
760 case 9:
761 return NpadIdType::Other;
762 default:
763 return NpadIdType::Invalid;
764 }
765}
766
767} // namespace Core::HID 735} // namespace Core::HID
diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp
index 11359f318..a6bdd28f2 100644
--- a/src/core/hid/input_interpreter.cpp
+++ b/src/core/hid/input_interpreter.cpp
@@ -13,14 +13,14 @@ InputInterpreter::InputInterpreter(Core::System& system)
13 : npad{system.ServiceManager() 13 : npad{system.ServiceManager()
14 .GetService<Service::HID::IHidServer>("hid") 14 .GetService<Service::HID::IHidServer>("hid")
15 ->GetResourceManager() 15 ->GetResourceManager()
16 ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} { 16 ->GetNpad()} {
17 ResetButtonStates(); 17 ResetButtonStates();
18} 18}
19 19
20InputInterpreter::~InputInterpreter() = default; 20InputInterpreter::~InputInterpreter() = default;
21 21
22void InputInterpreter::PollInput() { 22void InputInterpreter::PollInput() {
23 const auto button_state = npad.GetAndResetPressState(); 23 const auto button_state = npad->GetAndResetPressState();
24 24
25 previous_index = current_index; 25 previous_index = current_index;
26 current_index = (current_index + 1) % button_states.size(); 26 current_index = (current_index + 1) % button_states.size();
diff --git a/src/core/hid/input_interpreter.h b/src/core/hid/input_interpreter.h
index 8c521b381..3569aac93 100644
--- a/src/core/hid/input_interpreter.h
+++ b/src/core/hid/input_interpreter.h
@@ -16,7 +16,7 @@ enum class NpadButton : u64;
16} 16}
17 17
18namespace Service::HID { 18namespace Service::HID {
19class Controller_NPad; 19class NPad;
20} 20}
21 21
22/** 22/**
@@ -101,7 +101,7 @@ public:
101 } 101 }
102 102
103private: 103private:
104 Service::HID::Controller_NPad& npad; 104 std::shared_ptr<Service::HID::NPad> npad;
105 105
106 /// Stores 9 consecutive button states polled from HID. 106 /// Stores 9 consecutive button states polled from HID.
107 std::array<Core::HID::NpadButton, 9> button_states{}; 107 std::array<Core::HID::NpadButton, 9> button_states{};
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.cpp b/src/core/hle/service/hid/controllers/console_six_axis.cpp
new file mode 100644
index 000000000..b2bf1d78d
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/console_six_axis.cpp
@@ -0,0 +1,42 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/core.h"
5#include "core/core_timing.h"
6#include "core/hid/emulated_console.h"
7#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/console_six_axis.h"
9#include "core/memory.h"
10
11namespace Service::HID {
12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
13
14ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
15 : ControllerBase{hid_core_} {
16 console = hid_core.GetEmulatedConsole();
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
18 "ConsoleSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at(
20 reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
21}
22
23ConsoleSixAxis::~ConsoleSixAxis() = default;
24
25void ConsoleSixAxis::OnInit() {}
26
27void ConsoleSixAxis::OnRelease() {}
28
29void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
30 if (!IsControllerActivated()) {
31 return;
32 }
33
34 const auto motion_status = console->GetMotion();
35
36 shared_memory->sampling_number++;
37 shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
38 shared_memory->verticalization_error = motion_status.verticalization_error;
39 shared_memory->gyro_bias = motion_status.gyro_bias;
40}
41
42} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.h b/src/core/hle/service/hid/controllers/console_six_axis.h
new file mode 100644
index 000000000..5b7c6a29a
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/console_six_axis.h
@@ -0,0 +1,43 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/vector_math.h"
7#include "core/hle/service/hid/controllers/controller_base.h"
8
9namespace Core::HID {
10class EmulatedConsole;
11} // namespace Core::HID
12
13namespace Service::HID {
14class ConsoleSixAxis final : public ControllerBase {
15public:
16 explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
17 ~ConsoleSixAxis() override;
18
19 // Called when the controller is initialized
20 void OnInit() override;
21
22 // When the controller is released
23 void OnRelease() override;
24
25 // When the controller is requesting an update for the shared memory
26 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
27
28private:
29 // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
30 struct ConsoleSharedMemory {
31 u64 sampling_number{};
32 bool is_seven_six_axis_sensor_at_rest{};
33 INSERT_PADDING_BYTES(3); // padding
34 f32 verticalization_error{};
35 Common::Vec3f gyro_bias{};
36 INSERT_PADDING_BYTES(4); // padding
37 };
38 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
39
40 ConsoleSharedMemory* shared_memory = nullptr;
41 Core::HID::EmulatedConsole* console = nullptr;
42};
43} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index 8ec9f4a95..9de19ebfc 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -13,7 +13,7 @@
13namespace Service::HID { 13namespace Service::HID {
14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000; 14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
15 15
16Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 16DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
17 : ControllerBase{hid_core_} { 17 : ControllerBase{hid_core_} {
18 static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size, 18 static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
19 "DebugPadSharedMemory is bigger than the shared memory"); 19 "DebugPadSharedMemory is bigger than the shared memory");
@@ -22,13 +22,13 @@ Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_
22 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); 22 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
23} 23}
24 24
25Controller_DebugPad::~Controller_DebugPad() = default; 25DebugPad::~DebugPad() = default;
26 26
27void Controller_DebugPad::OnInit() {} 27void DebugPad::OnInit() {}
28 28
29void Controller_DebugPad::OnRelease() {} 29void DebugPad::OnRelease() {}
30 30
31void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 31void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
32 if (!IsControllerActivated()) { 32 if (!IsControllerActivated()) {
33 shared_memory->debug_pad_lifo.buffer_count = 0; 33 shared_memory->debug_pad_lifo.buffer_count = 0;
34 shared_memory->debug_pad_lifo.buffer_tail = 0; 34 shared_memory->debug_pad_lifo.buffer_tail = 0;
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 68ff0ea79..5566dba77 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -15,10 +15,10 @@ struct AnalogStickState;
15} // namespace Core::HID 15} // namespace Core::HID
16 16
17namespace Service::HID { 17namespace Service::HID {
18class Controller_DebugPad final : public ControllerBase { 18class DebugPad final : public ControllerBase {
19public: 19public:
20 explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 20 explicit DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
21 ~Controller_DebugPad() override; 21 ~DebugPad() override;
22 22
23 // Called when the controller is initialized 23 // Called when the controller is initialized
24 void OnInit() override; 24 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 63eecd42b..59b2ec73c 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -23,7 +23,7 @@ constexpr f32 Square(s32 num) {
23 return static_cast<f32>(num * num); 23 return static_cast<f32>(num * num);
24} 24}
25 25
26Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 26Gesture::Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
27 : ControllerBase(hid_core_) { 27 : ControllerBase(hid_core_) {
28 static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size, 28 static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
29 "GestureSharedMemory is bigger than the shared memory"); 29 "GestureSharedMemory is bigger than the shared memory");
@@ -31,17 +31,17 @@ Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_sh
31 reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); 31 reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
32 console = hid_core.GetEmulatedConsole(); 32 console = hid_core.GetEmulatedConsole();
33} 33}
34Controller_Gesture::~Controller_Gesture() = default; 34Gesture::~Gesture() = default;
35 35
36void Controller_Gesture::OnInit() { 36void Gesture::OnInit() {
37 shared_memory->gesture_lifo.buffer_count = 0; 37 shared_memory->gesture_lifo.buffer_count = 0;
38 shared_memory->gesture_lifo.buffer_tail = 0; 38 shared_memory->gesture_lifo.buffer_tail = 0;
39 force_update = true; 39 force_update = true;
40} 40}
41 41
42void Controller_Gesture::OnRelease() {} 42void Gesture::OnRelease() {}
43 43
44void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 44void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
45 if (!IsControllerActivated()) { 45 if (!IsControllerActivated()) {
46 shared_memory->gesture_lifo.buffer_count = 0; 46 shared_memory->gesture_lifo.buffer_count = 0;
47 shared_memory->gesture_lifo.buffer_tail = 0; 47 shared_memory->gesture_lifo.buffer_tail = 0;
@@ -64,7 +64,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
64 UpdateGestureSharedMemory(gesture, time_difference); 64 UpdateGestureSharedMemory(gesture, time_difference);
65} 65}
66 66
67void Controller_Gesture::ReadTouchInput() { 67void Gesture::ReadTouchInput() {
68 if (!Settings::values.touchscreen.enabled) { 68 if (!Settings::values.touchscreen.enabled) {
69 fingers = {}; 69 fingers = {};
70 return; 70 return;
@@ -76,8 +76,7 @@ void Controller_Gesture::ReadTouchInput() {
76 } 76 }
77} 77}
78 78
79bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, 79bool Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) {
80 f32 time_difference) {
81 const auto& last_entry = GetLastGestureEntry(); 80 const auto& last_entry = GetLastGestureEntry();
82 if (force_update) { 81 if (force_update) {
83 force_update = false; 82 force_update = false;
@@ -100,8 +99,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
100 return false; 99 return false;
101} 100}
102 101
103void Controller_Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, 102void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference) {
104 f32 time_difference) {
105 GestureType type = GestureType::Idle; 103 GestureType type = GestureType::Idle;
106 GestureAttribute attributes{}; 104 GestureAttribute attributes{};
107 105
@@ -138,8 +136,8 @@ void Controller_Gesture::UpdateGestureSharedMemory(GestureProperties& gesture,
138 shared_memory->gesture_lifo.WriteNextEntry(next_state); 136 shared_memory->gesture_lifo.WriteNextEntry(next_state);
139} 137}
140 138
141void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type, 139void Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
142 GestureAttribute& attributes) { 140 GestureAttribute& attributes) {
143 const auto& last_entry = GetLastGestureEntry(); 141 const auto& last_entry = GetLastGestureEntry();
144 142
145 gesture.detection_count++; 143 gesture.detection_count++;
@@ -152,8 +150,8 @@ void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& typ
152 } 150 }
153} 151}
154 152
155void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type, 153void Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
156 f32 time_difference) { 154 f32 time_difference) {
157 const auto& last_entry = GetLastGestureEntry(); 155 const auto& last_entry = GetLastGestureEntry();
158 156
159 // Promote to pan type if touch moved 157 // Promote to pan type if touch moved
@@ -186,9 +184,8 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Gestu
186 } 184 }
187} 185}
188 186
189void Controller_Gesture::EndGesture(GestureProperties& gesture, 187void Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props,
190 GestureProperties& last_gesture_props, GestureType& type, 188 GestureType& type, GestureAttribute& attributes, f32 time_difference) {
191 GestureAttribute& attributes, f32 time_difference) {
192 const auto& last_entry = GetLastGestureEntry(); 189 const auto& last_entry = GetLastGestureEntry();
193 190
194 if (last_gesture_props.active_points != 0) { 191 if (last_gesture_props.active_points != 0) {
@@ -222,9 +219,8 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture,
222 } 219 }
223} 220}
224 221
225void Controller_Gesture::SetTapEvent(GestureProperties& gesture, 222void Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
226 GestureProperties& last_gesture_props, GestureType& type, 223 GestureType& type, GestureAttribute& attributes) {
227 GestureAttribute& attributes) {
228 type = GestureType::Tap; 224 type = GestureType::Tap;
229 gesture = last_gesture_props; 225 gesture = last_gesture_props;
230 force_update = true; 226 force_update = true;
@@ -236,9 +232,8 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
236 } 232 }
237} 233}
238 234
239void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, 235void Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
240 GestureProperties& last_gesture_props, GestureType& type, 236 GestureType& type, f32 time_difference) {
241 f32 time_difference) {
242 const auto& last_entry = GetLastGestureEntry(); 237 const auto& last_entry = GetLastGestureEntry();
243 238
244 next_state.delta = gesture.mid_point - last_entry.pos; 239 next_state.delta = gesture.mid_point - last_entry.pos;
@@ -263,9 +258,8 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
263 } 258 }
264} 259}
265 260
266void Controller_Gesture::EndPanEvent(GestureProperties& gesture, 261void Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
267 GestureProperties& last_gesture_props, GestureType& type, 262 GestureType& type, f32 time_difference) {
268 f32 time_difference) {
269 const auto& last_entry = GetLastGestureEntry(); 263 const auto& last_entry = GetLastGestureEntry();
270 next_state.vel_x = 264 next_state.vel_x =
271 static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference); 265 static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference);
@@ -287,8 +281,8 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
287 force_update = true; 281 force_update = true;
288} 282}
289 283
290void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, 284void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
291 GestureProperties& last_gesture_props, GestureType& type) { 285 GestureType& type) {
292 const auto& last_entry = GetLastGestureEntry(); 286 const auto& last_entry = GetLastGestureEntry();
293 287
294 type = GestureType::Swipe; 288 type = GestureType::Swipe;
@@ -311,11 +305,11 @@ void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
311 next_state.direction = GestureDirection::Up; 305 next_state.direction = GestureDirection::Up;
312} 306}
313 307
314const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const { 308const Gesture::GestureState& Gesture::GetLastGestureEntry() const {
315 return shared_memory->gesture_lifo.ReadCurrentEntry().state; 309 return shared_memory->gesture_lifo.ReadCurrentEntry().state;
316} 310}
317 311
318Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() { 312Gesture::GestureProperties Gesture::GetGestureProperties() {
319 GestureProperties gesture; 313 GestureProperties gesture;
320 std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers; 314 std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
321 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), 315 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 0d6099ea0..4c6f8ee07 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -12,10 +12,10 @@
12#include "core/hle/service/hid/ring_lifo.h" 12#include "core/hle/service/hid/ring_lifo.h"
13 13
14namespace Service::HID { 14namespace Service::HID {
15class Controller_Gesture final : public ControllerBase { 15class Gesture final : public ControllerBase {
16public: 16public:
17 explicit Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 17 explicit Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
18 ~Controller_Gesture() override; 18 ~Gesture() override;
19 19
20 // Called when the controller is initialized 20 // Called when the controller is initialized
21 void OnInit() override; 21 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 117d87433..ddb1b0ba4 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -12,7 +12,7 @@
12namespace Service::HID { 12namespace Service::HID {
13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; 13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
14 14
15Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 15Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
16 : ControllerBase{hid_core_} { 16 : ControllerBase{hid_core_} {
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size, 17 static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
18 "KeyboardSharedMemory is bigger than the shared memory"); 18 "KeyboardSharedMemory is bigger than the shared memory");
@@ -21,13 +21,13 @@ Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_
21 emulated_devices = hid_core.GetEmulatedDevices(); 21 emulated_devices = hid_core.GetEmulatedDevices();
22} 22}
23 23
24Controller_Keyboard::~Controller_Keyboard() = default; 24Keyboard::~Keyboard() = default;
25 25
26void Controller_Keyboard::OnInit() {} 26void Keyboard::OnInit() {}
27 27
28void Controller_Keyboard::OnRelease() {} 28void Keyboard::OnRelease() {}
29 29
30void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 30void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
31 if (!IsControllerActivated()) { 31 if (!IsControllerActivated()) {
32 shared_memory->keyboard_lifo.buffer_count = 0; 32 shared_memory->keyboard_lifo.buffer_count = 0;
33 shared_memory->keyboard_lifo.buffer_tail = 0; 33 shared_memory->keyboard_lifo.buffer_tail = 0;
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 7532f53c6..172ec1309 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -14,10 +14,10 @@ struct KeyboardKey;
14} // namespace Core::HID 14} // namespace Core::HID
15 15
16namespace Service::HID { 16namespace Service::HID {
17class Controller_Keyboard final : public ControllerBase { 17class Keyboard final : public ControllerBase {
18public: 18public:
19 explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 19 explicit Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
20 ~Controller_Keyboard() override; 20 ~Keyboard() override;
21 21
22 // Called when the controller is initialized 22 // Called when the controller is initialized
23 void OnInit() override; 23 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 0afc66681..6e5a04e34 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -12,8 +12,7 @@
12namespace Service::HID { 12namespace Service::HID {
13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; 13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
14 14
15Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 15Mouse::Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
16 : ControllerBase{hid_core_} {
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size, 16 static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size,
18 "MouseSharedMemory is bigger than the shared memory"); 17 "MouseSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at( 18 shared_memory = std::construct_at(
@@ -21,12 +20,12 @@ Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared
21 emulated_devices = hid_core.GetEmulatedDevices(); 20 emulated_devices = hid_core.GetEmulatedDevices();
22} 21}
23 22
24Controller_Mouse::~Controller_Mouse() = default; 23Mouse::~Mouse() = default;
25 24
26void Controller_Mouse::OnInit() {} 25void Mouse::OnInit() {}
27void Controller_Mouse::OnRelease() {} 26void Mouse::OnRelease() {}
28 27
29void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 28void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
30 if (!IsControllerActivated()) { 29 if (!IsControllerActivated()) {
31 shared_memory->mouse_lifo.buffer_count = 0; 30 shared_memory->mouse_lifo.buffer_count = 0;
32 shared_memory->mouse_lifo.buffer_tail = 0; 31 shared_memory->mouse_lifo.buffer_tail = 0;
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 733d00577..a80f3823f 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -14,10 +14,10 @@ struct AnalogStickState;
14} // namespace Core::HID 14} // namespace Core::HID
15 15
16namespace Service::HID { 16namespace Service::HID {
17class Controller_Mouse final : public ControllerBase { 17class Mouse final : public ControllerBase {
18public: 18public:
19 explicit Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 19 explicit Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
20 ~Controller_Mouse() override; 20 ~Mouse() override;
21 21
22 // Called when the controller is initialized 22 // Called when the controller is initialized
23 void OnInit() override; 23 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 127af2b82..08ee9de9c 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -18,6 +18,7 @@
18#include "core/hle/kernel/k_readable_event.h" 18#include "core/hle/kernel/k_readable_event.h"
19#include "core/hle/service/hid/controllers/npad.h" 19#include "core/hle/service/hid/controllers/npad.h"
20#include "core/hle/service/hid/errors.h" 20#include "core/hle/service/hid/errors.h"
21#include "core/hle/service/hid/hid_util.h"
21#include "core/hle/service/kernel_helpers.h" 22#include "core/hle/service/kernel_helpers.h"
22 23
23namespace Service::HID { 24namespace Service::HID {
@@ -29,60 +30,8 @@ constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
29 Core::HID::NpadIdType::Handheld, 30 Core::HID::NpadIdType::Handheld,
30}; 31};
31 32
32bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) { 33NPad::NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
33 switch (npad_id) { 34 KernelHelpers::ServiceContext& service_context_)
34 case Core::HID::NpadIdType::Player1:
35 case Core::HID::NpadIdType::Player2:
36 case Core::HID::NpadIdType::Player3:
37 case Core::HID::NpadIdType::Player4:
38 case Core::HID::NpadIdType::Player5:
39 case Core::HID::NpadIdType::Player6:
40 case Core::HID::NpadIdType::Player7:
41 case Core::HID::NpadIdType::Player8:
42 case Core::HID::NpadIdType::Other:
43 case Core::HID::NpadIdType::Handheld:
44 return true;
45 default:
46 LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
47 return false;
48 }
49}
50
51Result Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
52 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
53 const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
54 const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
55
56 if (!npad_type) {
57 return VibrationInvalidStyleIndex;
58 }
59 if (!npad_id) {
60 return VibrationInvalidNpadId;
61 }
62 if (!device_index) {
63 return VibrationDeviceIndexOutOfRange;
64 }
65
66 return ResultSuccess;
67}
68
69Result Controller_NPad::VerifyValidSixAxisSensorHandle(
70 const Core::HID::SixAxisSensorHandle& device_handle) {
71 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
72 const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
73
74 if (!npad_id) {
75 return InvalidNpadId;
76 }
77 if (!device_index) {
78 return NpadDeviceIndexOutOfRange;
79 }
80
81 return ResultSuccess;
82}
83
84Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
85 KernelHelpers::ServiceContext& service_context_)
86 : ControllerBase{hid_core_}, service_context{service_context_} { 35 : ControllerBase{hid_core_}, service_context{service_context_} {
87 static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size); 36 static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
88 for (std::size_t i = 0; i < controller_data.size(); ++i) { 37 for (std::size_t i = 0; i < controller_data.size(); ++i) {
@@ -103,7 +52,7 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_m
103 } 52 }
104} 53}
105 54
106Controller_NPad::~Controller_NPad() { 55NPad::~NPad() {
107 for (std::size_t i = 0; i < controller_data.size(); ++i) { 56 for (std::size_t i = 0; i < controller_data.size(); ++i) {
108 auto& controller = controller_data[i]; 57 auto& controller = controller_data[i];
109 controller.device->DeleteCallback(controller.callback_key); 58 controller.device->DeleteCallback(controller.callback_key);
@@ -111,8 +60,7 @@ Controller_NPad::~Controller_NPad() {
111 OnRelease(); 60 OnRelease();
112} 61}
113 62
114void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, 63void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) {
115 std::size_t controller_idx) {
116 if (type == Core::HID::ControllerTriggerType::All) { 64 if (type == Core::HID::ControllerTriggerType::All) {
117 ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); 65 ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
118 ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); 66 ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
@@ -150,7 +98,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
150 } 98 }
151} 99}
152 100
153void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { 101void NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
154 auto& controller = GetControllerFromNpadIdType(npad_id); 102 auto& controller = GetControllerFromNpadIdType(npad_id);
155 if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) { 103 if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) {
156 return; 104 return;
@@ -350,7 +298,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
350 hid_core.SetLastActiveController(npad_id); 298 hid_core.SetLastActiveController(npad_id);
351} 299}
352 300
353void Controller_NPad::OnInit() { 301void NPad::OnInit() {
354 if (!IsControllerActivated()) { 302 if (!IsControllerActivated()) {
355 return; 303 return;
356 } 304 }
@@ -384,7 +332,7 @@ void Controller_NPad::OnInit() {
384 } 332 }
385} 333}
386 334
387void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) { 335void NPad::WriteEmptyEntry(NpadInternalState* npad) {
388 NPadGenericState dummy_pad_state{}; 336 NPadGenericState dummy_pad_state{};
389 NpadGcTriggerState dummy_gc_state{}; 337 NpadGcTriggerState dummy_gc_state{};
390 dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1; 338 dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
@@ -405,7 +353,7 @@ void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) {
405 npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state); 353 npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
406} 354}
407 355
408void Controller_NPad::OnRelease() { 356void NPad::OnRelease() {
409 is_controller_initialized = false; 357 is_controller_initialized = false;
410 for (std::size_t i = 0; i < controller_data.size(); ++i) { 358 for (std::size_t i = 0; i < controller_data.size(); ++i) {
411 auto& controller = controller_data[i]; 359 auto& controller = controller_data[i];
@@ -416,7 +364,7 @@ void Controller_NPad::OnRelease() {
416 } 364 }
417} 365}
418 366
419void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { 367void NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
420 std::scoped_lock lock{mutex}; 368 std::scoped_lock lock{mutex};
421 auto& controller = GetControllerFromNpadIdType(npad_id); 369 auto& controller = GetControllerFromNpadIdType(npad_id);
422 const auto controller_type = controller.device->GetNpadStyleIndex(); 370 const auto controller_type = controller.device->GetNpadStyleIndex();
@@ -485,7 +433,7 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
485 } 433 }
486} 434}
487 435
488void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 436void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
489 if (!IsControllerActivated()) { 437 if (!IsControllerActivated()) {
490 return; 438 return;
491 } 439 }
@@ -615,134 +563,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
615 } 563 }
616} 564}
617 565
618void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) { 566void NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
619 if (!IsControllerActivated()) {
620 return;
621 }
622
623 for (std::size_t i = 0; i < controller_data.size(); ++i) {
624 auto& controller = controller_data[i];
625
626 const auto& controller_type = controller.device->GetNpadStyleIndex();
627
628 if (controller_type == Core::HID::NpadStyleIndex::None ||
629 !controller.device->IsConnected()) {
630 continue;
631 }
632
633 auto* npad = controller.shared_memory;
634 const auto& motion_state = controller.device->GetMotions();
635 auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
636 auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
637 auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
638 auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
639 auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
640 auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
641
642 // Clear previous state
643 sixaxis_fullkey_state = {};
644 sixaxis_handheld_state = {};
645 sixaxis_dual_left_state = {};
646 sixaxis_dual_right_state = {};
647 sixaxis_left_lifo_state = {};
648 sixaxis_right_lifo_state = {};
649
650 if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
651 controller.sixaxis_at_rest = true;
652 for (std::size_t e = 0; e < motion_state.size(); ++e) {
653 controller.sixaxis_at_rest =
654 controller.sixaxis_at_rest && motion_state[e].is_at_rest;
655 }
656 }
657
658 const auto set_motion_state = [&](SixAxisSensorState& state,
659 const Core::HID::ControllerMotion& hid_state) {
660 using namespace std::literals::chrono_literals;
661 static constexpr SixAxisSensorState default_motion_state = {
662 .delta_time = std::chrono::nanoseconds(5ms).count(),
663 .accel = {0, 0, -1.0f},
664 .orientation =
665 {
666 Common::Vec3f{1.0f, 0, 0},
667 Common::Vec3f{0, 1.0f, 0},
668 Common::Vec3f{0, 0, 1.0f},
669 },
670 .attribute = {1},
671 };
672 if (!controller.sixaxis_sensor_enabled) {
673 state = default_motion_state;
674 return;
675 }
676 if (!Settings::values.motion_enabled.GetValue()) {
677 state = default_motion_state;
678 return;
679 }
680 state.attribute.is_connected.Assign(1);
681 state.delta_time = std::chrono::nanoseconds(5ms).count();
682 state.accel = hid_state.accel;
683 state.gyro = hid_state.gyro;
684 state.rotation = hid_state.rotation;
685 state.orientation = hid_state.orientation;
686 };
687
688 switch (controller_type) {
689 case Core::HID::NpadStyleIndex::None:
690 ASSERT(false);
691 break;
692 case Core::HID::NpadStyleIndex::ProController:
693 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
694 break;
695 case Core::HID::NpadStyleIndex::Handheld:
696 set_motion_state(sixaxis_handheld_state, motion_state[0]);
697 break;
698 case Core::HID::NpadStyleIndex::JoyconDual:
699 set_motion_state(sixaxis_dual_left_state, motion_state[0]);
700 set_motion_state(sixaxis_dual_right_state, motion_state[1]);
701 break;
702 case Core::HID::NpadStyleIndex::JoyconLeft:
703 set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
704 break;
705 case Core::HID::NpadStyleIndex::JoyconRight:
706 set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
707 break;
708 case Core::HID::NpadStyleIndex::Pokeball:
709 using namespace std::literals::chrono_literals;
710 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
711 sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
712 break;
713 default:
714 break;
715 }
716
717 sixaxis_fullkey_state.sampling_number =
718 npad->sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
719 sixaxis_handheld_state.sampling_number =
720 npad->sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
721 sixaxis_dual_left_state.sampling_number =
722 npad->sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
723 sixaxis_dual_right_state.sampling_number =
724 npad->sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
725 sixaxis_left_lifo_state.sampling_number =
726 npad->sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
727 sixaxis_right_lifo_state.sampling_number =
728 npad->sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
729
730 if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
731 // This buffer only is updated on handheld on HW
732 npad->sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
733 } else {
734 // Handheld doesn't update this buffer on HW
735 npad->sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
736 }
737
738 npad->sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
739 npad->sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
740 npad->sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
741 npad->sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
742 }
743}
744
745void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
746 hid_core.SetSupportedStyleTag(style_set); 567 hid_core.SetSupportedStyleTag(style_set);
747 568
748 if (is_controller_initialized) { 569 if (is_controller_initialized) {
@@ -753,14 +574,14 @@ void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
753 is_controller_initialized = true; 574 is_controller_initialized = true;
754} 575}
755 576
756Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const { 577Core::HID::NpadStyleTag NPad::GetSupportedStyleSet() const {
757 if (!is_controller_initialized) { 578 if (!is_controller_initialized) {
758 return {Core::HID::NpadStyleSet::None}; 579 return {Core::HID::NpadStyleSet::None};
759 } 580 }
760 return hid_core.GetSupportedStyleTag(); 581 return hid_core.GetSupportedStyleTag();
761} 582}
762 583
763Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) { 584Result NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
764 constexpr std::size_t max_number_npad_ids = 0xa; 585 constexpr std::size_t max_number_npad_ids = 0xa;
765 const auto length = data.size(); 586 const auto length = data.size();
766 ASSERT(length > 0 && (length % sizeof(u32)) == 0); 587 ASSERT(length > 0 && (length % sizeof(u32)) == 0);
@@ -776,17 +597,17 @@ Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
776 return ResultSuccess; 597 return ResultSuccess;
777} 598}
778 599
779void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { 600void NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
780 const auto copy_amount = supported_npad_id_types.size() * sizeof(u32); 601 const auto copy_amount = supported_npad_id_types.size() * sizeof(u32);
781 ASSERT(max_length <= copy_amount); 602 ASSERT(max_length <= copy_amount);
782 std::memcpy(data, supported_npad_id_types.data(), copy_amount); 603 std::memcpy(data, supported_npad_id_types.data(), copy_amount);
783} 604}
784 605
785std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { 606std::size_t NPad::GetSupportedNpadIdTypesSize() const {
786 return supported_npad_id_types.size(); 607 return supported_npad_id_types.size();
787} 608}
788 609
789void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) { 610void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
790 if (joy_hold_type != NpadJoyHoldType::Horizontal && 611 if (joy_hold_type != NpadJoyHoldType::Horizontal &&
791 joy_hold_type != NpadJoyHoldType::Vertical) { 612 joy_hold_type != NpadJoyHoldType::Vertical) {
792 LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}", 613 LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}",
@@ -796,11 +617,11 @@ void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
796 hold_type = joy_hold_type; 617 hold_type = joy_hold_type;
797} 618}
798 619
799Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const { 620NPad::NpadJoyHoldType NPad::GetHoldType() const {
800 return hold_type; 621 return hold_type;
801} 622}
802 623
803void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) { 624void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
804 if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) { 625 if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) {
805 ASSERT_MSG(false, "Activation mode should be always None, Single or Dual"); 626 ASSERT_MSG(false, "Activation mode should be always None, Single or Dual");
806 return; 627 return;
@@ -809,21 +630,20 @@ void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode a
809 handheld_activation_mode = activation_mode; 630 handheld_activation_mode = activation_mode;
810} 631}
811 632
812Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const { 633NPad::NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
813 return handheld_activation_mode; 634 return handheld_activation_mode;
814} 635}
815 636
816void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) { 637void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
817 communication_mode = communication_mode_; 638 communication_mode = communication_mode_;
818} 639}
819 640
820Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const { 641NPad::NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
821 return communication_mode; 642 return communication_mode;
822} 643}
823 644
824bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, 645bool NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
825 NpadJoyDeviceType npad_device_type, 646 NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) {
826 NpadJoyAssignmentMode assignment_mode) {
827 if (!IsNpadIdValid(npad_id)) { 647 if (!IsNpadIdValid(npad_id)) {
828 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 648 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
829 return false; 649 return false;
@@ -892,9 +712,8 @@ bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID:
892 return true; 712 return true;
893} 713}
894 714
895bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, 715bool NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
896 std::size_t device_index, 716 const Core::HID::VibrationValue& vibration_value) {
897 const Core::HID::VibrationValue& vibration_value) {
898 auto& controller = GetControllerFromNpadIdType(npad_id); 717 auto& controller = GetControllerFromNpadIdType(npad_id);
899 if (!controller.device->IsConnected()) { 718 if (!controller.device->IsConnected()) {
900 return false; 719 return false;
@@ -938,10 +757,9 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
938 return controller.device->SetVibration(device_index, vibration); 757 return controller.device->SetVibration(device_index, vibration);
939} 758}
940 759
941void Controller_NPad::VibrateController( 760void NPad::VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle,
942 const Core::HID::VibrationDeviceHandle& vibration_device_handle, 761 const Core::HID::VibrationValue& vibration_value) {
943 const Core::HID::VibrationValue& vibration_value) { 762 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
944 if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
945 return; 763 return;
946 } 764 }
947 765
@@ -985,7 +803,7 @@ void Controller_NPad::VibrateController(
985 } 803 }
986} 804}
987 805
988void Controller_NPad::VibrateControllers( 806void NPad::VibrateControllers(
989 std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, 807 std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
990 std::span<const Core::HID::VibrationValue> vibration_values) { 808 std::span<const Core::HID::VibrationValue> vibration_values) {
991 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { 809 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
@@ -1002,9 +820,9 @@ void Controller_NPad::VibrateControllers(
1002 } 820 }
1003} 821}
1004 822
1005Core::HID::VibrationValue Controller_NPad::GetLastVibration( 823Core::HID::VibrationValue NPad::GetLastVibration(
1006 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { 824 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
1007 if (IsDeviceHandleValid(vibration_device_handle).IsError()) { 825 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
1008 return {}; 826 return {};
1009 } 827 }
1010 828
@@ -1013,9 +831,9 @@ Core::HID::VibrationValue Controller_NPad::GetLastVibration(
1013 return controller.vibration[device_index].latest_vibration_value; 831 return controller.vibration[device_index].latest_vibration_value;
1014} 832}
1015 833
1016void Controller_NPad::InitializeVibrationDevice( 834void NPad::InitializeVibrationDevice(
1017 const Core::HID::VibrationDeviceHandle& vibration_device_handle) { 835 const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
1018 if (IsDeviceHandleValid(vibration_device_handle).IsError()) { 836 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
1019 return; 837 return;
1020 } 838 }
1021 839
@@ -1024,8 +842,8 @@ void Controller_NPad::InitializeVibrationDevice(
1024 InitializeVibrationDeviceAtIndex(npad_index, device_index); 842 InitializeVibrationDeviceAtIndex(npad_index, device_index);
1025} 843}
1026 844
1027void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id, 845void NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
1028 std::size_t device_index) { 846 std::size_t device_index) {
1029 auto& controller = GetControllerFromNpadIdType(npad_id); 847 auto& controller = GetControllerFromNpadIdType(npad_id);
1030 if (!Settings::values.vibration_enabled.GetValue()) { 848 if (!Settings::values.vibration_enabled.GetValue()) {
1031 controller.vibration[device_index].device_mounted = false; 849 controller.vibration[device_index].device_mounted = false;
@@ -1036,13 +854,13 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npa
1036 controller.device->IsVibrationEnabled(device_index); 854 controller.device->IsVibrationEnabled(device_index);
1037} 855}
1038 856
1039void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { 857void NPad::SetPermitVibrationSession(bool permit_vibration_session) {
1040 permit_vibration_session_enabled = permit_vibration_session; 858 permit_vibration_session_enabled = permit_vibration_session;
1041} 859}
1042 860
1043bool Controller_NPad::IsVibrationDeviceMounted( 861bool NPad::IsVibrationDeviceMounted(
1044 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { 862 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
1045 if (IsDeviceHandleValid(vibration_device_handle).IsError()) { 863 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
1046 return false; 864 return false;
1047 } 865 }
1048 866
@@ -1051,7 +869,7 @@ bool Controller_NPad::IsVibrationDeviceMounted(
1051 return controller.vibration[device_index].device_mounted; 869 return controller.vibration[device_index].device_mounted;
1052} 870}
1053 871
1054Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) { 872Kernel::KReadableEvent& NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
1055 if (!IsNpadIdValid(npad_id)) { 873 if (!IsNpadIdValid(npad_id)) {
1056 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 874 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1057 // Fallback to player 1 875 // Fallback to player 1
@@ -1063,18 +881,17 @@ Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::Npad
1063 return controller.styleset_changed_event->GetReadableEvent(); 881 return controller.styleset_changed_event->GetReadableEvent();
1064} 882}
1065 883
1066void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const { 884void NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
1067 const auto& controller = GetControllerFromNpadIdType(npad_id); 885 const auto& controller = GetControllerFromNpadIdType(npad_id);
1068 controller.styleset_changed_event->Signal(); 886 controller.styleset_changed_event->Signal();
1069} 887}
1070 888
1071void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, 889void NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id) {
1072 Core::HID::NpadIdType npad_id) {
1073 UpdateControllerAt(controller, npad_id, true); 890 UpdateControllerAt(controller, npad_id, true);
1074} 891}
1075 892
1076void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, 893void NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, Core::HID::NpadIdType npad_id,
1077 Core::HID::NpadIdType npad_id, bool connected) { 894 bool connected) {
1078 auto& controller = GetControllerFromNpadIdType(npad_id); 895 auto& controller = GetControllerFromNpadIdType(npad_id);
1079 if (!connected) { 896 if (!connected) {
1080 DisconnectNpad(npad_id); 897 DisconnectNpad(npad_id);
@@ -1085,7 +902,7 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
1085 InitNewlyAddedController(npad_id); 902 InitNewlyAddedController(npad_id);
1086} 903}
1087 904
1088Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { 905Result NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
1089 if (!IsNpadIdValid(npad_id)) { 906 if (!IsNpadIdValid(npad_id)) {
1090 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 907 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1091 return InvalidNpadId; 908 return InvalidNpadId;
@@ -1134,54 +951,9 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
1134 return ResultSuccess; 951 return ResultSuccess;
1135} 952}
1136 953
1137Result Controller_NPad::SetGyroscopeZeroDriftMode( 954Result NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
1138 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1139 Core::HID::GyroscopeZeroDriftMode drift_mode) {
1140 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1141 if (is_valid.IsError()) {
1142 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1143 return is_valid;
1144 }
1145
1146 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1147 auto& controller = GetControllerFromHandle(sixaxis_handle);
1148 sixaxis.gyroscope_zero_drift_mode = drift_mode;
1149 controller.device->SetGyroscopeZeroDriftMode(drift_mode);
1150
1151 return ResultSuccess;
1152}
1153
1154Result Controller_NPad::GetGyroscopeZeroDriftMode(
1155 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1156 Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
1157 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1158 if (is_valid.IsError()) {
1159 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1160 return is_valid;
1161 }
1162
1163 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1164 drift_mode = sixaxis.gyroscope_zero_drift_mode;
1165
1166 return ResultSuccess;
1167}
1168
1169Result Controller_NPad::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1170 bool& is_at_rest) const {
1171 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1172 if (is_valid.IsError()) {
1173 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1174 return is_valid;
1175 }
1176
1177 const auto& controller = GetControllerFromHandle(sixaxis_handle);
1178 is_at_rest = controller.sixaxis_at_rest;
1179 return ResultSuccess;
1180}
1181
1182Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
1183 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const { 955 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const {
1184 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 956 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
1185 if (is_valid.IsError()) { 957 if (is_valid.IsError()) {
1186 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); 958 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1187 return is_valid; 959 return is_valid;
@@ -1192,65 +964,9 @@ Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
1192 return ResultSuccess; 964 return ResultSuccess;
1193} 965}
1194 966
1195Result Controller_NPad::EnableSixAxisSensorUnalteredPassthrough( 967Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
1196 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
1197 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1198 if (is_valid.IsError()) {
1199 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1200 return is_valid;
1201 }
1202
1203 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1204 sixaxis.unaltered_passtrough = is_enabled;
1205 return ResultSuccess;
1206}
1207
1208Result Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled(
1209 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
1210 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1211 if (is_valid.IsError()) {
1212 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1213 return is_valid;
1214 }
1215
1216 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1217 is_enabled = sixaxis.unaltered_passtrough;
1218 return ResultSuccess;
1219}
1220
1221Result Controller_NPad::LoadSixAxisSensorCalibrationParameter(
1222 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1223 Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
1224 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1225 if (is_valid.IsError()) {
1226 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1227 return is_valid;
1228 }
1229
1230 // TODO: Request this data to the controller. On error return 0xd8ca
1231 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1232 calibration = sixaxis.calibration;
1233 return ResultSuccess;
1234}
1235
1236Result Controller_NPad::GetSixAxisSensorIcInformation(
1237 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1238 Core::HID::SixAxisSensorIcInformation& ic_information) const {
1239 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1240 if (is_valid.IsError()) {
1241 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1242 return is_valid;
1243 }
1244
1245 // TODO: Request this data to the controller. On error return 0xd8ca
1246 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1247 ic_information = sixaxis.ic_information;
1248 return ResultSuccess;
1249}
1250
1251Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
1252 const Core::HID::SixAxisSensorHandle& sixaxis_handle) { 968 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
1253 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 969 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
1254 if (is_valid.IsError()) { 970 if (is_valid.IsError()) {
1255 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); 971 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1256 return is_valid; 972 return is_valid;
@@ -1262,83 +978,32 @@ Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
1262 return ResultSuccess; 978 return ResultSuccess;
1263} 979}
1264 980
1265Result Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 981NPad::SixAxisLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
1266 bool sixaxis_status) { 982 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo;
1267 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1268 if (is_valid.IsError()) {
1269 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1270 return is_valid;
1271 }
1272
1273 auto& controller = GetControllerFromHandle(sixaxis_handle);
1274 controller.sixaxis_sensor_enabled = sixaxis_status;
1275 return ResultSuccess;
1276} 983}
1277 984
1278Result Controller_NPad::IsSixAxisSensorFusionEnabled( 985NPad::SixAxisLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
1279 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const { 986 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo;
1280 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1281 if (is_valid.IsError()) {
1282 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1283 return is_valid;
1284 }
1285
1286 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1287 is_fusion_enabled = sixaxis.is_fusion_enabled;
1288
1289 return ResultSuccess;
1290} 987}
1291Result Controller_NPad::SetSixAxisFusionEnabled(
1292 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) {
1293 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1294 if (is_valid.IsError()) {
1295 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1296 return is_valid;
1297 }
1298 988
1299 auto& sixaxis = GetSixaxisState(sixaxis_handle); 989NPad::SixAxisLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
1300 sixaxis.is_fusion_enabled = is_fusion_enabled; 990 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo;
1301
1302 return ResultSuccess;
1303} 991}
1304 992
1305Result Controller_NPad::SetSixAxisFusionParameters( 993NPad::SixAxisLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
1306 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 994 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo;
1307 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
1308 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1309 if (is_valid.IsError()) {
1310 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1311 return is_valid;
1312 }
1313
1314 const auto param1 = sixaxis_fusion_parameters.parameter1;
1315 if (param1 < 0.0f || param1 > 1.0f) {
1316 return InvalidSixAxisFusionRange;
1317 }
1318
1319 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1320 sixaxis.fusion = sixaxis_fusion_parameters;
1321
1322 return ResultSuccess;
1323} 995}
1324 996
1325Result Controller_NPad::GetSixAxisFusionParameters( 997NPad::SixAxisLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
1326 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 998 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo;
1327 Core::HID::SixAxisSensorFusionParameters& parameters) const { 999}
1328 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1329 if (is_valid.IsError()) {
1330 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1331 return is_valid;
1332 }
1333
1334 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1335 parameters = sixaxis.fusion;
1336 1000
1337 return ResultSuccess; 1001NPad::SixAxisLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
1002 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo;
1338} 1003}
1339 1004
1340Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, 1005Result NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
1341 Core::HID::NpadIdType npad_id_2) { 1006 Core::HID::NpadIdType npad_id_2) {
1342 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { 1007 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1343 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, 1008 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1344 npad_id_2); 1009 npad_id_2);
@@ -1400,18 +1065,17 @@ Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
1400 return ResultSuccess; 1065 return ResultSuccess;
1401} 1066}
1402 1067
1403void Controller_NPad::StartLRAssignmentMode() { 1068void NPad::StartLRAssignmentMode() {
1404 // Nothing internally is used for lr assignment mode. Since we have the ability to set the 1069 // Nothing internally is used for lr assignment mode. Since we have the ability to set the
1405 // controller types from boot, it doesn't really matter about showing a selection screen 1070 // controller types from boot, it doesn't really matter about showing a selection screen
1406 is_in_lr_assignment_mode = true; 1071 is_in_lr_assignment_mode = true;
1407} 1072}
1408 1073
1409void Controller_NPad::StopLRAssignmentMode() { 1074void NPad::StopLRAssignmentMode() {
1410 is_in_lr_assignment_mode = false; 1075 is_in_lr_assignment_mode = false;
1411} 1076}
1412 1077
1413Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, 1078Result NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2) {
1414 Core::HID::NpadIdType npad_id_2) {
1415 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { 1079 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1416 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, 1080 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1417 npad_id_2); 1081 npad_id_2);
@@ -1442,8 +1106,7 @@ Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
1442 return ResultSuccess; 1106 return ResultSuccess;
1443} 1107}
1444 1108
1445Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id, 1109Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const {
1446 Core::HID::LedPattern& pattern) const {
1447 if (!IsNpadIdValid(npad_id)) { 1110 if (!IsNpadIdValid(npad_id)) {
1448 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1111 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1449 return InvalidNpadId; 1112 return InvalidNpadId;
@@ -1453,8 +1116,8 @@ Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
1453 return ResultSuccess; 1116 return ResultSuccess;
1454} 1117}
1455 1118
1456Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, 1119Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
1457 bool& is_valid) const { 1120 bool& is_valid) const {
1458 if (!IsNpadIdValid(npad_id)) { 1121 if (!IsNpadIdValid(npad_id)) {
1459 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1122 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1460 return InvalidNpadId; 1123 return InvalidNpadId;
@@ -1464,8 +1127,8 @@ Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::
1464 return ResultSuccess; 1127 return ResultSuccess;
1465} 1128}
1466 1129
1467Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled( 1130Result NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
1468 bool is_protection_enabled, Core::HID::NpadIdType npad_id) { 1131 Core::HID::NpadIdType npad_id) {
1469 if (!IsNpadIdValid(npad_id)) { 1132 if (!IsNpadIdValid(npad_id)) {
1470 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1133 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1471 return InvalidNpadId; 1134 return InvalidNpadId;
@@ -1475,11 +1138,11 @@ Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
1475 return ResultSuccess; 1138 return ResultSuccess;
1476} 1139}
1477 1140
1478void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { 1141void NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
1479 analog_stick_use_center_clamp = use_center_clamp; 1142 analog_stick_use_center_clamp = use_center_clamp;
1480} 1143}
1481 1144
1482void Controller_NPad::ClearAllConnectedControllers() { 1145void NPad::ClearAllConnectedControllers() {
1483 for (auto& controller : controller_data) { 1146 for (auto& controller : controller_data) {
1484 if (controller.device->IsConnected() && 1147 if (controller.device->IsConnected() &&
1485 controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) { 1148 controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
@@ -1489,13 +1152,13 @@ void Controller_NPad::ClearAllConnectedControllers() {
1489 } 1152 }
1490} 1153}
1491 1154
1492void Controller_NPad::DisconnectAllConnectedControllers() { 1155void NPad::DisconnectAllConnectedControllers() {
1493 for (auto& controller : controller_data) { 1156 for (auto& controller : controller_data) {
1494 controller.device->Disconnect(); 1157 controller.device->Disconnect();
1495 } 1158 }
1496} 1159}
1497 1160
1498void Controller_NPad::ConnectAllDisconnectedControllers() { 1161void NPad::ConnectAllDisconnectedControllers() {
1499 for (auto& controller : controller_data) { 1162 for (auto& controller : controller_data) {
1500 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None && 1163 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
1501 !controller.device->IsConnected()) { 1164 !controller.device->IsConnected()) {
@@ -1504,18 +1167,18 @@ void Controller_NPad::ConnectAllDisconnectedControllers() {
1504 } 1167 }
1505} 1168}
1506 1169
1507void Controller_NPad::ClearAllControllers() { 1170void NPad::ClearAllControllers() {
1508 for (auto& controller : controller_data) { 1171 for (auto& controller : controller_data) {
1509 controller.device->Disconnect(); 1172 controller.device->Disconnect();
1510 controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); 1173 controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
1511 } 1174 }
1512} 1175}
1513 1176
1514Core::HID::NpadButton Controller_NPad::GetAndResetPressState() { 1177Core::HID::NpadButton NPad::GetAndResetPressState() {
1515 return static_cast<Core::HID::NpadButton>(press_state.exchange(0)); 1178 return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
1516} 1179}
1517 1180
1518void Controller_NPad::ApplyNpadSystemCommonPolicy() { 1181void NPad::ApplyNpadSystemCommonPolicy() {
1519 Core::HID::NpadStyleTag styletag{}; 1182 Core::HID::NpadStyleTag styletag{};
1520 styletag.fullkey.Assign(1); 1183 styletag.fullkey.Assign(1);
1521 styletag.handheld.Assign(1); 1184 styletag.handheld.Assign(1);
@@ -1540,7 +1203,7 @@ void Controller_NPad::ApplyNpadSystemCommonPolicy() {
1540 supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; 1203 supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld;
1541} 1204}
1542 1205
1543bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const { 1206bool NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
1544 if (controller == Core::HID::NpadStyleIndex::Handheld) { 1207 if (controller == Core::HID::NpadStyleIndex::Handheld) {
1545 const bool support_handheld = 1208 const bool support_handheld =
1546 std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 1209 std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
@@ -1591,51 +1254,50 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
1591 return false; 1254 return false;
1592} 1255}
1593 1256
1594Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( 1257NPad::NpadControllerData& NPad::GetControllerFromHandle(
1595 const Core::HID::SixAxisSensorHandle& device_handle) { 1258 const Core::HID::VibrationDeviceHandle& device_handle) {
1596 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); 1259 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1597 return GetControllerFromNpadIdType(npad_id); 1260 return GetControllerFromNpadIdType(npad_id);
1598} 1261}
1599 1262
1600const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( 1263const NPad::NpadControllerData& NPad::GetControllerFromHandle(
1601 const Core::HID::SixAxisSensorHandle& device_handle) const { 1264 const Core::HID::VibrationDeviceHandle& device_handle) const {
1602 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); 1265 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1603 return GetControllerFromNpadIdType(npad_id); 1266 return GetControllerFromNpadIdType(npad_id);
1604} 1267}
1605 1268
1606Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( 1269NPad::NpadControllerData& NPad::GetControllerFromHandle(
1607 const Core::HID::VibrationDeviceHandle& device_handle) { 1270 const Core::HID::SixAxisSensorHandle& device_handle) {
1608 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); 1271 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1609 return GetControllerFromNpadIdType(npad_id); 1272 return GetControllerFromNpadIdType(npad_id);
1610} 1273}
1611 1274
1612const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( 1275const NPad::NpadControllerData& NPad::GetControllerFromHandle(
1613 const Core::HID::VibrationDeviceHandle& device_handle) const { 1276 const Core::HID::SixAxisSensorHandle& device_handle) const {
1614 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); 1277 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1615 return GetControllerFromNpadIdType(npad_id); 1278 return GetControllerFromNpadIdType(npad_id);
1616} 1279}
1617 1280
1618Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType( 1281NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) {
1619 Core::HID::NpadIdType npad_id) {
1620 if (!IsNpadIdValid(npad_id)) { 1282 if (!IsNpadIdValid(npad_id)) {
1621 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1283 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1622 npad_id = Core::HID::NpadIdType::Player1; 1284 npad_id = Core::HID::NpadIdType::Player1;
1623 } 1285 }
1624 const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id); 1286 const auto npad_index = NpadIdTypeToIndex(npad_id);
1625 return controller_data[npad_index]; 1287 return controller_data[npad_index];
1626} 1288}
1627 1289
1628const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType( 1290const NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(
1629 Core::HID::NpadIdType npad_id) const { 1291 Core::HID::NpadIdType npad_id) const {
1630 if (!IsNpadIdValid(npad_id)) { 1292 if (!IsNpadIdValid(npad_id)) {
1631 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1293 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1632 npad_id = Core::HID::NpadIdType::Player1; 1294 npad_id = Core::HID::NpadIdType::Player1;
1633 } 1295 }
1634 const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id); 1296 const auto npad_index = NpadIdTypeToIndex(npad_id);
1635 return controller_data[npad_index]; 1297 return controller_data[npad_index];
1636} 1298}
1637 1299
1638Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties( 1300Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
1639 const Core::HID::SixAxisSensorHandle& sixaxis_handle) { 1301 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
1640 auto& controller = GetControllerFromHandle(sixaxis_handle); 1302 auto& controller = GetControllerFromHandle(sixaxis_handle);
1641 switch (sixaxis_handle.npad_type) { 1303 switch (sixaxis_handle.npad_type) {
@@ -1658,7 +1320,7 @@ Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
1658 } 1320 }
1659} 1321}
1660 1322
1661const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties( 1323const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
1662 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { 1324 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
1663 const auto& controller = GetControllerFromHandle(sixaxis_handle); 1325 const auto& controller = GetControllerFromHandle(sixaxis_handle);
1664 switch (sixaxis_handle.npad_type) { 1326 switch (sixaxis_handle.npad_type) {
@@ -1681,65 +1343,13 @@ const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
1681 } 1343 }
1682} 1344}
1683 1345
1684Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState( 1346NPad::AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
1685 const Core::HID::SixAxisSensorHandle& sixaxis_handle) { 1347 const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory;
1686 auto& controller = GetControllerFromHandle(sixaxis_handle);
1687 switch (sixaxis_handle.npad_type) {
1688 case Core::HID::NpadStyleIndex::ProController:
1689 case Core::HID::NpadStyleIndex::Pokeball:
1690 return controller.sixaxis_fullkey;
1691 case Core::HID::NpadStyleIndex::Handheld:
1692 return controller.sixaxis_handheld;
1693 case Core::HID::NpadStyleIndex::JoyconDual:
1694 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1695 return controller.sixaxis_dual_left;
1696 }
1697 return controller.sixaxis_dual_right;
1698 case Core::HID::NpadStyleIndex::JoyconLeft:
1699 return controller.sixaxis_left;
1700 case Core::HID::NpadStyleIndex::JoyconRight:
1701 return controller.sixaxis_right;
1702 default:
1703 return controller.sixaxis_unknown;
1704 }
1705}
1706
1707const Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
1708 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
1709 const auto& controller = GetControllerFromHandle(sixaxis_handle);
1710 switch (sixaxis_handle.npad_type) {
1711 case Core::HID::NpadStyleIndex::ProController:
1712 case Core::HID::NpadStyleIndex::Pokeball:
1713 return controller.sixaxis_fullkey;
1714 case Core::HID::NpadStyleIndex::Handheld:
1715 return controller.sixaxis_handheld;
1716 case Core::HID::NpadStyleIndex::JoyconDual:
1717 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1718 return controller.sixaxis_dual_left;
1719 }
1720 return controller.sixaxis_dual_right;
1721 case Core::HID::NpadStyleIndex::JoyconLeft:
1722 return controller.sixaxis_left;
1723 case Core::HID::NpadStyleIndex::JoyconRight:
1724 return controller.sixaxis_right;
1725 default:
1726 return controller.sixaxis_unknown;
1727 }
1728}
1729
1730Controller_NPad::AppletDetailedUiType Controller_NPad::GetAppletDetailedUiType(
1731 Core::HID::NpadIdType npad_id) {
1732
1733 auto controller = GetControllerFromNpadIdType(npad_id);
1734 auto shared_memory = controller.shared_memory;
1735 Service::HID::Controller_NPad::AppletFooterUiType applet_footer_type =
1736 shared_memory->applet_footer_type;
1737 1348
1738 Controller_NPad::AppletDetailedUiType detailed_ui_type{ 1349 return {
1739 .ui_variant = 0, 1350 .ui_variant = 0,
1740 .footer = applet_footer_type, 1351 .footer = shared_memory->applet_footer_type,
1741 }; 1352 };
1742 return detailed_ui_type;
1743} 1353}
1744 1354
1745} // namespace Service::HID 1355} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index cd93abdd1..9167c93f0 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -10,7 +10,6 @@
10 10
11#include "common/bit_field.h" 11#include "common/bit_field.h"
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/vector_math.h"
14 13
15#include "core/hid/hid_types.h" 14#include "core/hid/hid_types.h"
16#include "core/hle/service/hid/controllers/controller_base.h" 15#include "core/hle/service/hid/controllers/controller_base.h"
@@ -34,11 +33,11 @@ union Result;
34 33
35namespace Service::HID { 34namespace Service::HID {
36 35
37class Controller_NPad final : public ControllerBase { 36class NPad final : public ControllerBase {
38public: 37public:
39 explicit Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 38 explicit NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
40 KernelHelpers::ServiceContext& service_context_); 39 KernelHelpers::ServiceContext& service_context_);
41 ~Controller_NPad() override; 40 ~NPad() override;
42 41
43 // Called when the controller is initialized 42 // Called when the controller is initialized
44 void OnInit() override; 43 void OnInit() override;
@@ -49,9 +48,6 @@ public:
49 // When the controller is requesting an update for the shared memory 48 // When the controller is requesting an update for the shared memory
50 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 49 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
51 50
52 // When the controller is requesting a motion update for the shared memory
53 void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) override;
54
55 // This is nn::hid::NpadJoyHoldType 51 // This is nn::hid::NpadJoyHoldType
56 enum class NpadJoyHoldType : u64 { 52 enum class NpadJoyHoldType : u64 {
57 Vertical = 0, 53 Vertical = 0,
@@ -133,6 +129,8 @@ public:
133 Revision3 = 3, 129 Revision3 = 3,
134 }; 130 };
135 131
132 using SixAxisLifo = Lifo<Core::HID::SixAxisSensorState, hid_entry_count>;
133
136 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); 134 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
137 Core::HID::NpadStyleTag GetSupportedStyleSet() const; 135 Core::HID::NpadStyleTag GetSupportedStyleSet() const;
138 136
@@ -185,37 +183,18 @@ public:
185 183
186 Result DisconnectNpad(Core::HID::NpadIdType npad_id); 184 Result DisconnectNpad(Core::HID::NpadIdType npad_id);
187 185
188 Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
189 Core::HID::GyroscopeZeroDriftMode drift_mode);
190 Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
191 Core::HID::GyroscopeZeroDriftMode& drift_mode) const;
192 Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
193 bool& is_at_rest) const;
194 Result IsFirmwareUpdateAvailableForSixAxisSensor( 186 Result IsFirmwareUpdateAvailableForSixAxisSensor(
195 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const; 187 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const;
196 Result EnableSixAxisSensorUnalteredPassthrough(
197 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
198 Result IsSixAxisSensorUnalteredPassthroughEnabled(
199 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
200 Result LoadSixAxisSensorCalibrationParameter(
201 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
202 Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
203 Result GetSixAxisSensorIcInformation(
204 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
205 Core::HID::SixAxisSensorIcInformation& ic_information) const;
206 Result ResetIsSixAxisSensorDeviceNewlyAssigned( 188 Result ResetIsSixAxisSensorDeviceNewlyAssigned(
207 const Core::HID::SixAxisSensorHandle& sixaxis_handle); 189 const Core::HID::SixAxisSensorHandle& sixaxis_handle);
208 Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 190
209 bool sixaxis_status); 191 SixAxisLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
210 Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 192 SixAxisLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
211 bool& is_fusion_enabled) const; 193 SixAxisLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
212 Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 194 SixAxisLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
213 bool is_fusion_enabled); 195 SixAxisLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
214 Result SetSixAxisFusionParameters( 196 SixAxisLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
215 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 197
216 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
217 Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
218 Core::HID::SixAxisSensorFusionParameters& parameters) const;
219 Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; 198 Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
220 Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, 199 Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
221 bool& is_enabled) const; 200 bool& is_enabled) const;
@@ -239,10 +218,6 @@ public:
239 218
240 void ApplyNpadSystemCommonPolicy(); 219 void ApplyNpadSystemCommonPolicy();
241 220
242 static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
243 static Result IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
244 static Result VerifyValidSixAxisSensorHandle(
245 const Core::HID::SixAxisSensorHandle& device_handle);
246 AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); 221 AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
247 222
248private: 223private:
@@ -302,29 +277,6 @@ private:
302 }; 277 };
303 static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size"); 278 static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
304 279
305 // This is nn::hid::SixAxisSensorAttribute
306 struct SixAxisSensorAttribute {
307 union {
308 u32 raw{};
309 BitField<0, 1, u32> is_connected;
310 BitField<1, 1, u32> is_interpolated;
311 };
312 };
313 static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size");
314
315 // This is nn::hid::SixAxisSensorState
316 struct SixAxisSensorState {
317 s64 delta_time{};
318 s64 sampling_number{};
319 Common::Vec3f accel{};
320 Common::Vec3f gyro{};
321 Common::Vec3f rotation{};
322 std::array<Common::Vec3f, 3> orientation{};
323 SixAxisSensorAttribute attribute{};
324 INSERT_PADDING_BYTES(4); // Reserved
325 };
326 static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size");
327
328 // This is nn::hid::server::NpadGcTriggerState 280 // This is nn::hid::server::NpadGcTriggerState
329 struct NpadGcTriggerState { 281 struct NpadGcTriggerState {
330 s64 sampling_number{}; 282 s64 sampling_number{};
@@ -444,12 +396,12 @@ private:
444 Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{}; 396 Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{};
445 Lifo<NPadGenericState, hid_entry_count> palma_lifo{}; 397 Lifo<NPadGenericState, hid_entry_count> palma_lifo{};
446 Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{}; 398 Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{};
447 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{}; 399 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
448 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{}; 400 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
449 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{}; 401 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
450 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{}; 402 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
451 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{}; 403 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
452 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{}; 404 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
453 DeviceType device_type{}; 405 DeviceType device_type{};
454 INSERT_PADDING_BYTES(0x4); // Reserved 406 INSERT_PADDING_BYTES(0x4); // Reserved
455 NPadSystemProperties system_properties{}; 407 NPadSystemProperties system_properties{};
@@ -483,16 +435,6 @@ private:
483 std::chrono::steady_clock::time_point last_vibration_timepoint{}; 435 std::chrono::steady_clock::time_point last_vibration_timepoint{};
484 }; 436 };
485 437
486 struct SixaxisParameters {
487 bool is_fusion_enabled{true};
488 bool unaltered_passtrough{false};
489 Core::HID::SixAxisSensorFusionParameters fusion{};
490 Core::HID::SixAxisSensorCalibrationParameter calibration{};
491 Core::HID::SixAxisSensorIcInformation ic_information{};
492 Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{
493 Core::HID::GyroscopeZeroDriftMode::Standard};
494 };
495
496 struct NpadControllerData { 438 struct NpadControllerData {
497 Kernel::KEvent* styleset_changed_event{}; 439 Kernel::KEvent* styleset_changed_event{};
498 NpadInternalState* shared_memory = nullptr; 440 NpadInternalState* shared_memory = nullptr;
@@ -506,27 +448,10 @@ private:
506 bool is_dual_left_connected{true}; 448 bool is_dual_left_connected{true};
507 bool is_dual_right_connected{true}; 449 bool is_dual_right_connected{true};
508 450
509 // Motion parameters
510 bool sixaxis_at_rest{true};
511 bool sixaxis_sensor_enabled{true};
512 SixaxisParameters sixaxis_fullkey{};
513 SixaxisParameters sixaxis_handheld{};
514 SixaxisParameters sixaxis_dual_left{};
515 SixaxisParameters sixaxis_dual_right{};
516 SixaxisParameters sixaxis_left{};
517 SixaxisParameters sixaxis_right{};
518 SixaxisParameters sixaxis_unknown{};
519
520 // Current pad state 451 // Current pad state
521 NPadGenericState npad_pad_state{}; 452 NPadGenericState npad_pad_state{};
522 NPadGenericState npad_libnx_state{}; 453 NPadGenericState npad_libnx_state{};
523 NpadGcTriggerState npad_trigger_state{}; 454 NpadGcTriggerState npad_trigger_state{};
524 SixAxisSensorState sixaxis_fullkey_state{};
525 SixAxisSensorState sixaxis_handheld_state{};
526 SixAxisSensorState sixaxis_dual_left_state{};
527 SixAxisSensorState sixaxis_dual_right_state{};
528 SixAxisSensorState sixaxis_left_lifo_state{};
529 SixAxisSensorState sixaxis_right_lifo_state{};
530 int callback_key{}; 455 int callback_key{};
531 }; 456 };
532 457
@@ -537,13 +462,13 @@ private:
537 void WriteEmptyEntry(NpadInternalState* npad); 462 void WriteEmptyEntry(NpadInternalState* npad);
538 463
539 NpadControllerData& GetControllerFromHandle( 464 NpadControllerData& GetControllerFromHandle(
540 const Core::HID::SixAxisSensorHandle& device_handle);
541 const NpadControllerData& GetControllerFromHandle(
542 const Core::HID::SixAxisSensorHandle& device_handle) const;
543 NpadControllerData& GetControllerFromHandle(
544 const Core::HID::VibrationDeviceHandle& device_handle); 465 const Core::HID::VibrationDeviceHandle& device_handle);
545 const NpadControllerData& GetControllerFromHandle( 466 const NpadControllerData& GetControllerFromHandle(
546 const Core::HID::VibrationDeviceHandle& device_handle) const; 467 const Core::HID::VibrationDeviceHandle& device_handle) const;
468 NpadControllerData& GetControllerFromHandle(
469 const Core::HID::SixAxisSensorHandle& device_handle);
470 const NpadControllerData& GetControllerFromHandle(
471 const Core::HID::SixAxisSensorHandle& device_handle) const;
547 NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); 472 NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
548 const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; 473 const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
549 474
@@ -551,9 +476,6 @@ private:
551 const Core::HID::SixAxisSensorHandle& device_handle); 476 const Core::HID::SixAxisSensorHandle& device_handle);
552 const Core::HID::SixAxisSensorProperties& GetSixaxisProperties( 477 const Core::HID::SixAxisSensorProperties& GetSixaxisProperties(
553 const Core::HID::SixAxisSensorHandle& device_handle) const; 478 const Core::HID::SixAxisSensorHandle& device_handle) const;
554 SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
555 const SixaxisParameters& GetSixaxisState(
556 const Core::HID::SixAxisSensorHandle& device_handle) const;
557 479
558 std::atomic<u64> press_state{}; 480 std::atomic<u64> press_state{};
559 481
diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp
index 51a18335f..588ff9d62 100644
--- a/src/core/hle/service/hid/controllers/palma.cpp
+++ b/src/core/hle/service/hid/controllers/palma.cpp
@@ -12,35 +12,35 @@
12 12
13namespace Service::HID { 13namespace Service::HID {
14 14
15Controller_Palma::Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 15Palma::Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
16 KernelHelpers::ServiceContext& service_context_) 16 KernelHelpers::ServiceContext& service_context_)
17 : ControllerBase{hid_core_}, service_context{service_context_} { 17 : ControllerBase{hid_core_}, service_context{service_context_} {
18 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); 18 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
19 operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent"); 19 operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
20} 20}
21 21
22Controller_Palma::~Controller_Palma() { 22Palma::~Palma() {
23 service_context.CloseEvent(operation_complete_event); 23 service_context.CloseEvent(operation_complete_event);
24}; 24};
25 25
26void Controller_Palma::OnInit() {} 26void Palma::OnInit() {}
27 27
28void Controller_Palma::OnRelease() {} 28void Palma::OnRelease() {}
29 29
30void Controller_Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 30void Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
31 if (!IsControllerActivated()) { 31 if (!IsControllerActivated()) {
32 return; 32 return;
33 } 33 }
34} 34}
35 35
36Result Controller_Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, 36Result Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id,
37 PalmaConnectionHandle& handle) { 37 PalmaConnectionHandle& handle) {
38 active_handle.npad_id = npad_id; 38 active_handle.npad_id = npad_id;
39 handle = active_handle; 39 handle = active_handle;
40 return ResultSuccess; 40 return ResultSuccess;
41} 41}
42 42
43Result Controller_Palma::InitializePalma(const PalmaConnectionHandle& handle) { 43Result Palma::InitializePalma(const PalmaConnectionHandle& handle) {
44 if (handle.npad_id != active_handle.npad_id) { 44 if (handle.npad_id != active_handle.npad_id) {
45 return InvalidPalmaHandle; 45 return InvalidPalmaHandle;
46 } 46 }
@@ -48,7 +48,7 @@ Result Controller_Palma::InitializePalma(const PalmaConnectionHandle& handle) {
48 return ResultSuccess; 48 return ResultSuccess;
49} 49}
50 50
51Kernel::KReadableEvent& Controller_Palma::AcquirePalmaOperationCompleteEvent( 51Kernel::KReadableEvent& Palma::AcquirePalmaOperationCompleteEvent(
52 const PalmaConnectionHandle& handle) const { 52 const PalmaConnectionHandle& handle) const {
53 if (handle.npad_id != active_handle.npad_id) { 53 if (handle.npad_id != active_handle.npad_id) {
54 LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id); 54 LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id);
@@ -56,9 +56,9 @@ Kernel::KReadableEvent& Controller_Palma::AcquirePalmaOperationCompleteEvent(
56 return operation_complete_event->GetReadableEvent(); 56 return operation_complete_event->GetReadableEvent();
57} 57}
58 58
59Result Controller_Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle, 59Result Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle,
60 PalmaOperationType& operation_type, 60 PalmaOperationType& operation_type,
61 PalmaOperationData& data) const { 61 PalmaOperationData& data) const {
62 if (handle.npad_id != active_handle.npad_id) { 62 if (handle.npad_id != active_handle.npad_id) {
63 return InvalidPalmaHandle; 63 return InvalidPalmaHandle;
64 } 64 }
@@ -67,8 +67,7 @@ Result Controller_Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& hand
67 return ResultSuccess; 67 return ResultSuccess;
68} 68}
69 69
70Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, 70Result Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity) {
71 u64 palma_activity) {
72 if (handle.npad_id != active_handle.npad_id) { 71 if (handle.npad_id != active_handle.npad_id) {
73 return InvalidPalmaHandle; 72 return InvalidPalmaHandle;
74 } 73 }
@@ -79,8 +78,7 @@ Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle,
79 return ResultSuccess; 78 return ResultSuccess;
80} 79}
81 80
82Result Controller_Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, 81Result Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_) {
83 PalmaFrModeType fr_mode_) {
84 if (handle.npad_id != active_handle.npad_id) { 82 if (handle.npad_id != active_handle.npad_id) {
85 return InvalidPalmaHandle; 83 return InvalidPalmaHandle;
86 } 84 }
@@ -88,7 +86,7 @@ Result Controller_Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle,
88 return ResultSuccess; 86 return ResultSuccess;
89} 87}
90 88
91Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) { 89Result Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
92 if (handle.npad_id != active_handle.npad_id) { 90 if (handle.npad_id != active_handle.npad_id) {
93 return InvalidPalmaHandle; 91 return InvalidPalmaHandle;
94 } 92 }
@@ -99,25 +97,25 @@ Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
99 return ResultSuccess; 97 return ResultSuccess;
100} 98}
101 99
102Result Controller_Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) { 100Result Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) {
103 if (handle.npad_id != active_handle.npad_id) { 101 if (handle.npad_id != active_handle.npad_id) {
104 return InvalidPalmaHandle; 102 return InvalidPalmaHandle;
105 } 103 }
106 return ResultSuccess; 104 return ResultSuccess;
107} 105}
108 106
109Result Controller_Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) { 107Result Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) {
110 if (handle.npad_id != active_handle.npad_id) { 108 if (handle.npad_id != active_handle.npad_id) {
111 return InvalidPalmaHandle; 109 return InvalidPalmaHandle;
112 } 110 }
113 return ResultSuccess; 111 return ResultSuccess;
114} 112}
115 113
116void Controller_Palma::ReadPalmaApplicationSection() {} 114void Palma::ReadPalmaApplicationSection() {}
117 115
118void Controller_Palma::WritePalmaApplicationSection() {} 116void Palma::WritePalmaApplicationSection() {}
119 117
120Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) { 118Result Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) {
121 if (handle.npad_id != active_handle.npad_id) { 119 if (handle.npad_id != active_handle.npad_id) {
122 return InvalidPalmaHandle; 120 return InvalidPalmaHandle;
123 } 121 }
@@ -128,7 +126,7 @@ Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle
128 return ResultSuccess; 126 return ResultSuccess;
129} 127}
130 128
131Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) { 129Result Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) {
132 if (handle.npad_id != active_handle.npad_id) { 130 if (handle.npad_id != active_handle.npad_id) {
133 return InvalidPalmaHandle; 131 return InvalidPalmaHandle;
134 } 132 }
@@ -139,10 +137,9 @@ Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle&
139 return ResultSuccess; 137 return ResultSuccess;
140} 138}
141 139
142void Controller_Palma::WritePalmaActivityEntry() {} 140void Palma::WritePalmaActivityEntry() {}
143 141
144Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, 142Result Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown) {
145 u64 unknown) {
146 if (handle.npad_id != active_handle.npad_id) { 143 if (handle.npad_id != active_handle.npad_id) {
147 return InvalidPalmaHandle; 144 return InvalidPalmaHandle;
148 } 145 }
@@ -153,8 +150,8 @@ Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandl
153 return ResultSuccess; 150 return ResultSuccess;
154} 151}
155 152
156Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, 153Result Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave,
157 Common::ProcessAddress t_mem, u64 size) { 154 Common::ProcessAddress t_mem, u64 size) {
158 if (handle.npad_id != active_handle.npad_id) { 155 if (handle.npad_id != active_handle.npad_id) {
159 return InvalidPalmaHandle; 156 return InvalidPalmaHandle;
160 } 157 }
@@ -165,8 +162,8 @@ Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle
165 return ResultSuccess; 162 return ResultSuccess;
166} 163}
167 164
168Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, 165Result Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle,
169 s32 database_id_version_) { 166 s32 database_id_version_) {
170 if (handle.npad_id != active_handle.npad_id) { 167 if (handle.npad_id != active_handle.npad_id) {
171 return InvalidPalmaHandle; 168 return InvalidPalmaHandle;
172 } 169 }
@@ -178,8 +175,7 @@ Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnec
178 return ResultSuccess; 175 return ResultSuccess;
179} 176}
180 177
181Result Controller_Palma::GetPalmaDataBaseIdentificationVersion( 178Result Palma::GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle) {
182 const PalmaConnectionHandle& handle) {
183 if (handle.npad_id != active_handle.npad_id) { 179 if (handle.npad_id != active_handle.npad_id) {
184 return InvalidPalmaHandle; 180 return InvalidPalmaHandle;
185 } 181 }
@@ -191,26 +187,26 @@ Result Controller_Palma::GetPalmaDataBaseIdentificationVersion(
191 return ResultSuccess; 187 return ResultSuccess;
192} 188}
193 189
194void Controller_Palma::SuspendPalmaFeature() {} 190void Palma::SuspendPalmaFeature() {}
195 191
196Result Controller_Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const { 192Result Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const {
197 if (handle.npad_id != active_handle.npad_id) { 193 if (handle.npad_id != active_handle.npad_id) {
198 return InvalidPalmaHandle; 194 return InvalidPalmaHandle;
199 } 195 }
200 return operation.result; 196 return operation.result;
201} 197}
202void Controller_Palma::ReadPalmaPlayLog() {} 198void Palma::ReadPalmaPlayLog() {}
203 199
204void Controller_Palma::ResetPalmaPlayLog() {} 200void Palma::ResetPalmaPlayLog() {}
205 201
206void Controller_Palma::SetIsPalmaAllConnectable(bool is_all_connectable) { 202void Palma::SetIsPalmaAllConnectable(bool is_all_connectable) {
207 // If true controllers are able to be paired 203 // If true controllers are able to be paired
208 is_connectable = is_all_connectable; 204 is_connectable = is_all_connectable;
209} 205}
210 206
211void Controller_Palma::SetIsPalmaPairedConnectable() {} 207void Palma::SetIsPalmaPairedConnectable() {}
212 208
213Result Controller_Palma::PairPalma(const PalmaConnectionHandle& handle) { 209Result Palma::PairPalma(const PalmaConnectionHandle& handle) {
214 if (handle.npad_id != active_handle.npad_id) { 210 if (handle.npad_id != active_handle.npad_id) {
215 return InvalidPalmaHandle; 211 return InvalidPalmaHandle;
216 } 212 }
@@ -218,14 +214,14 @@ Result Controller_Palma::PairPalma(const PalmaConnectionHandle& handle) {
218 return ResultSuccess; 214 return ResultSuccess;
219} 215}
220 216
221void Controller_Palma::SetPalmaBoostMode(bool boost_mode) {} 217void Palma::SetPalmaBoostMode(bool boost_mode) {}
222 218
223void Controller_Palma::CancelWritePalmaWaveEntry() {} 219void Palma::CancelWritePalmaWaveEntry() {}
224 220
225void Controller_Palma::EnablePalmaBoostMode() {} 221void Palma::EnablePalmaBoostMode() {}
226 222
227void Controller_Palma::GetPalmaBluetoothAddress() {} 223void Palma::GetPalmaBluetoothAddress() {}
228 224
229void Controller_Palma::SetDisallowedPalmaConnection() {} 225void Palma::SetDisallowedPalmaConnection() {}
230 226
231} // namespace Service::HID 227} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h
index a0491a819..a6047f36a 100644
--- a/src/core/hle/service/hid/controllers/palma.h
+++ b/src/core/hle/service/hid/controllers/palma.h
@@ -23,7 +23,7 @@ class EmulatedController;
23} // namespace Core::HID 23} // namespace Core::HID
24 24
25namespace Service::HID { 25namespace Service::HID {
26class Controller_Palma final : public ControllerBase { 26class Palma final : public ControllerBase {
27public: 27public:
28 using PalmaOperationData = std::array<u8, 0x140>; 28 using PalmaOperationData = std::array<u8, 0x140>;
29 29
@@ -97,9 +97,9 @@ public:
97 static_assert(sizeof(PalmaConnectionHandle) == 0x8, 97 static_assert(sizeof(PalmaConnectionHandle) == 0x8,
98 "PalmaConnectionHandle has incorrect size."); 98 "PalmaConnectionHandle has incorrect size.");
99 99
100 explicit Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 100 explicit Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
101 KernelHelpers::ServiceContext& service_context_); 101 KernelHelpers::ServiceContext& service_context_);
102 ~Controller_Palma() override; 102 ~Palma() override;
103 103
104 // Called when the controller is initialized 104 // Called when the controller is initialized
105 void OnInit() override; 105 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/seven_six_axis.cpp
index bcb272eaf..495568484 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/seven_six_axis.cpp
@@ -1,32 +1,29 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include <cstring>
5#include "common/common_types.h"
4#include "core/core.h" 6#include "core/core.h"
5#include "core/core_timing.h" 7#include "core/core_timing.h"
8#include "core/frontend/emu_window.h"
6#include "core/hid/emulated_console.h" 9#include "core/hid/emulated_console.h"
10#include "core/hid/emulated_devices.h"
7#include "core/hid/hid_core.h" 11#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/console_sixaxis.h" 12#include "core/hle/service/hid/controllers/seven_six_axis.h"
9#include "core/memory.h" 13#include "core/memory.h"
10 14
11namespace Service::HID { 15namespace Service::HID {
12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; 16SevenSixAxis::SevenSixAxis(Core::System& system_)
13
14Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_)
15 : ControllerBase{system_.HIDCore()}, system{system_} { 17 : ControllerBase{system_.HIDCore()}, system{system_} {
16 console = hid_core.GetEmulatedConsole(); 18 console = hid_core.GetEmulatedConsole();
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
18 "ConsoleSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at(
20 reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
21} 19}
22 20
23Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default; 21SevenSixAxis::~SevenSixAxis() = default;
24
25void Controller_ConsoleSixAxis::OnInit() {}
26 22
27void Controller_ConsoleSixAxis::OnRelease() {} 23void SevenSixAxis::OnInit() {}
24void SevenSixAxis::OnRelease() {}
28 25
29void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 26void SevenSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
30 if (!IsControllerActivated() || transfer_memory == 0) { 27 if (!IsControllerActivated() || transfer_memory == 0) {
31 seven_sixaxis_lifo.buffer_count = 0; 28 seven_sixaxis_lifo.buffer_count = 0;
32 seven_sixaxis_lifo.buffer_tail = 0; 29 seven_sixaxis_lifo.buffer_tail = 0;
@@ -53,22 +50,17 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
53 -motion_status.quaternion.xyz.z, 50 -motion_status.quaternion.xyz.z,
54 }; 51 };
55 52
56 shared_memory->sampling_number++;
57 shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
58 shared_memory->verticalization_error = motion_status.verticalization_error;
59 shared_memory->gyro_bias = motion_status.gyro_bias;
60
61 // Update seven six axis transfer memory
62 seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); 53 seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
63 system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, 54 system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo,
64 sizeof(seven_sixaxis_lifo)); 55 sizeof(seven_sixaxis_lifo));
65} 56}
66 57
67void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { 58void SevenSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
68 transfer_memory = t_mem; 59 transfer_memory = t_mem;
69} 60}
70 61
71void Controller_ConsoleSixAxis::ResetTimestamp() { 62void SevenSixAxis::ResetTimestamp() {
72 last_saved_timestamp = last_global_timestamp; 63 last_saved_timestamp = last_global_timestamp;
73} 64}
65
74} // namespace Service::HID 66} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/seven_six_axis.h
index 7015d924c..40e3f5d12 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/seven_six_axis.h
@@ -1,10 +1,9 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include <array> 6#include "common/common_types.h"
7
8#include "common/quaternion.h" 7#include "common/quaternion.h"
9#include "common/typed_address.h" 8#include "common/typed_address.h"
10#include "core/hle/service/hid/controllers/controller_base.h" 9#include "core/hle/service/hid/controllers/controller_base.h"
@@ -19,10 +18,10 @@ class EmulatedConsole;
19} // namespace Core::HID 18} // namespace Core::HID
20 19
21namespace Service::HID { 20namespace Service::HID {
22class Controller_ConsoleSixAxis final : public ControllerBase { 21class SevenSixAxis final : public ControllerBase {
23public: 22public:
24 explicit Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_); 23 explicit SevenSixAxis(Core::System& system_);
25 ~Controller_ConsoleSixAxis() override; 24 ~SevenSixAxis() override;
26 25
27 // Called when the controller is initialized 26 // Called when the controller is initialized
28 void OnInit() override; 27 void OnInit() override;
@@ -51,28 +50,16 @@ private:
51 }; 50 };
52 static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size"); 51 static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size");
53 52
54 // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
55 struct ConsoleSharedMemory {
56 u64 sampling_number{};
57 bool is_seven_six_axis_sensor_at_rest{};
58 INSERT_PADDING_BYTES(3); // padding
59 f32 verticalization_error{};
60 Common::Vec3f gyro_bias{};
61 INSERT_PADDING_BYTES(4); // padding
62 };
63 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
64
65 Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{}; 53 Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{};
66 static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); 54 static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size");
67 55
56 u64 last_saved_timestamp{};
57 u64 last_global_timestamp{};
58
68 SevenSixAxisState next_seven_sixaxis_state{}; 59 SevenSixAxisState next_seven_sixaxis_state{};
69 Common::ProcessAddress transfer_memory{}; 60 Common::ProcessAddress transfer_memory{};
70 ConsoleSharedMemory* shared_memory = nullptr;
71 Core::HID::EmulatedConsole* console = nullptr; 61 Core::HID::EmulatedConsole* console = nullptr;
72 62
73 u64 last_saved_timestamp{};
74 u64 last_global_timestamp{};
75
76 Core::System& system; 63 Core::System& system;
77}; 64};
78} // namespace Service::HID 65} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/six_axis.cpp b/src/core/hle/service/hid/controllers/six_axis.cpp
new file mode 100644
index 000000000..3d24a5c04
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/six_axis.cpp
@@ -0,0 +1,413 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "common/common_types.h"
5#include "core/core_timing.h"
6#include "core/hid/emulated_controller.h"
7#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/npad.h"
9#include "core/hle/service/hid/controllers/six_axis.h"
10#include "core/hle/service/hid/errors.h"
11#include "core/hle/service/hid/hid_util.h"
12
13namespace Service::HID {
14
15SixAxis::SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_)
16 : ControllerBase{hid_core_}, npad{npad_} {
17 for (std::size_t i = 0; i < controller_data.size(); ++i) {
18 auto& controller = controller_data[i];
19 controller.device = hid_core.GetEmulatedControllerByIndex(i);
20 }
21}
22
23SixAxis::~SixAxis() = default;
24
25void SixAxis::OnInit() {}
26void SixAxis::OnRelease() {}
27
28void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
29 if (!IsControllerActivated()) {
30 return;
31 }
32
33 for (std::size_t i = 0; i < controller_data.size(); ++i) {
34 auto& controller = controller_data[i];
35
36 const auto npad_id = IndexToNpadIdType(i);
37 const auto& controller_type = controller.device->GetNpadStyleIndex();
38
39 if (controller_type == Core::HID::NpadStyleIndex::None ||
40 !controller.device->IsConnected()) {
41 continue;
42 }
43
44 const auto& motion_state = controller.device->GetMotions();
45 auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
46 auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
47 auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
48 auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
49 auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
50 auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
51
52 auto& sixaxis_fullkey_lifo = npad->GetSixAxisFullkeyLifo(npad_id);
53 auto& sixaxis_handheld_lifo = npad->GetSixAxisHandheldLifo(npad_id);
54 auto& sixaxis_dual_left_lifo = npad->GetSixAxisDualLeftLifo(npad_id);
55 auto& sixaxis_dual_right_lifo = npad->GetSixAxisDualRightLifo(npad_id);
56 auto& sixaxis_left_lifo = npad->GetSixAxisLeftLifo(npad_id);
57 auto& sixaxis_right_lifo = npad->GetSixAxisRightLifo(npad_id);
58
59 // Clear previous state
60 sixaxis_fullkey_state = {};
61 sixaxis_handheld_state = {};
62 sixaxis_dual_left_state = {};
63 sixaxis_dual_right_state = {};
64 sixaxis_left_lifo_state = {};
65 sixaxis_right_lifo_state = {};
66
67 if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
68 controller.sixaxis_at_rest = true;
69 for (std::size_t e = 0; e < motion_state.size(); ++e) {
70 controller.sixaxis_at_rest =
71 controller.sixaxis_at_rest && motion_state[e].is_at_rest;
72 }
73 }
74
75 const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state,
76 const Core::HID::ControllerMotion& hid_state) {
77 using namespace std::literals::chrono_literals;
78 static constexpr Core::HID::SixAxisSensorState default_motion_state = {
79 .delta_time = std::chrono::nanoseconds(5ms).count(),
80 .accel = {0, 0, -1.0f},
81 .orientation =
82 {
83 Common::Vec3f{1.0f, 0, 0},
84 Common::Vec3f{0, 1.0f, 0},
85 Common::Vec3f{0, 0, 1.0f},
86 },
87 .attribute = {1},
88 };
89 if (!controller.sixaxis_sensor_enabled) {
90 state = default_motion_state;
91 return;
92 }
93 if (!Settings::values.motion_enabled.GetValue()) {
94 state = default_motion_state;
95 return;
96 }
97 state.attribute.is_connected.Assign(1);
98 state.delta_time = std::chrono::nanoseconds(5ms).count();
99 state.accel = hid_state.accel;
100 state.gyro = hid_state.gyro;
101 state.rotation = hid_state.rotation;
102 state.orientation = hid_state.orientation;
103 };
104
105 switch (controller_type) {
106 case Core::HID::NpadStyleIndex::None:
107 ASSERT(false);
108 break;
109 case Core::HID::NpadStyleIndex::ProController:
110 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
111 break;
112 case Core::HID::NpadStyleIndex::Handheld:
113 set_motion_state(sixaxis_handheld_state, motion_state[0]);
114 break;
115 case Core::HID::NpadStyleIndex::JoyconDual:
116 set_motion_state(sixaxis_dual_left_state, motion_state[0]);
117 set_motion_state(sixaxis_dual_right_state, motion_state[1]);
118 break;
119 case Core::HID::NpadStyleIndex::JoyconLeft:
120 set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
121 break;
122 case Core::HID::NpadStyleIndex::JoyconRight:
123 set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
124 break;
125 case Core::HID::NpadStyleIndex::Pokeball:
126 using namespace std::literals::chrono_literals;
127 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
128 sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
129 break;
130 default:
131 break;
132 }
133
134 sixaxis_fullkey_state.sampling_number =
135 sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
136 sixaxis_handheld_state.sampling_number =
137 sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
138 sixaxis_dual_left_state.sampling_number =
139 sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
140 sixaxis_dual_right_state.sampling_number =
141 sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
142 sixaxis_left_lifo_state.sampling_number =
143 sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
144 sixaxis_right_lifo_state.sampling_number =
145 sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
146
147 if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
148 // This buffer only is updated on handheld on HW
149 sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
150 } else {
151 // Handheld doesn't update this buffer on HW
152 sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
153 }
154
155 sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
156 sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
157 sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
158 sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
159 }
160}
161
162Result SixAxis::SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
163 Core::HID::GyroscopeZeroDriftMode drift_mode) {
164 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
165 if (is_valid.IsError()) {
166 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
167 return is_valid;
168 }
169
170 auto& sixaxis = GetSixaxisState(sixaxis_handle);
171 auto& controller = GetControllerFromHandle(sixaxis_handle);
172 sixaxis.gyroscope_zero_drift_mode = drift_mode;
173 controller.device->SetGyroscopeZeroDriftMode(drift_mode);
174
175 return ResultSuccess;
176}
177
178Result SixAxis::GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
179 Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
180 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
181 if (is_valid.IsError()) {
182 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
183 return is_valid;
184 }
185
186 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
187 drift_mode = sixaxis.gyroscope_zero_drift_mode;
188
189 return ResultSuccess;
190}
191
192Result SixAxis::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
193 bool& is_at_rest) const {
194 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
195 if (is_valid.IsError()) {
196 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
197 return is_valid;
198 }
199
200 const auto& controller = GetControllerFromHandle(sixaxis_handle);
201 is_at_rest = controller.sixaxis_at_rest;
202 return ResultSuccess;
203}
204
205Result SixAxis::LoadSixAxisSensorCalibrationParameter(
206 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
207 Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
208 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
209 if (is_valid.IsError()) {
210 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
211 return is_valid;
212 }
213
214 // TODO: Request this data to the controller. On error return 0xd8ca
215 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
216 calibration = sixaxis.calibration;
217 return ResultSuccess;
218}
219
220Result SixAxis::GetSixAxisSensorIcInformation(
221 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
222 Core::HID::SixAxisSensorIcInformation& ic_information) const {
223 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
224 if (is_valid.IsError()) {
225 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
226 return is_valid;
227 }
228
229 // TODO: Request this data to the controller. On error return 0xd8ca
230 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
231 ic_information = sixaxis.ic_information;
232 return ResultSuccess;
233}
234
235Result SixAxis::EnableSixAxisSensorUnalteredPassthrough(
236 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
237 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
238 if (is_valid.IsError()) {
239 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
240 return is_valid;
241 }
242
243 auto& sixaxis = GetSixaxisState(sixaxis_handle);
244 sixaxis.unaltered_passtrough = is_enabled;
245 return ResultSuccess;
246}
247
248Result SixAxis::IsSixAxisSensorUnalteredPassthroughEnabled(
249 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
250 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
251 if (is_valid.IsError()) {
252 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
253 return is_valid;
254 }
255
256 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
257 is_enabled = sixaxis.unaltered_passtrough;
258 return ResultSuccess;
259}
260
261Result SixAxis::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
262 bool sixaxis_status) {
263 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
264 if (is_valid.IsError()) {
265 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
266 return is_valid;
267 }
268
269 auto& controller = GetControllerFromHandle(sixaxis_handle);
270 controller.sixaxis_sensor_enabled = sixaxis_status;
271 return ResultSuccess;
272}
273
274Result SixAxis::IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
275 bool& is_fusion_enabled) const {
276 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
277 if (is_valid.IsError()) {
278 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
279 return is_valid;
280 }
281
282 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
283 is_fusion_enabled = sixaxis.is_fusion_enabled;
284
285 return ResultSuccess;
286}
287Result SixAxis::SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
288 bool is_fusion_enabled) {
289 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
290 if (is_valid.IsError()) {
291 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
292 return is_valid;
293 }
294
295 auto& sixaxis = GetSixaxisState(sixaxis_handle);
296 sixaxis.is_fusion_enabled = is_fusion_enabled;
297
298 return ResultSuccess;
299}
300
301Result SixAxis::SetSixAxisFusionParameters(
302 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
303 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
304 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
305 if (is_valid.IsError()) {
306 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
307 return is_valid;
308 }
309
310 const auto param1 = sixaxis_fusion_parameters.parameter1;
311 if (param1 < 0.0f || param1 > 1.0f) {
312 return InvalidSixAxisFusionRange;
313 }
314
315 auto& sixaxis = GetSixaxisState(sixaxis_handle);
316 sixaxis.fusion = sixaxis_fusion_parameters;
317
318 return ResultSuccess;
319}
320
321Result SixAxis::GetSixAxisFusionParameters(
322 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
323 Core::HID::SixAxisSensorFusionParameters& parameters) const {
324 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
325 if (is_valid.IsError()) {
326 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
327 return is_valid;
328 }
329
330 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
331 parameters = sixaxis.fusion;
332
333 return ResultSuccess;
334}
335
336SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
337 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
338 auto& controller = GetControllerFromHandle(sixaxis_handle);
339 switch (sixaxis_handle.npad_type) {
340 case Core::HID::NpadStyleIndex::ProController:
341 case Core::HID::NpadStyleIndex::Pokeball:
342 return controller.sixaxis_fullkey;
343 case Core::HID::NpadStyleIndex::Handheld:
344 return controller.sixaxis_handheld;
345 case Core::HID::NpadStyleIndex::JoyconDual:
346 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
347 return controller.sixaxis_dual_left;
348 }
349 return controller.sixaxis_dual_right;
350 case Core::HID::NpadStyleIndex::JoyconLeft:
351 return controller.sixaxis_left;
352 case Core::HID::NpadStyleIndex::JoyconRight:
353 return controller.sixaxis_right;
354 default:
355 return controller.sixaxis_unknown;
356 }
357}
358
359const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
360 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
361 const auto& controller = GetControllerFromHandle(sixaxis_handle);
362 switch (sixaxis_handle.npad_type) {
363 case Core::HID::NpadStyleIndex::ProController:
364 case Core::HID::NpadStyleIndex::Pokeball:
365 return controller.sixaxis_fullkey;
366 case Core::HID::NpadStyleIndex::Handheld:
367 return controller.sixaxis_handheld;
368 case Core::HID::NpadStyleIndex::JoyconDual:
369 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
370 return controller.sixaxis_dual_left;
371 }
372 return controller.sixaxis_dual_right;
373 case Core::HID::NpadStyleIndex::JoyconLeft:
374 return controller.sixaxis_left;
375 case Core::HID::NpadStyleIndex::JoyconRight:
376 return controller.sixaxis_right;
377 default:
378 return controller.sixaxis_unknown;
379 }
380}
381
382SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle(
383 const Core::HID::SixAxisSensorHandle& device_handle) {
384 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
385 return GetControllerFromNpadIdType(npad_id);
386}
387
388const SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle(
389 const Core::HID::SixAxisSensorHandle& device_handle) const {
390 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
391 return GetControllerFromNpadIdType(npad_id);
392}
393
394SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) {
395 if (!IsNpadIdValid(npad_id)) {
396 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
397 npad_id = Core::HID::NpadIdType::Player1;
398 }
399 const auto npad_index = NpadIdTypeToIndex(npad_id);
400 return controller_data[npad_index];
401}
402
403const SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(
404 Core::HID::NpadIdType npad_id) const {
405 if (!IsNpadIdValid(npad_id)) {
406 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
407 npad_id = Core::HID::NpadIdType::Player1;
408 }
409 const auto npad_index = NpadIdTypeToIndex(npad_id);
410 return controller_data[npad_index];
411}
412
413} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/six_axis.h b/src/core/hle/service/hid/controllers/six_axis.h
new file mode 100644
index 000000000..4c4f5dc7b
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/six_axis.h
@@ -0,0 +1,111 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "common/common_types.h"
7#include "core/hid/hid_types.h"
8#include "core/hle/service/hid/controllers/controller_base.h"
9#include "core/hle/service/hid/ring_lifo.h"
10
11namespace Core::HID {
12class EmulatedController;
13} // namespace Core::HID
14
15namespace Service::HID {
16class NPad;
17
18class SixAxis final : public ControllerBase {
19public:
20 explicit SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_);
21 ~SixAxis() override;
22
23 // Called when the controller is initialized
24 void OnInit() override;
25
26 // When the controller is released
27 void OnRelease() override;
28
29 // When the controller is requesting an update for the shared memory
30 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
31
32 Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
33 Core::HID::GyroscopeZeroDriftMode drift_mode);
34 Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
35 Core::HID::GyroscopeZeroDriftMode& drift_mode) const;
36 Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
37 bool& is_at_rest) const;
38 Result EnableSixAxisSensorUnalteredPassthrough(
39 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
40 Result IsSixAxisSensorUnalteredPassthroughEnabled(
41 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
42 Result LoadSixAxisSensorCalibrationParameter(
43 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
44 Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
45 Result GetSixAxisSensorIcInformation(
46 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
47 Core::HID::SixAxisSensorIcInformation& ic_information) const;
48 Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
49 bool sixaxis_status);
50 Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
51 bool& is_fusion_enabled) const;
52 Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
53 bool is_fusion_enabled);
54 Result SetSixAxisFusionParameters(
55 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
56 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
57 Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
58 Core::HID::SixAxisSensorFusionParameters& parameters) const;
59
60private:
61 static constexpr std::size_t NPAD_COUNT = 10;
62
63 struct SixaxisParameters {
64 bool is_fusion_enabled{true};
65 bool unaltered_passtrough{false};
66 Core::HID::SixAxisSensorFusionParameters fusion{};
67 Core::HID::SixAxisSensorCalibrationParameter calibration{};
68 Core::HID::SixAxisSensorIcInformation ic_information{};
69 Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{
70 Core::HID::GyroscopeZeroDriftMode::Standard};
71 };
72
73 struct NpadControllerData {
74 Core::HID::EmulatedController* device = nullptr;
75
76 // Motion parameters
77 bool sixaxis_at_rest{true};
78 bool sixaxis_sensor_enabled{true};
79 SixaxisParameters sixaxis_fullkey{};
80 SixaxisParameters sixaxis_handheld{};
81 SixaxisParameters sixaxis_dual_left{};
82 SixaxisParameters sixaxis_dual_right{};
83 SixaxisParameters sixaxis_left{};
84 SixaxisParameters sixaxis_right{};
85 SixaxisParameters sixaxis_unknown{};
86
87 // Current pad state
88 Core::HID::SixAxisSensorState sixaxis_fullkey_state{};
89 Core::HID::SixAxisSensorState sixaxis_handheld_state{};
90 Core::HID::SixAxisSensorState sixaxis_dual_left_state{};
91 Core::HID::SixAxisSensorState sixaxis_dual_right_state{};
92 Core::HID::SixAxisSensorState sixaxis_left_lifo_state{};
93 Core::HID::SixAxisSensorState sixaxis_right_lifo_state{};
94 int callback_key{};
95 };
96
97 SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
98 const SixaxisParameters& GetSixaxisState(
99 const Core::HID::SixAxisSensorHandle& device_handle) const;
100
101 NpadControllerData& GetControllerFromHandle(
102 const Core::HID::SixAxisSensorHandle& device_handle);
103 const NpadControllerData& GetControllerFromHandle(
104 const Core::HID::SixAxisSensorHandle& device_handle) const;
105 NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
106 const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
107
108 std::shared_ptr<NPad> npad;
109 std::array<NpadControllerData, NPAD_COUNT> controller_data{};
110};
111} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 3ef91df4b..3bcf0ee9f 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -15,8 +15,7 @@
15namespace Service::HID { 15namespace Service::HID {
16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; 16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
17 17
18Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_, 18TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
19 u8* raw_shared_memory_)
20 : ControllerBase{hid_core_} { 19 : ControllerBase{hid_core_} {
21 static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size, 20 static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
22 "TouchSharedMemory is bigger than the shared memory"); 21 "TouchSharedMemory is bigger than the shared memory");
@@ -25,13 +24,13 @@ Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_,
25 console = hid_core.GetEmulatedConsole(); 24 console = hid_core.GetEmulatedConsole();
26} 25}
27 26
28Controller_Touchscreen::~Controller_Touchscreen() = default; 27TouchScreen::~TouchScreen() = default;
29 28
30void Controller_Touchscreen::OnInit() {} 29void TouchScreen::OnInit() {}
31 30
32void Controller_Touchscreen::OnRelease() {} 31void TouchScreen::OnRelease() {}
33 32
34void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 33void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
35 shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); 34 shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
36 35
37 if (!IsControllerActivated()) { 36 if (!IsControllerActivated()) {
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index dd00921fd..cd342ce91 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -14,10 +14,10 @@ class EmulatedConsole;
14} // namespace Core::HID 14} // namespace Core::HID
15 15
16namespace Service::HID { 16namespace Service::HID {
17class Controller_Touchscreen final : public ControllerBase { 17class TouchScreen final : public ControllerBase {
18public: 18public:
19 explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 19 explicit TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
20 ~Controller_Touchscreen() override; 20 ~TouchScreen() override;
21 21
22 // Called when the controller is initialized 22 // Called when the controller is initialized
23 void OnInit() override; 23 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
index 62119e2c5..0aaed1fa7 100644
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ b/src/core/hle/service/hid/controllers/xpad.cpp
@@ -10,20 +10,19 @@
10namespace Service::HID { 10namespace Service::HID {
11constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; 11constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
12 12
13Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 13XPad::XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
14 : ControllerBase{hid_core_} {
15 static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size, 14 static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size,
16 "XpadSharedMemory is bigger than the shared memory"); 15 "XpadSharedMemory is bigger than the shared memory");
17 shared_memory = std::construct_at( 16 shared_memory = std::construct_at(
18 reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); 17 reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
19} 18}
20Controller_XPad::~Controller_XPad() = default; 19XPad::~XPad() = default;
21 20
22void Controller_XPad::OnInit() {} 21void XPad::OnInit() {}
23 22
24void Controller_XPad::OnRelease() {} 23void XPad::OnRelease() {}
25 24
26void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 25void XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
27 if (!IsControllerActivated()) { 26 if (!IsControllerActivated()) {
28 shared_memory->basic_xpad_lifo.buffer_count = 0; 27 shared_memory->basic_xpad_lifo.buffer_count = 0;
29 shared_memory->basic_xpad_lifo.buffer_tail = 0; 28 shared_memory->basic_xpad_lifo.buffer_tail = 0;
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index d01dee5fc..9e63a317a 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -10,10 +10,10 @@
10#include "core/hle/service/hid/ring_lifo.h" 10#include "core/hle/service/hid/ring_lifo.h"
11 11
12namespace Service::HID { 12namespace Service::HID {
13class Controller_XPad final : public ControllerBase { 13class XPad final : public ControllerBase {
14public: 14public:
15 explicit Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 15 explicit XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
16 ~Controller_XPad() override; 16 ~XPad() override;
17 17
18 // Called when the controller is initialized 18 // Called when the controller is initialized
19 void OnInit() override; 19 void OnInit() override;
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp
index 9caed6541..583142e35 100644
--- a/src/core/hle/service/hid/hid_server.cpp
+++ b/src/core/hle/service/hid/hid_server.cpp
@@ -12,11 +12,12 @@
12#include "core/hle/service/hid/errors.h" 12#include "core/hle/service/hid/errors.h"
13#include "core/hle/service/hid/hid_firmware_settings.h" 13#include "core/hle/service/hid/hid_firmware_settings.h"
14#include "core/hle/service/hid/hid_server.h" 14#include "core/hle/service/hid/hid_server.h"
15#include "core/hle/service/hid/hid_util.h"
15#include "core/hle/service/hid/resource_manager.h" 16#include "core/hle/service/hid/resource_manager.h"
16#include "core/hle/service/ipc_helpers.h" 17#include "core/hle/service/ipc_helpers.h"
17#include "core/memory.h" 18#include "core/memory.h"
18 19
19#include "core/hle/service/hid/controllers/console_sixaxis.h" 20#include "core/hle/service/hid/controllers/console_six_axis.h"
20#include "core/hle/service/hid/controllers/controller_base.h" 21#include "core/hle/service/hid/controllers/controller_base.h"
21#include "core/hle/service/hid/controllers/debug_pad.h" 22#include "core/hle/service/hid/controllers/debug_pad.h"
22#include "core/hle/service/hid/controllers/gesture.h" 23#include "core/hle/service/hid/controllers/gesture.h"
@@ -24,9 +25,9 @@
24#include "core/hle/service/hid/controllers/mouse.h" 25#include "core/hle/service/hid/controllers/mouse.h"
25#include "core/hle/service/hid/controllers/npad.h" 26#include "core/hle/service/hid/controllers/npad.h"
26#include "core/hle/service/hid/controllers/palma.h" 27#include "core/hle/service/hid/controllers/palma.h"
27#include "core/hle/service/hid/controllers/stubbed.h" 28#include "core/hle/service/hid/controllers/seven_six_axis.h"
29#include "core/hle/service/hid/controllers/six_axis.h"
28#include "core/hle/service/hid/controllers/touchscreen.h" 30#include "core/hle/service/hid/controllers/touchscreen.h"
29#include "core/hle/service/hid/controllers/xpad.h"
30 31
31namespace Service::HID { 32namespace Service::HID {
32 33
@@ -50,8 +51,7 @@ private:
50 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; 51 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
51 52
52 if (resource_manager != nullptr) { 53 if (resource_manager != nullptr) {
53 resource_manager->GetController<Controller_NPad>(HidController::NPad) 54 resource_manager->GetNpad()->InitializeVibrationDevice(vibration_device_handle);
54 .InitializeVibrationDevice(vibration_device_handle);
55 } 55 }
56 56
57 LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", 57 LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}",
@@ -235,15 +235,14 @@ void IHidServer::ActivateDebugPad(HLERequestContext& ctx) {
235 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 235 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
236 236
237 Result result = ResultSuccess; 237 Result result = ResultSuccess;
238 auto& debug_pad = 238 auto debug_pad = GetResourceManager()->GetDebugPad();
239 GetResourceManager()->GetController<Controller_DebugPad>(HidController::DebugPad);
240 239
241 if (!firmware_settings->IsDeviceManaged()) { 240 if (!firmware_settings->IsDeviceManaged()) {
242 result = debug_pad.Activate(); 241 result = debug_pad->Activate();
243 } 242 }
244 243
245 if (result.IsSuccess()) { 244 if (result.IsSuccess()) {
246 result = debug_pad.Activate(applet_resource_user_id); 245 result = debug_pad->Activate(applet_resource_user_id);
247 } 246 }
248 247
249 IPC::ResponseBuilder rb{ctx, 2}; 248 IPC::ResponseBuilder rb{ctx, 2};
@@ -257,15 +256,14 @@ void IHidServer::ActivateTouchScreen(HLERequestContext& ctx) {
257 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 256 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
258 257
259 Result result = ResultSuccess; 258 Result result = ResultSuccess;
260 auto& touch_screen = 259 auto touch_screen = GetResourceManager()->GetTouchScreen();
261 GetResourceManager()->GetController<Controller_Touchscreen>(HidController::Touchscreen);
262 260
263 if (!firmware_settings->IsDeviceManaged()) { 261 if (!firmware_settings->IsDeviceManaged()) {
264 result = touch_screen.Activate(); 262 result = touch_screen->Activate();
265 } 263 }
266 264
267 if (result.IsSuccess()) { 265 if (result.IsSuccess()) {
268 result = touch_screen.Activate(applet_resource_user_id); 266 result = touch_screen->Activate(applet_resource_user_id);
269 } 267 }
270 268
271 IPC::ResponseBuilder rb{ctx, 2}; 269 IPC::ResponseBuilder rb{ctx, 2};
@@ -279,14 +277,14 @@ void IHidServer::ActivateMouse(HLERequestContext& ctx) {
279 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 277 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
280 278
281 Result result = ResultSuccess; 279 Result result = ResultSuccess;
282 auto& mouse = GetResourceManager()->GetController<Controller_Mouse>(HidController::Mouse); 280 auto mouse = GetResourceManager()->GetMouse();
283 281
284 if (!firmware_settings->IsDeviceManaged()) { 282 if (!firmware_settings->IsDeviceManaged()) {
285 result = mouse.Activate(); 283 result = mouse->Activate();
286 } 284 }
287 285
288 if (result.IsSuccess()) { 286 if (result.IsSuccess()) {
289 result = mouse.Activate(applet_resource_user_id); 287 result = mouse->Activate(applet_resource_user_id);
290 } 288 }
291 289
292 IPC::ResponseBuilder rb{ctx, 2}; 290 IPC::ResponseBuilder rb{ctx, 2};
@@ -300,15 +298,14 @@ void IHidServer::ActivateKeyboard(HLERequestContext& ctx) {
300 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 298 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
301 299
302 Result result = ResultSuccess; 300 Result result = ResultSuccess;
303 auto& keyboard = 301 auto keyboard = GetResourceManager()->GetKeyboard();
304 GetResourceManager()->GetController<Controller_Keyboard>(HidController::Keyboard);
305 302
306 if (!firmware_settings->IsDeviceManaged()) { 303 if (!firmware_settings->IsDeviceManaged()) {
307 result = keyboard.Activate(); 304 result = keyboard->Activate();
308 } 305 }
309 306
310 if (result.IsSuccess()) { 307 if (result.IsSuccess()) {
311 result = keyboard.Activate(applet_resource_user_id); 308 result = keyboard->Activate(applet_resource_user_id);
312 } 309 }
313 310
314 IPC::ResponseBuilder rb{ctx, 2}; 311 IPC::ResponseBuilder rb{ctx, 2};
@@ -502,8 +499,8 @@ void IHidServer::StartSixAxisSensor(HLERequestContext& ctx) {
502 499
503 const auto parameters{rp.PopRaw<Parameters>()}; 500 const auto parameters{rp.PopRaw<Parameters>()};
504 501
505 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 502 auto six_axis = GetResourceManager()->GetSixAxis();
506 const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, true); 503 const auto result = six_axis->SetSixAxisEnabled(parameters.sixaxis_handle, true);
507 504
508 LOG_DEBUG(Service_HID, 505 LOG_DEBUG(Service_HID,
509 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 506 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -525,8 +522,8 @@ void IHidServer::StopSixAxisSensor(HLERequestContext& ctx) {
525 522
526 const auto parameters{rp.PopRaw<Parameters>()}; 523 const auto parameters{rp.PopRaw<Parameters>()};
527 524
528 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 525 auto six_axis = GetResourceManager()->GetSixAxis();
529 const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, false); 526 const auto result = six_axis->SetSixAxisEnabled(parameters.sixaxis_handle, false);
530 527
531 LOG_DEBUG(Service_HID, 528 LOG_DEBUG(Service_HID,
532 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 529 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -549,9 +546,9 @@ void IHidServer::IsSixAxisSensorFusionEnabled(HLERequestContext& ctx) {
549 const auto parameters{rp.PopRaw<Parameters>()}; 546 const auto parameters{rp.PopRaw<Parameters>()};
550 547
551 bool is_enabled{}; 548 bool is_enabled{};
552 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 549 auto six_axis = GetResourceManager()->GetSixAxis();
553 const auto result = 550 const auto result =
554 controller.IsSixAxisSensorFusionEnabled(parameters.sixaxis_handle, is_enabled); 551 six_axis->IsSixAxisSensorFusionEnabled(parameters.sixaxis_handle, is_enabled);
555 552
556 LOG_DEBUG(Service_HID, 553 LOG_DEBUG(Service_HID,
557 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 554 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -575,9 +572,9 @@ void IHidServer::EnableSixAxisSensorFusion(HLERequestContext& ctx) {
575 572
576 const auto parameters{rp.PopRaw<Parameters>()}; 573 const auto parameters{rp.PopRaw<Parameters>()};
577 574
578 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 575 auto six_axis = GetResourceManager()->GetSixAxis();
579 const auto result = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle, 576 const auto result = six_axis->SetSixAxisFusionEnabled(parameters.sixaxis_handle,
580 parameters.enable_sixaxis_sensor_fusion); 577 parameters.enable_sixaxis_sensor_fusion);
581 578
582 LOG_DEBUG(Service_HID, 579 LOG_DEBUG(Service_HID,
583 "called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, " 580 "called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
@@ -602,9 +599,9 @@ void IHidServer::SetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
602 599
603 const auto parameters{rp.PopRaw<Parameters>()}; 600 const auto parameters{rp.PopRaw<Parameters>()};
604 601
605 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 602 auto six_axis = GetResourceManager()->GetSixAxis();
606 const auto result = 603 const auto result =
607 controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion); 604 six_axis->SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
608 605
609 LOG_DEBUG(Service_HID, 606 LOG_DEBUG(Service_HID,
610 "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, " 607 "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
@@ -629,10 +626,9 @@ void IHidServer::GetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
629 const auto parameters{rp.PopRaw<Parameters>()}; 626 const auto parameters{rp.PopRaw<Parameters>()};
630 627
631 Core::HID::SixAxisSensorFusionParameters fusion_parameters{}; 628 Core::HID::SixAxisSensorFusionParameters fusion_parameters{};
632 const auto& controller = 629 auto six_axis = GetResourceManager()->GetSixAxis();
633 GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
634 const auto result = 630 const auto result =
635 controller.GetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters); 631 six_axis->GetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
636 632
637 LOG_DEBUG(Service_HID, 633 LOG_DEBUG(Service_HID,
638 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 634 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -660,10 +656,10 @@ void IHidServer::ResetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
660 .parameter1 = 0.03f, 656 .parameter1 = 0.03f,
661 .parameter2 = 0.4f, 657 .parameter2 = 0.4f,
662 }; 658 };
663 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 659 auto six_axis = GetResourceManager()->GetSixAxis();
664 const auto result1 = 660 const auto result1 =
665 controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters); 661 six_axis->SetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
666 const auto result2 = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle, true); 662 const auto result2 = six_axis->SetSixAxisFusionEnabled(parameters.sixaxis_handle, true);
667 663
668 LOG_DEBUG(Service_HID, 664 LOG_DEBUG(Service_HID,
669 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 665 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -684,8 +680,8 @@ void IHidServer::SetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
684 const auto drift_mode{rp.PopEnum<Core::HID::GyroscopeZeroDriftMode>()}; 680 const auto drift_mode{rp.PopEnum<Core::HID::GyroscopeZeroDriftMode>()};
685 const auto applet_resource_user_id{rp.Pop<u64>()}; 681 const auto applet_resource_user_id{rp.Pop<u64>()};
686 682
687 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 683 auto six_axis = GetResourceManager()->GetSixAxis();
688 const auto result = controller.SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode); 684 const auto result = six_axis->SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
689 685
690 LOG_DEBUG(Service_HID, 686 LOG_DEBUG(Service_HID,
691 "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, " 687 "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, "
@@ -709,8 +705,8 @@ void IHidServer::GetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
709 const auto parameters{rp.PopRaw<Parameters>()}; 705 const auto parameters{rp.PopRaw<Parameters>()};
710 706
711 auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard}; 707 auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
712 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 708 auto six_axis = GetResourceManager()->GetSixAxis();
713 const auto result = controller.GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode); 709 const auto result = six_axis->GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
714 710
715 LOG_DEBUG(Service_HID, 711 LOG_DEBUG(Service_HID,
716 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 712 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -734,8 +730,8 @@ void IHidServer::ResetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
734 const auto parameters{rp.PopRaw<Parameters>()}; 730 const auto parameters{rp.PopRaw<Parameters>()};
735 731
736 const auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard}; 732 const auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
737 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 733 auto six_axis = GetResourceManager()->GetSixAxis();
738 const auto result = controller.SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode); 734 const auto result = six_axis->SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
739 735
740 LOG_DEBUG(Service_HID, 736 LOG_DEBUG(Service_HID,
741 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 737 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -758,8 +754,8 @@ void IHidServer::IsSixAxisSensorAtRest(HLERequestContext& ctx) {
758 const auto parameters{rp.PopRaw<Parameters>()}; 754 const auto parameters{rp.PopRaw<Parameters>()};
759 755
760 bool is_at_rest{}; 756 bool is_at_rest{};
761 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 757 auto six_axis = GetResourceManager()->GetSixAxis();
762 controller.IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest); 758 six_axis->IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest);
763 759
764 LOG_DEBUG(Service_HID, 760 LOG_DEBUG(Service_HID,
765 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 761 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -783,9 +779,9 @@ void IHidServer::IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ct
783 const auto parameters{rp.PopRaw<Parameters>()}; 779 const auto parameters{rp.PopRaw<Parameters>()};
784 780
785 bool is_firmware_available{}; 781 bool is_firmware_available{};
786 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 782 auto controller = GetResourceManager()->GetNpad();
787 controller.IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle, 783 controller->IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle,
788 is_firmware_available); 784 is_firmware_available);
789 785
790 LOG_WARNING( 786 LOG_WARNING(
791 Service_HID, 787 Service_HID,
@@ -809,9 +805,9 @@ void IHidServer::EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx)
809 805
810 const auto parameters{rp.PopRaw<Parameters>()}; 806 const auto parameters{rp.PopRaw<Parameters>()};
811 807
812 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 808 auto six_axis = GetResourceManager()->GetSixAxis();
813 const auto result = controller.EnableSixAxisSensorUnalteredPassthrough( 809 const auto result = six_axis->EnableSixAxisSensorUnalteredPassthrough(parameters.sixaxis_handle,
814 parameters.sixaxis_handle, parameters.enabled); 810 parameters.enabled);
815 811
816 LOG_DEBUG(Service_HID, 812 LOG_DEBUG(Service_HID,
817 "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, " 813 "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, "
@@ -836,8 +832,8 @@ void IHidServer::IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& c
836 const auto parameters{rp.PopRaw<Parameters>()}; 832 const auto parameters{rp.PopRaw<Parameters>()};
837 833
838 bool is_unaltered_sisxaxis_enabled{}; 834 bool is_unaltered_sisxaxis_enabled{};
839 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 835 auto six_axis = GetResourceManager()->GetSixAxis();
840 const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled( 836 const auto result = six_axis->IsSixAxisSensorUnalteredPassthroughEnabled(
841 parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled); 837 parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled);
842 838
843 LOG_DEBUG( 839 LOG_DEBUG(
@@ -863,9 +859,9 @@ void IHidServer::LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx) {
863 const auto parameters{rp.PopRaw<Parameters>()}; 859 const auto parameters{rp.PopRaw<Parameters>()};
864 860
865 Core::HID::SixAxisSensorCalibrationParameter calibration{}; 861 Core::HID::SixAxisSensorCalibrationParameter calibration{};
866 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 862 auto six_axis = GetResourceManager()->GetSixAxis();
867 const auto result = 863 const auto result =
868 controller.LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration); 864 six_axis->LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration);
869 865
870 LOG_WARNING( 866 LOG_WARNING(
871 Service_HID, 867 Service_HID,
@@ -893,9 +889,9 @@ void IHidServer::GetSixAxisSensorIcInformation(HLERequestContext& ctx) {
893 const auto parameters{rp.PopRaw<Parameters>()}; 889 const auto parameters{rp.PopRaw<Parameters>()};
894 890
895 Core::HID::SixAxisSensorIcInformation ic_information{}; 891 Core::HID::SixAxisSensorIcInformation ic_information{};
896 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 892 auto six_axis = GetResourceManager()->GetSixAxis();
897 const auto result = 893 const auto result =
898 controller.GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information); 894 six_axis->GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information);
899 895
900 LOG_WARNING( 896 LOG_WARNING(
901 Service_HID, 897 Service_HID,
@@ -922,9 +918,9 @@ void IHidServer::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx)
922 918
923 const auto parameters{rp.PopRaw<Parameters>()}; 919 const auto parameters{rp.PopRaw<Parameters>()};
924 920
925 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 921 auto controller = GetResourceManager()->GetNpad();
926 const auto result = 922 const auto result =
927 controller.ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle); 923 controller->ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle);
928 924
929 LOG_WARNING( 925 LOG_WARNING(
930 Service_HID, 926 Service_HID,
@@ -951,15 +947,15 @@ void IHidServer::ActivateGesture(HLERequestContext& ctx) {
951 parameters.basic_gesture_id, parameters.applet_resource_user_id); 947 parameters.basic_gesture_id, parameters.applet_resource_user_id);
952 948
953 Result result = ResultSuccess; 949 Result result = ResultSuccess;
954 auto& gesture = GetResourceManager()->GetController<Controller_Gesture>(HidController::Gesture); 950 auto gesture = GetResourceManager()->GetGesture();
955 951
956 if (!firmware_settings->IsDeviceManaged()) { 952 if (!firmware_settings->IsDeviceManaged()) {
957 result = gesture.Activate(); 953 result = gesture->Activate();
958 } 954 }
959 955
960 if (result.IsSuccess()) { 956 if (result.IsSuccess()) {
961 // TODO: Use gesture id here 957 // TODO: Use gesture id here
962 result = gesture.Activate(parameters.applet_resource_user_id); 958 result = gesture->Activate(parameters.applet_resource_user_id);
963 } 959 }
964 960
965 IPC::ResponseBuilder rb{ctx, 2}; 961 IPC::ResponseBuilder rb{ctx, 2};
@@ -977,9 +973,7 @@ void IHidServer::SetSupportedNpadStyleSet(HLERequestContext& ctx) {
977 973
978 const auto parameters{rp.PopRaw<Parameters>()}; 974 const auto parameters{rp.PopRaw<Parameters>()};
979 975
980 GetResourceManager() 976 GetResourceManager()->GetNpad()->SetSupportedStyleSet({parameters.supported_styleset});
981 ->GetController<Controller_NPad>(HidController::NPad)
982 .SetSupportedStyleSet({parameters.supported_styleset});
983 977
984 LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}", 978 LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}",
985 parameters.supported_styleset, parameters.applet_resource_user_id); 979 parameters.supported_styleset, parameters.applet_resource_user_id);
@@ -996,19 +990,14 @@ void IHidServer::GetSupportedNpadStyleSet(HLERequestContext& ctx) {
996 990
997 IPC::ResponseBuilder rb{ctx, 3}; 991 IPC::ResponseBuilder rb{ctx, 3};
998 rb.Push(ResultSuccess); 992 rb.Push(ResultSuccess);
999 rb.PushEnum(GetResourceManager() 993 rb.PushEnum(GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw);
1000 ->GetController<Controller_NPad>(HidController::NPad)
1001 .GetSupportedStyleSet()
1002 .raw);
1003} 994}
1004 995
1005void IHidServer::SetSupportedNpadIdType(HLERequestContext& ctx) { 996void IHidServer::SetSupportedNpadIdType(HLERequestContext& ctx) {
1006 IPC::RequestParser rp{ctx}; 997 IPC::RequestParser rp{ctx};
1007 const auto applet_resource_user_id{rp.Pop<u64>()}; 998 const auto applet_resource_user_id{rp.Pop<u64>()};
1008 999
1009 const auto result = GetResourceManager() 1000 const auto result = GetResourceManager()->GetNpad()->SetSupportedNpadIdTypes(ctx.ReadBuffer());
1010 ->GetController<Controller_NPad>(HidController::NPad)
1011 .SetSupportedNpadIdTypes(ctx.ReadBuffer());
1012 1001
1013 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1002 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1014 1003
@@ -1022,10 +1011,10 @@ void IHidServer::ActivateNpad(HLERequestContext& ctx) {
1022 1011
1023 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1012 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1024 1013
1025 auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1014 auto npad = GetResourceManager()->GetNpad();
1026 1015
1027 // TODO: npad->SetRevision(applet_resource_user_id, NpadRevision::Revision0); 1016 // TODO: npad->SetRevision(applet_resource_user_id, NpadRevision::Revision0);
1028 const Result result = npad.Activate(applet_resource_user_id); 1017 const Result result = npad->Activate(applet_resource_user_id);
1029 1018
1030 IPC::ResponseBuilder rb{ctx, 2}; 1019 IPC::ResponseBuilder rb{ctx, 2};
1031 rb.Push(result); 1020 rb.Push(result);
@@ -1059,15 +1048,12 @@ void IHidServer::AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx) {
1059 parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown); 1048 parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown);
1060 1049
1061 // Games expect this event to be signaled after calling this function 1050 // Games expect this event to be signaled after calling this function
1062 GetResourceManager() 1051 GetResourceManager()->GetNpad()->SignalStyleSetChangedEvent(parameters.npad_id);
1063 ->GetController<Controller_NPad>(HidController::NPad)
1064 .SignalStyleSetChangedEvent(parameters.npad_id);
1065 1052
1066 IPC::ResponseBuilder rb{ctx, 2, 1}; 1053 IPC::ResponseBuilder rb{ctx, 2, 1};
1067 rb.Push(ResultSuccess); 1054 rb.Push(ResultSuccess);
1068 rb.PushCopyObjects(GetResourceManager() 1055 rb.PushCopyObjects(
1069 ->GetController<Controller_NPad>(HidController::NPad) 1056 GetResourceManager()->GetNpad()->GetStyleSetChangedEvent(parameters.npad_id));
1070 .GetStyleSetChangedEvent(parameters.npad_id));
1071} 1057}
1072 1058
1073void IHidServer::DisconnectNpad(HLERequestContext& ctx) { 1059void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
@@ -1081,8 +1067,8 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
1081 1067
1082 const auto parameters{rp.PopRaw<Parameters>()}; 1068 const auto parameters{rp.PopRaw<Parameters>()};
1083 1069
1084 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1070 auto controller = GetResourceManager()->GetNpad();
1085 controller.DisconnectNpad(parameters.npad_id); 1071 controller->DisconnectNpad(parameters.npad_id);
1086 1072
1087 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1073 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1088 parameters.applet_resource_user_id); 1074 parameters.applet_resource_user_id);
@@ -1096,8 +1082,8 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
1096 const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()}; 1082 const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
1097 1083
1098 Core::HID::LedPattern pattern{0, 0, 0, 0}; 1084 Core::HID::LedPattern pattern{0, 0, 0, 0};
1099 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1085 auto controller = GetResourceManager()->GetNpad();
1100 const auto result = controller.GetLedPattern(npad_id, pattern); 1086 const auto result = controller->GetLedPattern(npad_id, pattern);
1101 1087
1102 LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); 1088 LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
1103 1089
@@ -1109,7 +1095,7 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
1109void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { 1095void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
1110 IPC::RequestParser rp{ctx}; 1096 IPC::RequestParser rp{ctx};
1111 struct Parameters { 1097 struct Parameters {
1112 Controller_NPad::NpadRevision revision; 1098 NPad::NpadRevision revision;
1113 INSERT_PADDING_WORDS_NOINIT(1); 1099 INSERT_PADDING_WORDS_NOINIT(1);
1114 u64 applet_resource_user_id; 1100 u64 applet_resource_user_id;
1115 }; 1101 };
@@ -1120,10 +1106,10 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
1120 LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision, 1106 LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision,
1121 parameters.applet_resource_user_id); 1107 parameters.applet_resource_user_id);
1122 1108
1123 auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1109 auto npad = GetResourceManager()->GetNpad();
1124 1110
1125 // TODO: npad->SetRevision(applet_resource_user_id, revision); 1111 // TODO: npad->SetRevision(applet_resource_user_id, revision);
1126 const auto result = npad.Activate(parameters.applet_resource_user_id); 1112 const auto result = npad->Activate(parameters.applet_resource_user_id);
1127 1113
1128 IPC::ResponseBuilder rb{ctx, 2}; 1114 IPC::ResponseBuilder rb{ctx, 2};
1129 rb.Push(result); 1115 rb.Push(result);
@@ -1132,11 +1118,9 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
1132void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) { 1118void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) {
1133 IPC::RequestParser rp{ctx}; 1119 IPC::RequestParser rp{ctx};
1134 const auto applet_resource_user_id{rp.Pop<u64>()}; 1120 const auto applet_resource_user_id{rp.Pop<u64>()};
1135 const auto hold_type{rp.PopEnum<Controller_NPad::NpadJoyHoldType>()}; 1121 const auto hold_type{rp.PopEnum<NPad::NpadJoyHoldType>()};
1136 1122
1137 GetResourceManager() 1123 GetResourceManager()->GetNpad()->SetHoldType(hold_type);
1138 ->GetController<Controller_NPad>(HidController::NPad)
1139 .SetHoldType(hold_type);
1140 1124
1141 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}", 1125 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}",
1142 applet_resource_user_id, hold_type); 1126 applet_resource_user_id, hold_type);
@@ -1153,8 +1137,7 @@ void IHidServer::GetNpadJoyHoldType(HLERequestContext& ctx) {
1153 1137
1154 IPC::ResponseBuilder rb{ctx, 4}; 1138 IPC::ResponseBuilder rb{ctx, 4};
1155 rb.Push(ResultSuccess); 1139 rb.Push(ResultSuccess);
1156 rb.PushEnum( 1140 rb.PushEnum(GetResourceManager()->GetNpad()->GetHoldType());
1157 GetResourceManager()->GetController<Controller_NPad>(HidController::NPad).GetHoldType());
1158} 1141}
1159 1142
1160void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) { 1143void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) {
@@ -1169,10 +1152,9 @@ void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx)
1169 const auto parameters{rp.PopRaw<Parameters>()}; 1152 const auto parameters{rp.PopRaw<Parameters>()};
1170 1153
1171 Core::HID::NpadIdType new_npad_id{}; 1154 Core::HID::NpadIdType new_npad_id{};
1172 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1155 auto controller = GetResourceManager()->GetNpad();
1173 controller.SetNpadMode(new_npad_id, parameters.npad_id, 1156 controller->SetNpadMode(new_npad_id, parameters.npad_id, NPad::NpadJoyDeviceType::Left,
1174 Controller_NPad::NpadJoyDeviceType::Left, 1157 NPad::NpadJoyAssignmentMode::Single);
1175 Controller_NPad::NpadJoyAssignmentMode::Single);
1176 1158
1177 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1159 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1178 parameters.applet_resource_user_id); 1160 parameters.applet_resource_user_id);
@@ -1187,16 +1169,16 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
1187 Core::HID::NpadIdType npad_id; 1169 Core::HID::NpadIdType npad_id;
1188 INSERT_PADDING_WORDS_NOINIT(1); 1170 INSERT_PADDING_WORDS_NOINIT(1);
1189 u64 applet_resource_user_id; 1171 u64 applet_resource_user_id;
1190 Controller_NPad::NpadJoyDeviceType npad_joy_device_type; 1172 NPad::NpadJoyDeviceType npad_joy_device_type;
1191 }; 1173 };
1192 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); 1174 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1193 1175
1194 const auto parameters{rp.PopRaw<Parameters>()}; 1176 const auto parameters{rp.PopRaw<Parameters>()};
1195 1177
1196 Core::HID::NpadIdType new_npad_id{}; 1178 Core::HID::NpadIdType new_npad_id{};
1197 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1179 auto controller = GetResourceManager()->GetNpad();
1198 controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, 1180 controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1199 Controller_NPad::NpadJoyAssignmentMode::Single); 1181 NPad::NpadJoyAssignmentMode::Single);
1200 1182
1201 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", 1183 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1202 parameters.npad_id, parameters.applet_resource_user_id, 1184 parameters.npad_id, parameters.applet_resource_user_id,
@@ -1218,9 +1200,8 @@ void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
1218 const auto parameters{rp.PopRaw<Parameters>()}; 1200 const auto parameters{rp.PopRaw<Parameters>()};
1219 1201
1220 Core::HID::NpadIdType new_npad_id{}; 1202 Core::HID::NpadIdType new_npad_id{};
1221 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1203 auto controller = GetResourceManager()->GetNpad();
1222 controller.SetNpadMode(new_npad_id, parameters.npad_id, {}, 1204 controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NPad::NpadJoyAssignmentMode::Dual);
1223 Controller_NPad::NpadJoyAssignmentMode::Dual);
1224 1205
1225 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1206 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1226 parameters.applet_resource_user_id); // Spams a lot when controller applet is open 1207 parameters.applet_resource_user_id); // Spams a lot when controller applet is open
@@ -1235,8 +1216,8 @@ void IHidServer::MergeSingleJoyAsDualJoy(HLERequestContext& ctx) {
1235 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; 1216 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
1236 const auto applet_resource_user_id{rp.Pop<u64>()}; 1217 const auto applet_resource_user_id{rp.Pop<u64>()};
1237 1218
1238 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1219 auto controller = GetResourceManager()->GetNpad();
1239 const auto result = controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); 1220 const auto result = controller->MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
1240 1221
1241 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", 1222 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
1242 npad_id_1, npad_id_2, applet_resource_user_id); 1223 npad_id_1, npad_id_2, applet_resource_user_id);
@@ -1249,9 +1230,7 @@ void IHidServer::StartLrAssignmentMode(HLERequestContext& ctx) {
1249 IPC::RequestParser rp{ctx}; 1230 IPC::RequestParser rp{ctx};
1250 const auto applet_resource_user_id{rp.Pop<u64>()}; 1231 const auto applet_resource_user_id{rp.Pop<u64>()};
1251 1232
1252 GetResourceManager() 1233 GetResourceManager()->GetNpad()->StartLRAssignmentMode();
1253 ->GetController<Controller_NPad>(HidController::NPad)
1254 .StartLRAssignmentMode();
1255 1234
1256 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1235 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1257 1236
@@ -1263,9 +1242,7 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
1263 IPC::RequestParser rp{ctx}; 1242 IPC::RequestParser rp{ctx};
1264 const auto applet_resource_user_id{rp.Pop<u64>()}; 1243 const auto applet_resource_user_id{rp.Pop<u64>()};
1265 1244
1266 GetResourceManager() 1245 GetResourceManager()->GetNpad()->StopLRAssignmentMode();
1267 ->GetController<Controller_NPad>(HidController::NPad)
1268 .StopLRAssignmentMode();
1269 1246
1270 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1247 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1271 1248
@@ -1276,11 +1253,9 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
1276void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) { 1253void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
1277 IPC::RequestParser rp{ctx}; 1254 IPC::RequestParser rp{ctx};
1278 const auto applet_resource_user_id{rp.Pop<u64>()}; 1255 const auto applet_resource_user_id{rp.Pop<u64>()};
1279 const auto activation_mode{rp.PopEnum<Controller_NPad::NpadHandheldActivationMode>()}; 1256 const auto activation_mode{rp.PopEnum<NPad::NpadHandheldActivationMode>()};
1280 1257
1281 GetResourceManager() 1258 GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode);
1282 ->GetController<Controller_NPad>(HidController::NPad)
1283 .SetNpadHandheldActivationMode(activation_mode);
1284 1259
1285 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}", 1260 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}",
1286 applet_resource_user_id, activation_mode); 1261 applet_resource_user_id, activation_mode);
@@ -1297,9 +1272,7 @@ void IHidServer::GetNpadHandheldActivationMode(HLERequestContext& ctx) {
1297 1272
1298 IPC::ResponseBuilder rb{ctx, 4}; 1273 IPC::ResponseBuilder rb{ctx, 4};
1299 rb.Push(ResultSuccess); 1274 rb.Push(ResultSuccess);
1300 rb.PushEnum(GetResourceManager() 1275 rb.PushEnum(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode());
1301 ->GetController<Controller_NPad>(HidController::NPad)
1302 .GetNpadHandheldActivationMode());
1303} 1276}
1304 1277
1305void IHidServer::SwapNpadAssignment(HLERequestContext& ctx) { 1278void IHidServer::SwapNpadAssignment(HLERequestContext& ctx) {
@@ -1308,8 +1281,8 @@ void IHidServer::SwapNpadAssignment(HLERequestContext& ctx) {
1308 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; 1281 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
1309 const auto applet_resource_user_id{rp.Pop<u64>()}; 1282 const auto applet_resource_user_id{rp.Pop<u64>()};
1310 1283
1311 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1284 auto controller = GetResourceManager()->GetNpad();
1312 const auto result = controller.SwapNpadAssignment(npad_id_1, npad_id_2); 1285 const auto result = controller->SwapNpadAssignment(npad_id_1, npad_id_2);
1313 1286
1314 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", 1287 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
1315 npad_id_1, npad_id_2, applet_resource_user_id); 1288 npad_id_1, npad_id_2, applet_resource_user_id);
@@ -1330,9 +1303,9 @@ void IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext&
1330 const auto parameters{rp.PopRaw<Parameters>()}; 1303 const auto parameters{rp.PopRaw<Parameters>()};
1331 1304
1332 bool is_enabled = false; 1305 bool is_enabled = false;
1333 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1306 auto controller = GetResourceManager()->GetNpad();
1334 const auto result = 1307 const auto result =
1335 controller.IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled); 1308 controller->IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled);
1336 1309
1337 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", 1310 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
1338 parameters.npad_id, parameters.applet_resource_user_id); 1311 parameters.npad_id, parameters.applet_resource_user_id);
@@ -1354,8 +1327,8 @@ void IHidServer::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ct
1354 1327
1355 const auto parameters{rp.PopRaw<Parameters>()}; 1328 const auto parameters{rp.PopRaw<Parameters>()};
1356 1329
1357 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1330 auto controller = GetResourceManager()->GetNpad();
1358 const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled( 1331 const auto result = controller->SetUnintendedHomeButtonInputProtectionEnabled(
1359 parameters.is_enabled, parameters.npad_id); 1332 parameters.is_enabled, parameters.npad_id);
1360 1333
1361 LOG_DEBUG(Service_HID, 1334 LOG_DEBUG(Service_HID,
@@ -1372,17 +1345,17 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
1372 Core::HID::NpadIdType npad_id; 1345 Core::HID::NpadIdType npad_id;
1373 INSERT_PADDING_WORDS_NOINIT(1); 1346 INSERT_PADDING_WORDS_NOINIT(1);
1374 u64 applet_resource_user_id; 1347 u64 applet_resource_user_id;
1375 Controller_NPad::NpadJoyDeviceType npad_joy_device_type; 1348 NPad::NpadJoyDeviceType npad_joy_device_type;
1376 }; 1349 };
1377 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); 1350 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1378 1351
1379 const auto parameters{rp.PopRaw<Parameters>()}; 1352 const auto parameters{rp.PopRaw<Parameters>()};
1380 1353
1381 Core::HID::NpadIdType new_npad_id{}; 1354 Core::HID::NpadIdType new_npad_id{};
1382 auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad); 1355 auto controller = GetResourceManager()->GetNpad();
1383 const auto is_reassigned = 1356 const auto is_reassigned =
1384 controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, 1357 controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1385 Controller_NPad::NpadJoyAssignmentMode::Single); 1358 NPad::NpadJoyAssignmentMode::Single);
1386 1359
1387 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", 1360 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1388 parameters.npad_id, parameters.applet_resource_user_id, 1361 parameters.npad_id, parameters.applet_resource_user_id,
@@ -1405,9 +1378,8 @@ void IHidServer::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) {
1405 1378
1406 const auto parameters{rp.PopRaw<Parameters>()}; 1379 const auto parameters{rp.PopRaw<Parameters>()};
1407 1380
1408 GetResourceManager() 1381 GetResourceManager()->GetNpad()->SetAnalogStickUseCenterClamp(
1409 ->GetController<Controller_NPad>(HidController::NPad) 1382 parameters.analog_stick_use_center_clamp);
1410 .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp);
1411 1383
1412 LOG_WARNING(Service_HID, 1384 LOG_WARNING(Service_HID,
1413 "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}", 1385 "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}",
@@ -1451,8 +1423,7 @@ void IHidServer::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) {
1451void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { 1423void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {
1452 IPC::RequestParser rp{ctx}; 1424 IPC::RequestParser rp{ctx};
1453 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; 1425 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
1454 const auto& controller = 1426 const auto controller = GetResourceManager()->GetNpad();
1455 GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
1456 1427
1457 Core::HID::VibrationDeviceInfo vibration_device_info; 1428 Core::HID::VibrationDeviceInfo vibration_device_info;
1458 bool check_device_index = false; 1429 bool check_device_index = false;
@@ -1496,7 +1467,7 @@ void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {
1496 LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", 1467 LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}",
1497 vibration_device_info.type, vibration_device_info.position); 1468 vibration_device_info.type, vibration_device_info.position);
1498 1469
1499 const auto result = controller.IsDeviceHandleValid(vibration_device_handle); 1470 const auto result = IsVibrationHandleValid(vibration_device_handle);
1500 if (result.IsError()) { 1471 if (result.IsError()) {
1501 IPC::ResponseBuilder rb{ctx, 2}; 1472 IPC::ResponseBuilder rb{ctx, 2};
1502 rb.Push(result); 1473 rb.Push(result);
@@ -1520,9 +1491,8 @@ void IHidServer::SendVibrationValue(HLERequestContext& ctx) {
1520 1491
1521 const auto parameters{rp.PopRaw<Parameters>()}; 1492 const auto parameters{rp.PopRaw<Parameters>()};
1522 1493
1523 GetResourceManager() 1494 GetResourceManager()->GetNpad()->VibrateController(parameters.vibration_device_handle,
1524 ->GetController<Controller_NPad>(HidController::NPad) 1495 parameters.vibration_value);
1525 .VibrateController(parameters.vibration_device_handle, parameters.vibration_value);
1526 1496
1527 LOG_DEBUG(Service_HID, 1497 LOG_DEBUG(Service_HID,
1528 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 1498 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -1553,9 +1523,8 @@ void IHidServer::GetActualVibrationValue(HLERequestContext& ctx) {
1553 1523
1554 IPC::ResponseBuilder rb{ctx, 6}; 1524 IPC::ResponseBuilder rb{ctx, 6};
1555 rb.Push(ResultSuccess); 1525 rb.Push(ResultSuccess);
1556 rb.PushRaw(GetResourceManager() 1526 rb.PushRaw(
1557 ->GetController<Controller_NPad>(HidController::NPad) 1527 GetResourceManager()->GetNpad()->GetLastVibration(parameters.vibration_device_handle));
1558 .GetLastVibration(parameters.vibration_device_handle));
1559} 1528}
1560 1529
1561void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) { 1530void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) {
@@ -1606,9 +1575,7 @@ void IHidServer::SendVibrationValues(HLERequestContext& ctx) {
1606 auto vibration_values = std::span( 1575 auto vibration_values = std::span(
1607 reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count); 1576 reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
1608 1577
1609 GetResourceManager() 1578 GetResourceManager()->GetNpad()->VibrateControllers(vibration_device_handles, vibration_values);
1610 ->GetController<Controller_NPad>(HidController::NPad)
1611 .VibrateControllers(vibration_device_handles, vibration_values);
1612 1579
1613 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1580 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1614 1581
@@ -1662,9 +1629,8 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) {
1662 } 1629 }
1663 }(); 1630 }();
1664 1631
1665 GetResourceManager() 1632 GetResourceManager()->GetNpad()->VibrateController(parameters.vibration_device_handle,
1666 ->GetController<Controller_NPad>(HidController::NPad) 1633 vibration_value);
1667 .VibrateController(parameters.vibration_device_handle, vibration_value);
1668 1634
1669 LOG_DEBUG(Service_HID, 1635 LOG_DEBUG(Service_HID,
1670 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " 1636 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, "
@@ -1688,9 +1654,8 @@ void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) {
1688 1654
1689 const auto parameters{rp.PopRaw<Parameters>()}; 1655 const auto parameters{rp.PopRaw<Parameters>()};
1690 1656
1691 const auto last_vibration = GetResourceManager() 1657 const auto last_vibration =
1692 ->GetController<Controller_NPad>(HidController::NPad) 1658 GetResourceManager()->GetNpad()->GetLastVibration(parameters.vibration_device_handle);
1693 .GetLastVibration(parameters.vibration_device_handle);
1694 1659
1695 const auto gc_erm_command = [last_vibration] { 1660 const auto gc_erm_command = [last_vibration] {
1696 if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) { 1661 if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
@@ -1725,9 +1690,7 @@ void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) {
1725 IPC::RequestParser rp{ctx}; 1690 IPC::RequestParser rp{ctx};
1726 const auto applet_resource_user_id{rp.Pop<u64>()}; 1691 const auto applet_resource_user_id{rp.Pop<u64>()};
1727 1692
1728 GetResourceManager() 1693 GetResourceManager()->GetNpad()->SetPermitVibrationSession(true);
1729 ->GetController<Controller_NPad>(HidController::NPad)
1730 .SetPermitVibrationSession(true);
1731 1694
1732 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1695 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1733 1696
@@ -1736,9 +1699,7 @@ void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) {
1736} 1699}
1737 1700
1738void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) { 1701void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) {
1739 GetResourceManager() 1702 GetResourceManager()->GetNpad()->SetPermitVibrationSession(false);
1740 ->GetController<Controller_NPad>(HidController::NPad)
1741 .SetPermitVibrationSession(false);
1742 1703
1743 LOG_DEBUG(Service_HID, "called"); 1704 LOG_DEBUG(Service_HID, "called");
1744 1705
@@ -1765,9 +1726,8 @@ void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) {
1765 1726
1766 IPC::ResponseBuilder rb{ctx, 3}; 1727 IPC::ResponseBuilder rb{ctx, 3};
1767 rb.Push(ResultSuccess); 1728 rb.Push(ResultSuccess);
1768 rb.Push(GetResourceManager() 1729 rb.Push(GetResourceManager()->GetNpad()->IsVibrationDeviceMounted(
1769 ->GetController<Controller_NPad>(HidController::NPad) 1730 parameters.vibration_device_handle));
1770 .IsVibrationDeviceMounted(parameters.vibration_device_handle));
1771} 1731}
1772 1732
1773void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { 1733void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {
@@ -1777,15 +1737,14 @@ void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {
1777 LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1737 LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1778 1738
1779 Result result = ResultSuccess; 1739 Result result = ResultSuccess;
1780 auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>( 1740 auto console_sixaxis = GetResourceManager()->GetConsoleSixAxis();
1781 HidController::ConsoleSixAxisSensor);
1782 1741
1783 if (!firmware_settings->IsDeviceManaged()) { 1742 if (!firmware_settings->IsDeviceManaged()) {
1784 result = console_sixaxis.Activate(); 1743 result = console_sixaxis->Activate();
1785 } 1744 }
1786 1745
1787 if (result.IsSuccess()) { 1746 if (result.IsSuccess()) {
1788 result = console_sixaxis.Activate(applet_resource_user_id); 1747 result = console_sixaxis->Activate(applet_resource_user_id);
1789 } 1748 }
1790 1749
1791 IPC::ResponseBuilder rb{ctx, 2}; 1750 IPC::ResponseBuilder rb{ctx, 2};
@@ -1839,15 +1798,14 @@ void IHidServer::ActivateSevenSixAxisSensor(HLERequestContext& ctx) {
1839 LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1798 LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1840 1799
1841 Result result = ResultSuccess; 1800 Result result = ResultSuccess;
1842 auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>( 1801 auto seven_sixaxis = GetResourceManager()->GetSevenSixAxis();
1843 HidController::ConsoleSixAxisSensor);
1844 1802
1845 if (!firmware_settings->IsDeviceManaged()) { 1803 if (!firmware_settings->IsDeviceManaged()) {
1846 result = console_sixaxis.Activate(); 1804 result = seven_sixaxis->Activate();
1847 } 1805 }
1848 1806
1849 if (result.IsSuccess()) { 1807 if (result.IsSuccess()) {
1850 console_sixaxis.Activate(applet_resource_user_id); 1808 seven_sixaxis->Activate(applet_resource_user_id);
1851 } 1809 }
1852 1810
1853 IPC::ResponseBuilder rb{ctx, 2}; 1811 IPC::ResponseBuilder rb{ctx, 2};
@@ -1911,13 +1869,10 @@ void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) {
1911 ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size"); 1869 ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size");
1912 1870
1913 // Activate console six axis controller 1871 // Activate console six axis controller
1914 GetResourceManager() 1872 GetResourceManager()->GetConsoleSixAxis()->Activate();
1915 ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) 1873 GetResourceManager()->GetSevenSixAxis()->Activate();
1916 .Activate();
1917 1874
1918 GetResourceManager() 1875 GetResourceManager()->GetSevenSixAxis()->SetTransferMemoryAddress(t_mem_1->GetSourceAddress());
1919 ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
1920 .SetTransferMemoryAddress(t_mem_1->GetSourceAddress());
1921 1876
1922 LOG_WARNING(Service_HID, 1877 LOG_WARNING(Service_HID,
1923 "called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, " 1878 "called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, "
@@ -1943,9 +1898,7 @@ void IHidServer::ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx) {
1943 IPC::RequestParser rp{ctx}; 1898 IPC::RequestParser rp{ctx};
1944 const auto applet_resource_user_id{rp.Pop<u64>()}; 1899 const auto applet_resource_user_id{rp.Pop<u64>()};
1945 1900
1946 GetResourceManager() 1901 GetResourceManager()->GetSevenSixAxis()->ResetTimestamp();
1947 ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
1948 .ResetTimestamp();
1949 1902
1950 LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1903 LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1951 1904
@@ -1977,9 +1930,9 @@ void IHidServer::GetPalmaConnectionHandle(HLERequestContext& ctx) {
1977 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", 1930 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
1978 parameters.npad_id, parameters.applet_resource_user_id); 1931 parameters.npad_id, parameters.applet_resource_user_id);
1979 1932
1980 Controller_Palma::PalmaConnectionHandle handle; 1933 Palma::PalmaConnectionHandle handle;
1981 auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma); 1934 auto controller = GetResourceManager()->GetPalma();
1982 const auto result = controller.GetPalmaConnectionHandle(parameters.npad_id, handle); 1935 const auto result = controller->GetPalmaConnectionHandle(parameters.npad_id, handle);
1983 1936
1984 IPC::ResponseBuilder rb{ctx, 4}; 1937 IPC::ResponseBuilder rb{ctx, 4};
1985 rb.Push(result); 1938 rb.Push(result);
@@ -1988,12 +1941,12 @@ void IHidServer::GetPalmaConnectionHandle(HLERequestContext& ctx) {
1988 1941
1989void IHidServer::InitializePalma(HLERequestContext& ctx) { 1942void IHidServer::InitializePalma(HLERequestContext& ctx) {
1990 IPC::RequestParser rp{ctx}; 1943 IPC::RequestParser rp{ctx};
1991 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 1944 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
1992 1945
1993 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 1946 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
1994 1947
1995 auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma); 1948 auto controller = GetResourceManager()->GetPalma();
1996 const auto result = controller.InitializePalma(connection_handle); 1949 const auto result = controller->InitializePalma(connection_handle);
1997 1950
1998 IPC::ResponseBuilder rb{ctx, 2}; 1951 IPC::ResponseBuilder rb{ctx, 2};
1999 rb.Push(result); 1952 rb.Push(result);
@@ -2001,27 +1954,27 @@ void IHidServer::InitializePalma(HLERequestContext& ctx) {
2001 1954
2002void IHidServer::AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx) { 1955void IHidServer::AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx) {
2003 IPC::RequestParser rp{ctx}; 1956 IPC::RequestParser rp{ctx};
2004 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 1957 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2005 1958
2006 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 1959 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2007 1960
2008 auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma); 1961 auto controller = GetResourceManager()->GetPalma();
2009 1962
2010 IPC::ResponseBuilder rb{ctx, 2, 1}; 1963 IPC::ResponseBuilder rb{ctx, 2, 1};
2011 rb.Push(ResultSuccess); 1964 rb.Push(ResultSuccess);
2012 rb.PushCopyObjects(controller.AcquirePalmaOperationCompleteEvent(connection_handle)); 1965 rb.PushCopyObjects(controller->AcquirePalmaOperationCompleteEvent(connection_handle));
2013} 1966}
2014 1967
2015void IHidServer::GetPalmaOperationInfo(HLERequestContext& ctx) { 1968void IHidServer::GetPalmaOperationInfo(HLERequestContext& ctx) {
2016 IPC::RequestParser rp{ctx}; 1969 IPC::RequestParser rp{ctx};
2017 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 1970 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2018 1971
2019 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 1972 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2020 1973
2021 Controller_Palma::PalmaOperationType operation_type; 1974 Palma::PalmaOperationType operation_type;
2022 Controller_Palma::PalmaOperationData data; 1975 Palma::PalmaOperationData data;
2023 auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma); 1976 auto controller = GetResourceManager()->GetPalma();
2024 const auto result = controller.GetPalmaOperationInfo(connection_handle, operation_type, data); 1977 const auto result = controller->GetPalmaOperationInfo(connection_handle, operation_type, data);
2025 1978
2026 if (result.IsError()) { 1979 if (result.IsError()) {
2027 IPC::ResponseBuilder rb{ctx, 2}; 1980 IPC::ResponseBuilder rb{ctx, 2};
@@ -2036,14 +1989,14 @@ void IHidServer::GetPalmaOperationInfo(HLERequestContext& ctx) {
2036 1989
2037void IHidServer::PlayPalmaActivity(HLERequestContext& ctx) { 1990void IHidServer::PlayPalmaActivity(HLERequestContext& ctx) {
2038 IPC::RequestParser rp{ctx}; 1991 IPC::RequestParser rp{ctx};
2039 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 1992 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2040 const auto palma_activity{rp.Pop<u64>()}; 1993 const auto palma_activity{rp.Pop<u64>()};
2041 1994
2042 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, palma_activity={}", 1995 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, palma_activity={}",
2043 connection_handle.npad_id, palma_activity); 1996 connection_handle.npad_id, palma_activity);
2044 1997
2045 auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma); 1998 auto controller = GetResourceManager()->GetPalma();
2046 const auto result = controller.PlayPalmaActivity(connection_handle, palma_activity); 1999 const auto result = controller->PlayPalmaActivity(connection_handle, palma_activity);
2047 2000
2048 IPC::ResponseBuilder rb{ctx, 2}; 2001 IPC::ResponseBuilder rb{ctx, 2};
2049 rb.Push(result); 2002 rb.Push(result);
@@ -2051,14 +2004,14 @@ void IHidServer::PlayPalmaActivity(HLERequestContext& ctx) {
2051 2004
2052void IHidServer::SetPalmaFrModeType(HLERequestContext& ctx) { 2005void IHidServer::SetPalmaFrModeType(HLERequestContext& ctx) {
2053 IPC::RequestParser rp{ctx}; 2006 IPC::RequestParser rp{ctx};
2054 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2007 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2055 const auto fr_mode{rp.PopEnum<Controller_Palma::PalmaFrModeType>()}; 2008 const auto fr_mode{rp.PopEnum<Palma::PalmaFrModeType>()};
2056 2009
2057 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, fr_mode={}", 2010 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, fr_mode={}",
2058 connection_handle.npad_id, fr_mode); 2011 connection_handle.npad_id, fr_mode);
2059 2012
2060 auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma); 2013 auto controller = GetResourceManager()->GetPalma();
2061 const auto result = controller.SetPalmaFrModeType(connection_handle, fr_mode); 2014 const auto result = controller->SetPalmaFrModeType(connection_handle, fr_mode);
2062 2015
2063 IPC::ResponseBuilder rb{ctx, 2}; 2016 IPC::ResponseBuilder rb{ctx, 2};
2064 rb.Push(result); 2017 rb.Push(result);
@@ -2066,12 +2019,12 @@ void IHidServer::SetPalmaFrModeType(HLERequestContext& ctx) {
2066 2019
2067void IHidServer::ReadPalmaStep(HLERequestContext& ctx) { 2020void IHidServer::ReadPalmaStep(HLERequestContext& ctx) {
2068 IPC::RequestParser rp{ctx}; 2021 IPC::RequestParser rp{ctx};
2069 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2022 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2070 2023
2071 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 2024 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2072 2025
2073 auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma); 2026 auto controller = GetResourceManager()->GetPalma();
2074 const auto result = controller.ReadPalmaStep(connection_handle); 2027 const auto result = controller->ReadPalmaStep(connection_handle);
2075 2028
2076 IPC::ResponseBuilder rb{ctx, 2}; 2029 IPC::ResponseBuilder rb{ctx, 2};
2077 rb.Push(result); 2030 rb.Push(result);
@@ -2082,7 +2035,7 @@ void IHidServer::EnablePalmaStep(HLERequestContext& ctx) {
2082 struct Parameters { 2035 struct Parameters {
2083 bool is_enabled; 2036 bool is_enabled;
2084 INSERT_PADDING_WORDS_NOINIT(1); 2037 INSERT_PADDING_WORDS_NOINIT(1);
2085 Controller_Palma::PalmaConnectionHandle connection_handle; 2038 Palma::PalmaConnectionHandle connection_handle;
2086 }; 2039 };
2087 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); 2040 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2088 2041
@@ -2091,9 +2044,9 @@ void IHidServer::EnablePalmaStep(HLERequestContext& ctx) {
2091 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, is_enabled={}", 2044 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, is_enabled={}",
2092 parameters.connection_handle.npad_id, parameters.is_enabled); 2045 parameters.connection_handle.npad_id, parameters.is_enabled);
2093 2046
2094 auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma); 2047 auto controller = GetResourceManager()->GetPalma();
2095 const auto result = 2048 const auto result =
2096 controller.EnablePalmaStep(parameters.connection_handle, parameters.is_enabled); 2049 controller->EnablePalmaStep(parameters.connection_handle, parameters.is_enabled);
2097 2050
2098 IPC::ResponseBuilder rb{ctx, 2}; 2051 IPC::ResponseBuilder rb{ctx, 2};
2099 rb.Push(result); 2052 rb.Push(result);
@@ -2101,12 +2054,12 @@ void IHidServer::EnablePalmaStep(HLERequestContext& ctx) {
2101 2054
2102void IHidServer::ResetPalmaStep(HLERequestContext& ctx) { 2055void IHidServer::ResetPalmaStep(HLERequestContext& ctx) {
2103 IPC::RequestParser rp{ctx}; 2056 IPC::RequestParser rp{ctx};
2104 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2057 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2105 2058
2106 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 2059 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2107 2060
2108 auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma); 2061 auto controller = GetResourceManager()->GetPalma();
2109 const auto result = controller.ResetPalmaStep(connection_handle); 2062 const auto result = controller->ResetPalmaStep(connection_handle);
2110 2063
2111 IPC::ResponseBuilder rb{ctx, 2}; 2064 IPC::ResponseBuilder rb{ctx, 2};
2112 rb.Push(result); 2065 rb.Push(result);
@@ -2128,13 +2081,11 @@ void IHidServer::WritePalmaApplicationSection(HLERequestContext& ctx) {
2128 2081
2129void IHidServer::ReadPalmaUniqueCode(HLERequestContext& ctx) { 2082void IHidServer::ReadPalmaUniqueCode(HLERequestContext& ctx) {
2130 IPC::RequestParser rp{ctx}; 2083 IPC::RequestParser rp{ctx};
2131 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2084 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2132 2085
2133 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 2086 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2134 2087
2135 GetResourceManager() 2088 GetResourceManager()->GetPalma()->ReadPalmaUniqueCode(connection_handle);
2136 ->GetController<Controller_Palma>(HidController::Palma)
2137 .ReadPalmaUniqueCode(connection_handle);
2138 2089
2139 IPC::ResponseBuilder rb{ctx, 2}; 2090 IPC::ResponseBuilder rb{ctx, 2};
2140 rb.Push(ResultSuccess); 2091 rb.Push(ResultSuccess);
@@ -2142,13 +2093,11 @@ void IHidServer::ReadPalmaUniqueCode(HLERequestContext& ctx) {
2142 2093
2143void IHidServer::SetPalmaUniqueCodeInvalid(HLERequestContext& ctx) { 2094void IHidServer::SetPalmaUniqueCodeInvalid(HLERequestContext& ctx) {
2144 IPC::RequestParser rp{ctx}; 2095 IPC::RequestParser rp{ctx};
2145 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2096 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2146 2097
2147 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 2098 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2148 2099
2149 GetResourceManager() 2100 GetResourceManager()->GetPalma()->SetPalmaUniqueCodeInvalid(connection_handle);
2150 ->GetController<Controller_Palma>(HidController::Palma)
2151 .SetPalmaUniqueCodeInvalid(connection_handle);
2152 2101
2153 IPC::ResponseBuilder rb{ctx, 2}; 2102 IPC::ResponseBuilder rb{ctx, 2};
2154 rb.Push(ResultSuccess); 2103 rb.Push(ResultSuccess);
@@ -2163,7 +2112,7 @@ void IHidServer::WritePalmaActivityEntry(HLERequestContext& ctx) {
2163 2112
2164void IHidServer::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) { 2113void IHidServer::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
2165 IPC::RequestParser rp{ctx}; 2114 IPC::RequestParser rp{ctx};
2166 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2115 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2167 const auto unknown{rp.Pop<u64>()}; 2116 const auto unknown{rp.Pop<u64>()};
2168 2117
2169 [[maybe_unused]] const auto buffer = ctx.ReadBuffer(); 2118 [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
@@ -2171,9 +2120,7 @@ void IHidServer::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
2171 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}", 2120 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}",
2172 connection_handle.npad_id, unknown); 2121 connection_handle.npad_id, unknown);
2173 2122
2174 GetResourceManager() 2123 GetResourceManager()->GetPalma()->WritePalmaRgbLedPatternEntry(connection_handle, unknown);
2175 ->GetController<Controller_Palma>(HidController::Palma)
2176 .WritePalmaRgbLedPatternEntry(connection_handle, unknown);
2177 2124
2178 IPC::ResponseBuilder rb{ctx, 2}; 2125 IPC::ResponseBuilder rb{ctx, 2};
2179 rb.Push(ResultSuccess); 2126 rb.Push(ResultSuccess);
@@ -2181,8 +2128,8 @@ void IHidServer::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
2181 2128
2182void IHidServer::WritePalmaWaveEntry(HLERequestContext& ctx) { 2129void IHidServer::WritePalmaWaveEntry(HLERequestContext& ctx) {
2183 IPC::RequestParser rp{ctx}; 2130 IPC::RequestParser rp{ctx};
2184 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2131 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2185 const auto wave_set{rp.PopEnum<Controller_Palma::PalmaWaveSet>()}; 2132 const auto wave_set{rp.PopEnum<Palma::PalmaWaveSet>()};
2186 const auto unknown{rp.Pop<u64>()}; 2133 const auto unknown{rp.Pop<u64>()};
2187 const auto t_mem_size{rp.Pop<u64>()}; 2134 const auto t_mem_size{rp.Pop<u64>()};
2188 const auto t_mem_handle{ctx.GetCopyHandle(0)}; 2135 const auto t_mem_handle{ctx.GetCopyHandle(0)};
@@ -2207,9 +2154,8 @@ void IHidServer::WritePalmaWaveEntry(HLERequestContext& ctx) {
2207 "t_mem_handle=0x{:08X}, t_mem_size={}, size={}", 2154 "t_mem_handle=0x{:08X}, t_mem_size={}, size={}",
2208 connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size); 2155 connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size);
2209 2156
2210 GetResourceManager() 2157 GetResourceManager()->GetPalma()->WritePalmaWaveEntry(connection_handle, wave_set,
2211 ->GetController<Controller_Palma>(HidController::Palma) 2158 t_mem->GetSourceAddress(), t_mem_size);
2212 .WritePalmaWaveEntry(connection_handle, wave_set, t_mem->GetSourceAddress(), t_mem_size);
2213 2159
2214 IPC::ResponseBuilder rb{ctx, 2}; 2160 IPC::ResponseBuilder rb{ctx, 2};
2215 rb.Push(ResultSuccess); 2161 rb.Push(ResultSuccess);
@@ -2220,7 +2166,7 @@ void IHidServer::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
2220 struct Parameters { 2166 struct Parameters {
2221 s32 database_id_version; 2167 s32 database_id_version;
2222 INSERT_PADDING_WORDS_NOINIT(1); 2168 INSERT_PADDING_WORDS_NOINIT(1);
2223 Controller_Palma::PalmaConnectionHandle connection_handle; 2169 Palma::PalmaConnectionHandle connection_handle;
2224 }; 2170 };
2225 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); 2171 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2226 2172
@@ -2229,10 +2175,8 @@ void IHidServer::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
2229 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, database_id_version={}", 2175 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, database_id_version={}",
2230 parameters.connection_handle.npad_id, parameters.database_id_version); 2176 parameters.connection_handle.npad_id, parameters.database_id_version);
2231 2177
2232 GetResourceManager() 2178 GetResourceManager()->GetPalma()->SetPalmaDataBaseIdentificationVersion(
2233 ->GetController<Controller_Palma>(HidController::Palma) 2179 parameters.connection_handle, parameters.database_id_version);
2234 .SetPalmaDataBaseIdentificationVersion(parameters.connection_handle,
2235 parameters.database_id_version);
2236 2180
2237 IPC::ResponseBuilder rb{ctx, 2}; 2181 IPC::ResponseBuilder rb{ctx, 2};
2238 rb.Push(ResultSuccess); 2182 rb.Push(ResultSuccess);
@@ -2240,13 +2184,11 @@ void IHidServer::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
2240 2184
2241void IHidServer::GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) { 2185void IHidServer::GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
2242 IPC::RequestParser rp{ctx}; 2186 IPC::RequestParser rp{ctx};
2243 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2187 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2244 2188
2245 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 2189 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2246 2190
2247 GetResourceManager() 2191 GetResourceManager()->GetPalma()->GetPalmaDataBaseIdentificationVersion(connection_handle);
2248 ->GetController<Controller_Palma>(HidController::Palma)
2249 .GetPalmaDataBaseIdentificationVersion(connection_handle);
2250 2192
2251 IPC::ResponseBuilder rb{ctx, 2}; 2193 IPC::ResponseBuilder rb{ctx, 2};
2252 rb.Push(ResultSuccess); 2194 rb.Push(ResultSuccess);
@@ -2261,13 +2203,12 @@ void IHidServer::SuspendPalmaFeature(HLERequestContext& ctx) {
2261 2203
2262void IHidServer::GetPalmaOperationResult(HLERequestContext& ctx) { 2204void IHidServer::GetPalmaOperationResult(HLERequestContext& ctx) {
2263 IPC::RequestParser rp{ctx}; 2205 IPC::RequestParser rp{ctx};
2264 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2206 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2265 2207
2266 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 2208 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2267 2209
2268 const auto result = GetResourceManager() 2210 const auto result =
2269 ->GetController<Controller_Palma>(HidController::Palma) 2211 GetResourceManager()->GetPalma()->GetPalmaOperationResult(connection_handle);
2270 .GetPalmaOperationResult(connection_handle);
2271 2212
2272 IPC::ResponseBuilder rb{ctx, 2}; 2213 IPC::ResponseBuilder rb{ctx, 2};
2273 rb.Push(result); 2214 rb.Push(result);
@@ -2302,9 +2243,7 @@ void IHidServer::SetIsPalmaAllConnectable(HLERequestContext& ctx) {
2302 "(STUBBED) called, is_palma_all_connectable={},applet_resource_user_id={}", 2243 "(STUBBED) called, is_palma_all_connectable={},applet_resource_user_id={}",
2303 parameters.is_palma_all_connectable, parameters.applet_resource_user_id); 2244 parameters.is_palma_all_connectable, parameters.applet_resource_user_id);
2304 2245
2305 GetResourceManager() 2246 GetResourceManager()->GetPalma()->SetIsPalmaAllConnectable(parameters.is_palma_all_connectable);
2306 ->GetController<Controller_Palma>(HidController::Palma)
2307 .SetIsPalmaAllConnectable(parameters.is_palma_all_connectable);
2308 2247
2309 IPC::ResponseBuilder rb{ctx, 2}; 2248 IPC::ResponseBuilder rb{ctx, 2};
2310 rb.Push(ResultSuccess); 2249 rb.Push(ResultSuccess);
@@ -2319,13 +2258,11 @@ void IHidServer::SetIsPalmaPairedConnectable(HLERequestContext& ctx) {
2319 2258
2320void IHidServer::PairPalma(HLERequestContext& ctx) { 2259void IHidServer::PairPalma(HLERequestContext& ctx) {
2321 IPC::RequestParser rp{ctx}; 2260 IPC::RequestParser rp{ctx};
2322 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; 2261 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2323 2262
2324 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id); 2263 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2325 2264
2326 GetResourceManager() 2265 GetResourceManager()->GetPalma()->PairPalma(connection_handle);
2327 ->GetController<Controller_Palma>(HidController::Palma)
2328 .PairPalma(connection_handle);
2329 2266
2330 IPC::ResponseBuilder rb{ctx, 2}; 2267 IPC::ResponseBuilder rb{ctx, 2};
2331 rb.Push(ResultSuccess); 2268 rb.Push(ResultSuccess);
@@ -2337,9 +2274,7 @@ void IHidServer::SetPalmaBoostMode(HLERequestContext& ctx) {
2337 2274
2338 LOG_WARNING(Service_HID, "(STUBBED) called, palma_boost_mode={}", palma_boost_mode); 2275 LOG_WARNING(Service_HID, "(STUBBED) called, palma_boost_mode={}", palma_boost_mode);
2339 2276
2340 GetResourceManager() 2277 GetResourceManager()->GetPalma()->SetPalmaBoostMode(palma_boost_mode);
2341 ->GetController<Controller_Palma>(HidController::Palma)
2342 .SetPalmaBoostMode(palma_boost_mode);
2343 2278
2344 IPC::ResponseBuilder rb{ctx, 2}; 2279 IPC::ResponseBuilder rb{ctx, 2};
2345 rb.Push(ResultSuccess); 2280 rb.Push(ResultSuccess);
@@ -2376,11 +2311,9 @@ void IHidServer::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
2376void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) { 2311void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) {
2377 IPC::RequestParser rp{ctx}; 2312 IPC::RequestParser rp{ctx};
2378 const auto applet_resource_user_id{rp.Pop<u64>()}; 2313 const auto applet_resource_user_id{rp.Pop<u64>()};
2379 const auto communication_mode{rp.PopEnum<Controller_NPad::NpadCommunicationMode>()}; 2314 const auto communication_mode{rp.PopEnum<NPad::NpadCommunicationMode>()};
2380 2315
2381 GetResourceManager() 2316 GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode);
2382 ->GetController<Controller_NPad>(HidController::NPad)
2383 .SetNpadCommunicationMode(communication_mode);
2384 2317
2385 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}", 2318 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}",
2386 applet_resource_user_id, communication_mode); 2319 applet_resource_user_id, communication_mode);
@@ -2396,9 +2329,7 @@ void IHidServer::GetNpadCommunicationMode(HLERequestContext& ctx) {
2396 2329
2397 IPC::ResponseBuilder rb{ctx, 4}; 2330 IPC::ResponseBuilder rb{ctx, 4};
2398 rb.Push(ResultSuccess); 2331 rb.Push(ResultSuccess);
2399 rb.PushEnum(GetResourceManager() 2332 rb.PushEnum(GetResourceManager()->GetNpad()->GetNpadCommunicationMode());
2400 ->GetController<Controller_NPad>(HidController::NPad)
2401 .GetNpadCommunicationMode());
2402} 2333}
2403 2334
2404void IHidServer::SetTouchScreenConfiguration(HLERequestContext& ctx) { 2335void IHidServer::SetTouchScreenConfiguration(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp
index 6f1902ee5..b56d0347a 100644
--- a/src/core/hle/service/hid/hid_system_server.cpp
+++ b/src/core/hle/service/hid/hid_system_server.cpp
@@ -16,206 +16,206 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
16 resource_manager{resource} { 16 resource_manager{resource} {
17 // clang-format off 17 // clang-format off
18 static const FunctionInfo functions[] = { 18 static const FunctionInfo functions[] = {
19 {31, nullptr, "SendKeyboardLockKeyEvent"}, 19 {31, nullptr, "SendKeyboardLockKeyEvent"},
20 {101, nullptr, "AcquireHomeButtonEventHandle"}, 20 {101, nullptr, "AcquireHomeButtonEventHandle"},
21 {111, nullptr, "ActivateHomeButton"}, 21 {111, nullptr, "ActivateHomeButton"},
22 {121, nullptr, "AcquireSleepButtonEventHandle"}, 22 {121, nullptr, "AcquireSleepButtonEventHandle"},
23 {131, nullptr, "ActivateSleepButton"}, 23 {131, nullptr, "ActivateSleepButton"},
24 {141, nullptr, "AcquireCaptureButtonEventHandle"}, 24 {141, nullptr, "AcquireCaptureButtonEventHandle"},
25 {151, nullptr, "ActivateCaptureButton"}, 25 {151, nullptr, "ActivateCaptureButton"},
26 {161, nullptr, "GetPlatformConfig"}, 26 {161, nullptr, "GetPlatformConfig"},
27 {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"}, 27 {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
28 {211, nullptr, "GetNpadsWithNfc"}, 28 {211, nullptr, "GetNpadsWithNfc"},
29 {212, nullptr, "AcquireNfcActivateEventHandle"}, 29 {212, nullptr, "AcquireNfcActivateEventHandle"},
30 {213, nullptr, "ActivateNfc"}, 30 {213, nullptr, "ActivateNfc"},
31 {214, nullptr, "GetXcdHandleForNpadWithNfc"}, 31 {214, nullptr, "GetXcdHandleForNpadWithNfc"},
32 {215, nullptr, "IsNfcActivated"}, 32 {215, nullptr, "IsNfcActivated"},
33 {230, nullptr, "AcquireIrSensorEventHandle"}, 33 {230, nullptr, "AcquireIrSensorEventHandle"},
34 {231, nullptr, "ActivateIrSensor"}, 34 {231, nullptr, "ActivateIrSensor"},
35 {232, nullptr, "GetIrSensorState"}, 35 {232, nullptr, "GetIrSensorState"},
36 {233, nullptr, "GetXcdHandleForNpadWithIrSensor"}, 36 {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
37 {301, nullptr, "ActivateNpadSystem"}, 37 {301, nullptr, "ActivateNpadSystem"},
38 {303, &IHidSystemServer::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"}, 38 {303, &IHidSystemServer::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
39 {304, &IHidSystemServer::EnableAssigningSingleOnSlSrPress, "EnableAssigningSingleOnSlSrPress"}, 39 {304, &IHidSystemServer::EnableAssigningSingleOnSlSrPress, "EnableAssigningSingleOnSlSrPress"},
40 {305, &IHidSystemServer::DisableAssigningSingleOnSlSrPress, "DisableAssigningSingleOnSlSrPress"}, 40 {305, &IHidSystemServer::DisableAssigningSingleOnSlSrPress, "DisableAssigningSingleOnSlSrPress"},
41 {306, &IHidSystemServer::GetLastActiveNpad, "GetLastActiveNpad"}, 41 {306, &IHidSystemServer::GetLastActiveNpad, "GetLastActiveNpad"},
42 {307, nullptr, "GetNpadSystemExtStyle"}, 42 {307, nullptr, "GetNpadSystemExtStyle"},
43 {308, &IHidSystemServer::ApplyNpadSystemCommonPolicyFull, "ApplyNpadSystemCommonPolicyFull"}, 43 {308, &IHidSystemServer::ApplyNpadSystemCommonPolicyFull, "ApplyNpadSystemCommonPolicyFull"},
44 {309, &IHidSystemServer::GetNpadFullKeyGripColor, "GetNpadFullKeyGripColor"}, 44 {309, &IHidSystemServer::GetNpadFullKeyGripColor, "GetNpadFullKeyGripColor"},
45 {310, &IHidSystemServer::GetMaskedSupportedNpadStyleSet, "GetMaskedSupportedNpadStyleSet"}, 45 {310, &IHidSystemServer::GetMaskedSupportedNpadStyleSet, "GetMaskedSupportedNpadStyleSet"},
46 {311, nullptr, "SetNpadPlayerLedBlinkingDevice"}, 46 {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
47 {312, &IHidSystemServer::SetSupportedNpadStyleSetAll, "SetSupportedNpadStyleSetAll"}, 47 {312, &IHidSystemServer::SetSupportedNpadStyleSetAll, "SetSupportedNpadStyleSetAll"},
48 {313, nullptr, "GetNpadCaptureButtonAssignment"}, 48 {313, nullptr, "GetNpadCaptureButtonAssignment"},
49 {314, nullptr, "GetAppletFooterUiType"}, 49 {314, nullptr, "GetAppletFooterUiType"},
50 {315, &IHidSystemServer::GetAppletDetailedUiType, "GetAppletDetailedUiType"}, 50 {315, &IHidSystemServer::GetAppletDetailedUiType, "GetAppletDetailedUiType"},
51 {316, &IHidSystemServer::GetNpadInterfaceType, "GetNpadInterfaceType"}, 51 {316, &IHidSystemServer::GetNpadInterfaceType, "GetNpadInterfaceType"},
52 {317, &IHidSystemServer::GetNpadLeftRightInterfaceType, "GetNpadLeftRightInterfaceType"}, 52 {317, &IHidSystemServer::GetNpadLeftRightInterfaceType, "GetNpadLeftRightInterfaceType"},
53 {318, &IHidSystemServer::HasBattery, "HasBattery"}, 53 {318, &IHidSystemServer::HasBattery, "HasBattery"},
54 {319, &IHidSystemServer::HasLeftRightBattery, "HasLeftRightBattery"}, 54 {319, &IHidSystemServer::HasLeftRightBattery, "HasLeftRightBattery"},
55 {321, &IHidSystemServer::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"}, 55 {321, &IHidSystemServer::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
56 {322, &IHidSystemServer::GetIrSensorState, "GetIrSensorState"}, 56 {322, &IHidSystemServer::GetIrSensorState, "GetIrSensorState"},
57 {323, nullptr, "GetXcdHandleForNpadWithIrSensor"}, 57 {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
58 {324, nullptr, "GetUniquePadButtonSet"}, 58 {324, nullptr, "GetUniquePadButtonSet"},
59 {325, nullptr, "GetUniquePadColor"}, 59 {325, nullptr, "GetUniquePadColor"},
60 {326, nullptr, "GetUniquePadAppletDetailedUiType"}, 60 {326, nullptr, "GetUniquePadAppletDetailedUiType"},
61 {327, nullptr, "GetAbstractedPadIdDataFromNpad"}, 61 {327, nullptr, "GetAbstractedPadIdDataFromNpad"},
62 {328, nullptr, "AttachAbstractedPadToNpad"}, 62 {328, nullptr, "AttachAbstractedPadToNpad"},
63 {329, nullptr, "DetachAbstractedPadAll"}, 63 {329, nullptr, "DetachAbstractedPadAll"},
64 {330, nullptr, "CheckAbstractedPadConnection"}, 64 {330, nullptr, "CheckAbstractedPadConnection"},
65 {500, nullptr, "SetAppletResourceUserId"}, 65 {500, nullptr, "SetAppletResourceUserId"},
66 {501, nullptr, "RegisterAppletResourceUserId"}, 66 {501, nullptr, "RegisterAppletResourceUserId"},
67 {502, nullptr, "UnregisterAppletResourceUserId"}, 67 {502, nullptr, "UnregisterAppletResourceUserId"},
68 {503, nullptr, "EnableAppletToGetInput"}, 68 {503, nullptr, "EnableAppletToGetInput"},
69 {504, nullptr, "SetAruidValidForVibration"}, 69 {504, nullptr, "SetAruidValidForVibration"},
70 {505, nullptr, "EnableAppletToGetSixAxisSensor"}, 70 {505, nullptr, "EnableAppletToGetSixAxisSensor"},
71 {506, nullptr, "EnableAppletToGetPadInput"}, 71 {506, nullptr, "EnableAppletToGetPadInput"},
72 {507, nullptr, "EnableAppletToGetTouchScreen"}, 72 {507, nullptr, "EnableAppletToGetTouchScreen"},
73 {510, nullptr, "SetVibrationMasterVolume"}, 73 {510, nullptr, "SetVibrationMasterVolume"},
74 {511, nullptr, "GetVibrationMasterVolume"}, 74 {511, nullptr, "GetVibrationMasterVolume"},
75 {512, nullptr, "BeginPermitVibrationSession"}, 75 {512, nullptr, "BeginPermitVibrationSession"},
76 {513, nullptr, "EndPermitVibrationSession"}, 76 {513, nullptr, "EndPermitVibrationSession"},
77 {514, nullptr, "Unknown514"}, 77 {514, nullptr, "Unknown514"},
78 {520, nullptr, "EnableHandheldHids"}, 78 {520, nullptr, "EnableHandheldHids"},
79 {521, nullptr, "DisableHandheldHids"}, 79 {521, nullptr, "DisableHandheldHids"},
80 {522, nullptr, "SetJoyConRailEnabled"}, 80 {522, nullptr, "SetJoyConRailEnabled"},
81 {523, nullptr, "IsJoyConRailEnabled"}, 81 {523, nullptr, "IsJoyConRailEnabled"},
82 {524, nullptr, "IsHandheldHidsEnabled"}, 82 {524, nullptr, "IsHandheldHidsEnabled"},
83 {525, nullptr, "IsJoyConAttachedOnAllRail"}, 83 {525, nullptr, "IsJoyConAttachedOnAllRail"},
84 {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"}, 84 {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
85 {541, nullptr, "GetPlayReportControllerUsages"}, 85 {541, nullptr, "GetPlayReportControllerUsages"},
86 {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"}, 86 {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
87 {543, nullptr, "GetRegisteredDevicesOld"}, 87 {543, nullptr, "GetRegisteredDevicesOld"},
88 {544, &IHidSystemServer::AcquireConnectionTriggerTimeoutEvent, "AcquireConnectionTriggerTimeoutEvent"}, 88 {544, &IHidSystemServer::AcquireConnectionTriggerTimeoutEvent, "AcquireConnectionTriggerTimeoutEvent"},
89 {545, nullptr, "SendConnectionTrigger"}, 89 {545, nullptr, "SendConnectionTrigger"},
90 {546, &IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport, "AcquireDeviceRegisteredEventForControllerSupport"}, 90 {546, &IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport, "AcquireDeviceRegisteredEventForControllerSupport"},
91 {547, nullptr, "GetAllowedBluetoothLinksCount"}, 91 {547, nullptr, "GetAllowedBluetoothLinksCount"},
92 {548, &IHidSystemServer::GetRegisteredDevices, "GetRegisteredDevices"}, 92 {548, &IHidSystemServer::GetRegisteredDevices, "GetRegisteredDevices"},
93 {549, nullptr, "GetConnectableRegisteredDevices"}, 93 {549, nullptr, "GetConnectableRegisteredDevices"},
94 {700, nullptr, "ActivateUniquePad"}, 94 {700, nullptr, "ActivateUniquePad"},
95 {702, &IHidSystemServer::AcquireUniquePadConnectionEventHandle, "AcquireUniquePadConnectionEventHandle"}, 95 {702, &IHidSystemServer::AcquireUniquePadConnectionEventHandle, "AcquireUniquePadConnectionEventHandle"},
96 {703, &IHidSystemServer::GetUniquePadIds, "GetUniquePadIds"}, 96 {703, &IHidSystemServer::GetUniquePadIds, "GetUniquePadIds"},
97 {751, &IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"}, 97 {751, &IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
98 {800, nullptr, "ListSixAxisSensorHandles"}, 98 {800, nullptr, "ListSixAxisSensorHandles"},
99 {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"}, 99 {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
100 {802, nullptr, "ResetSixAxisSensorCalibrationValues"}, 100 {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
101 {803, nullptr, "StartSixAxisSensorUserCalibration"}, 101 {803, nullptr, "StartSixAxisSensorUserCalibration"},
102 {804, nullptr, "CancelSixAxisSensorUserCalibration"}, 102 {804, nullptr, "CancelSixAxisSensorUserCalibration"},
103 {805, nullptr, "GetUniquePadBluetoothAddress"}, 103 {805, nullptr, "GetUniquePadBluetoothAddress"},
104 {806, nullptr, "DisconnectUniquePad"}, 104 {806, nullptr, "DisconnectUniquePad"},
105 {807, nullptr, "GetUniquePadType"}, 105 {807, nullptr, "GetUniquePadType"},
106 {808, nullptr, "GetUniquePadInterface"}, 106 {808, nullptr, "GetUniquePadInterface"},
107 {809, nullptr, "GetUniquePadSerialNumber"}, 107 {809, nullptr, "GetUniquePadSerialNumber"},
108 {810, nullptr, "GetUniquePadControllerNumber"}, 108 {810, nullptr, "GetUniquePadControllerNumber"},
109 {811, nullptr, "GetSixAxisSensorUserCalibrationStage"}, 109 {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
110 {812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"}, 110 {812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
111 {821, nullptr, "StartAnalogStickManualCalibration"}, 111 {821, nullptr, "StartAnalogStickManualCalibration"},
112 {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"}, 112 {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
113 {823, nullptr, "CancelAnalogStickManualCalibration"}, 113 {823, nullptr, "CancelAnalogStickManualCalibration"},
114 {824, nullptr, "ResetAnalogStickManualCalibration"}, 114 {824, nullptr, "ResetAnalogStickManualCalibration"},
115 {825, nullptr, "GetAnalogStickState"}, 115 {825, nullptr, "GetAnalogStickState"},
116 {826, nullptr, "GetAnalogStickManualCalibrationStage"}, 116 {826, nullptr, "GetAnalogStickManualCalibrationStage"},
117 {827, nullptr, "IsAnalogStickButtonPressed"}, 117 {827, nullptr, "IsAnalogStickButtonPressed"},
118 {828, nullptr, "IsAnalogStickInReleasePosition"}, 118 {828, nullptr, "IsAnalogStickInReleasePosition"},
119 {829, nullptr, "IsAnalogStickInCircumference"}, 119 {829, nullptr, "IsAnalogStickInCircumference"},
120 {830, nullptr, "SetNotificationLedPattern"}, 120 {830, nullptr, "SetNotificationLedPattern"},
121 {831, nullptr, "SetNotificationLedPatternWithTimeout"}, 121 {831, nullptr, "SetNotificationLedPatternWithTimeout"},
122 {832, nullptr, "PrepareHidsForNotificationWake"}, 122 {832, nullptr, "PrepareHidsForNotificationWake"},
123 {850, &IHidSystemServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"}, 123 {850, &IHidSystemServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
124 {851, nullptr, "EnableUsbFullKeyController"}, 124 {851, nullptr, "EnableUsbFullKeyController"},
125 {852, nullptr, "IsUsbConnected"}, 125 {852, nullptr, "IsUsbConnected"},
126 {870, &IHidSystemServer::IsHandheldButtonPressedOnConsoleMode, "IsHandheldButtonPressedOnConsoleMode"}, 126 {870, &IHidSystemServer::IsHandheldButtonPressedOnConsoleMode, "IsHandheldButtonPressedOnConsoleMode"},
127 {900, nullptr, "ActivateInputDetector"}, 127 {900, nullptr, "ActivateInputDetector"},
128 {901, nullptr, "NotifyInputDetector"}, 128 {901, nullptr, "NotifyInputDetector"},
129 {1000, &IHidSystemServer::InitializeFirmwareUpdate, "InitializeFirmwareUpdate"}, 129 {1000, &IHidSystemServer::InitializeFirmwareUpdate, "InitializeFirmwareUpdate"},
130 {1001, nullptr, "GetFirmwareVersion"}, 130 {1001, nullptr, "GetFirmwareVersion"},
131 {1002, nullptr, "GetAvailableFirmwareVersion"}, 131 {1002, nullptr, "GetAvailableFirmwareVersion"},
132 {1003, nullptr, "IsFirmwareUpdateAvailable"}, 132 {1003, nullptr, "IsFirmwareUpdateAvailable"},
133 {1004, nullptr, "CheckFirmwareUpdateRequired"}, 133 {1004, nullptr, "CheckFirmwareUpdateRequired"},
134 {1005, nullptr, "StartFirmwareUpdate"}, 134 {1005, nullptr, "StartFirmwareUpdate"},
135 {1006, nullptr, "AbortFirmwareUpdate"}, 135 {1006, nullptr, "AbortFirmwareUpdate"},
136 {1007, nullptr, "GetFirmwareUpdateState"}, 136 {1007, nullptr, "GetFirmwareUpdateState"},
137 {1008, nullptr, "ActivateAudioControl"}, 137 {1008, nullptr, "ActivateAudioControl"},
138 {1009, nullptr, "AcquireAudioControlEventHandle"}, 138 {1009, nullptr, "AcquireAudioControlEventHandle"},
139 {1010, nullptr, "GetAudioControlStates"}, 139 {1010, nullptr, "GetAudioControlStates"},
140 {1011, nullptr, "DeactivateAudioControl"}, 140 {1011, nullptr, "DeactivateAudioControl"},
141 {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"}, 141 {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
142 {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"}, 142 {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
143 {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"}, 143 {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
144 {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"}, 144 {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
145 {1100, nullptr, "GetHidbusSystemServiceObject"}, 145 {1100, nullptr, "GetHidbusSystemServiceObject"},
146 {1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"}, 146 {1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"},
147 {1130, nullptr, "InitializeUsbFirmwareUpdate"}, 147 {1130, nullptr, "InitializeUsbFirmwareUpdate"},
148 {1131, nullptr, "FinalizeUsbFirmwareUpdate"}, 148 {1131, nullptr, "FinalizeUsbFirmwareUpdate"},
149 {1132, nullptr, "CheckUsbFirmwareUpdateRequired"}, 149 {1132, nullptr, "CheckUsbFirmwareUpdateRequired"},
150 {1133, nullptr, "StartUsbFirmwareUpdate"}, 150 {1133, nullptr, "StartUsbFirmwareUpdate"},
151 {1134, nullptr, "GetUsbFirmwareUpdateState"}, 151 {1134, nullptr, "GetUsbFirmwareUpdateState"},
152 {1135, &IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory, "InitializeUsbFirmwareUpdateWithoutMemory"}, 152 {1135, &IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory, "InitializeUsbFirmwareUpdateWithoutMemory"},
153 {1150, nullptr, "SetTouchScreenMagnification"}, 153 {1150, nullptr, "SetTouchScreenMagnification"},
154 {1151, nullptr, "GetTouchScreenFirmwareVersion"}, 154 {1151, nullptr, "GetTouchScreenFirmwareVersion"},
155 {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, 155 {1152, nullptr, "SetTouchScreenDefaultConfiguration"},
156 {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, 156 {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
157 {1154, nullptr, "IsFirmwareAvailableForNotification"}, 157 {1154, nullptr, "IsFirmwareAvailableForNotification"},
158 {1155, nullptr, "SetForceHandheldStyleVibration"}, 158 {1155, nullptr, "SetForceHandheldStyleVibration"},
159 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, 159 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
160 {1157, nullptr, "CancelConnectionTrigger"}, 160 {1157, nullptr, "CancelConnectionTrigger"},
161 {1200, nullptr, "IsButtonConfigSupported"}, 161 {1200, nullptr, "IsButtonConfigSupported"},
162 {1201, nullptr, "IsButtonConfigEmbeddedSupported"}, 162 {1201, nullptr, "IsButtonConfigEmbeddedSupported"},
163 {1202, nullptr, "DeleteButtonConfig"}, 163 {1202, nullptr, "DeleteButtonConfig"},
164 {1203, nullptr, "DeleteButtonConfigEmbedded"}, 164 {1203, nullptr, "DeleteButtonConfigEmbedded"},
165 {1204, nullptr, "SetButtonConfigEnabled"}, 165 {1204, nullptr, "SetButtonConfigEnabled"},
166 {1205, nullptr, "SetButtonConfigEmbeddedEnabled"}, 166 {1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
167 {1206, nullptr, "IsButtonConfigEnabled"}, 167 {1206, nullptr, "IsButtonConfigEnabled"},
168 {1207, nullptr, "IsButtonConfigEmbeddedEnabled"}, 168 {1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
169 {1208, nullptr, "SetButtonConfigEmbedded"}, 169 {1208, nullptr, "SetButtonConfigEmbedded"},
170 {1209, nullptr, "SetButtonConfigFull"}, 170 {1209, nullptr, "SetButtonConfigFull"},
171 {1210, nullptr, "SetButtonConfigLeft"}, 171 {1210, nullptr, "SetButtonConfigLeft"},
172 {1211, nullptr, "SetButtonConfigRight"}, 172 {1211, nullptr, "SetButtonConfigRight"},
173 {1212, nullptr, "GetButtonConfigEmbedded"}, 173 {1212, nullptr, "GetButtonConfigEmbedded"},
174 {1213, nullptr, "GetButtonConfigFull"}, 174 {1213, nullptr, "GetButtonConfigFull"},
175 {1214, nullptr, "GetButtonConfigLeft"}, 175 {1214, nullptr, "GetButtonConfigLeft"},
176 {1215, nullptr, "GetButtonConfigRight"}, 176 {1215, nullptr, "GetButtonConfigRight"},
177 {1250, nullptr, "IsCustomButtonConfigSupported"}, 177 {1250, nullptr, "IsCustomButtonConfigSupported"},
178 {1251, nullptr, "IsDefaultButtonConfigEmbedded"}, 178 {1251, nullptr, "IsDefaultButtonConfigEmbedded"},
179 {1252, nullptr, "IsDefaultButtonConfigFull"}, 179 {1252, nullptr, "IsDefaultButtonConfigFull"},
180 {1253, nullptr, "IsDefaultButtonConfigLeft"}, 180 {1253, nullptr, "IsDefaultButtonConfigLeft"},
181 {1254, nullptr, "IsDefaultButtonConfigRight"}, 181 {1254, nullptr, "IsDefaultButtonConfigRight"},
182 {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"}, 182 {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
183 {1256, nullptr, "IsButtonConfigStorageFullEmpty"}, 183 {1256, nullptr, "IsButtonConfigStorageFullEmpty"},
184 {1257, nullptr, "IsButtonConfigStorageLeftEmpty"}, 184 {1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
185 {1258, nullptr, "IsButtonConfigStorageRightEmpty"}, 185 {1258, nullptr, "IsButtonConfigStorageRightEmpty"},
186 {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"}, 186 {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
187 {1260, nullptr, "GetButtonConfigStorageFullDeprecated"}, 187 {1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
188 {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"}, 188 {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
189 {1262, nullptr, "GetButtonConfigStorageRightDeprecated"}, 189 {1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
190 {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"}, 190 {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
191 {1264, nullptr, "SetButtonConfigStorageFullDeprecated"}, 191 {1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
192 {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"}, 192 {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
193 {1266, nullptr, "SetButtonConfigStorageRightDeprecated"}, 193 {1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
194 {1267, nullptr, "DeleteButtonConfigStorageEmbedded"}, 194 {1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
195 {1268, nullptr, "DeleteButtonConfigStorageFull"}, 195 {1268, nullptr, "DeleteButtonConfigStorageFull"},
196 {1269, nullptr, "DeleteButtonConfigStorageLeft"}, 196 {1269, nullptr, "DeleteButtonConfigStorageLeft"},
197 {1270, nullptr, "DeleteButtonConfigStorageRight"}, 197 {1270, nullptr, "DeleteButtonConfigStorageRight"},
198 {1271, nullptr, "IsUsingCustomButtonConfig"}, 198 {1271, nullptr, "IsUsingCustomButtonConfig"},
199 {1272, nullptr, "IsAnyCustomButtonConfigEnabled"}, 199 {1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
200 {1273, nullptr, "SetAllCustomButtonConfigEnabled"}, 200 {1273, nullptr, "SetAllCustomButtonConfigEnabled"},
201 {1274, nullptr, "SetDefaultButtonConfig"}, 201 {1274, nullptr, "SetDefaultButtonConfig"},
202 {1275, nullptr, "SetAllDefaultButtonConfig"}, 202 {1275, nullptr, "SetAllDefaultButtonConfig"},
203 {1276, nullptr, "SetHidButtonConfigEmbedded"}, 203 {1276, nullptr, "SetHidButtonConfigEmbedded"},
204 {1277, nullptr, "SetHidButtonConfigFull"}, 204 {1277, nullptr, "SetHidButtonConfigFull"},
205 {1278, nullptr, "SetHidButtonConfigLeft"}, 205 {1278, nullptr, "SetHidButtonConfigLeft"},
206 {1279, nullptr, "SetHidButtonConfigRight"}, 206 {1279, nullptr, "SetHidButtonConfigRight"},
207 {1280, nullptr, "GetHidButtonConfigEmbedded"}, 207 {1280, nullptr, "GetHidButtonConfigEmbedded"},
208 {1281, nullptr, "GetHidButtonConfigFull"}, 208 {1281, nullptr, "GetHidButtonConfigFull"},
209 {1282, nullptr, "GetHidButtonConfigLeft"}, 209 {1282, nullptr, "GetHidButtonConfigLeft"},
210 {1283, nullptr, "GetHidButtonConfigRight"}, 210 {1283, nullptr, "GetHidButtonConfigRight"},
211 {1284, nullptr, "GetButtonConfigStorageEmbedded"}, 211 {1284, nullptr, "GetButtonConfigStorageEmbedded"},
212 {1285, nullptr, "GetButtonConfigStorageFull"}, 212 {1285, nullptr, "GetButtonConfigStorageFull"},
213 {1286, nullptr, "GetButtonConfigStorageLeft"}, 213 {1286, nullptr, "GetButtonConfigStorageLeft"},
214 {1287, nullptr, "GetButtonConfigStorageRight"}, 214 {1287, nullptr, "GetButtonConfigStorageRight"},
215 {1288, nullptr, "SetButtonConfigStorageEmbedded"}, 215 {1288, nullptr, "SetButtonConfigStorageEmbedded"},
216 {1289, nullptr, "SetButtonConfigStorageFull"}, 216 {1289, nullptr, "SetButtonConfigStorageFull"},
217 {1290, nullptr, "DeleteButtonConfigStorageRight"}, 217 {1290, nullptr, "DeleteButtonConfigStorageRight"},
218 {1291, nullptr, "DeleteButtonConfigStorageRight"}, 218 {1291, nullptr, "DeleteButtonConfigStorageRight"},
219 }; 219 };
220 // clang-format on 220 // clang-format on
221 221
@@ -240,9 +240,7 @@ IHidSystemServer::~IHidSystemServer() {
240void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) { 240void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
241 LOG_WARNING(Service_HID, "called"); 241 LOG_WARNING(Service_HID, "called");
242 242
243 GetResourceManager() 243 GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy();
244 ->GetController<Controller_NPad>(HidController::NPad)
245 .ApplyNpadSystemCommonPolicy();
246 244
247 IPC::ResponseBuilder rb{ctx, 2}; 245 IPC::ResponseBuilder rb{ctx, 2};
248 rb.Push(ResultSuccess); 246 rb.Push(ResultSuccess);
@@ -273,9 +271,7 @@ void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) {
273void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) { 271void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) {
274 LOG_WARNING(Service_HID, "called"); 272 LOG_WARNING(Service_HID, "called");
275 273
276 GetResourceManager() 274 GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy();
277 ->GetController<Controller_NPad>(HidController::NPad)
278 .ApplyNpadSystemCommonPolicy();
279 275
280 IPC::ResponseBuilder rb{ctx, 2}; 276 IPC::ResponseBuilder rb{ctx, 2};
281 rb.Push(ResultSuccess); 277 rb.Push(ResultSuccess);
@@ -304,10 +300,7 @@ void IHidSystemServer::GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx) {
304 LOG_INFO(Service_HID, "(STUBBED) called"); 300 LOG_INFO(Service_HID, "(STUBBED) called");
305 301
306 Core::HID::NpadStyleSet supported_styleset = 302 Core::HID::NpadStyleSet supported_styleset =
307 GetResourceManager() 303 GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw;
308 ->GetController<Controller_NPad>(HidController::NPad)
309 .GetSupportedStyleSet()
310 .raw;
311 304
312 IPC::ResponseBuilder rb{ctx, 3}; 305 IPC::ResponseBuilder rb{ctx, 3};
313 rb.Push(ResultSuccess); 306 rb.Push(ResultSuccess);
@@ -320,10 +313,7 @@ void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) {
320 LOG_INFO(Service_HID, "(STUBBED) called"); 313 LOG_INFO(Service_HID, "(STUBBED) called");
321 314
322 Core::HID::NpadStyleSet supported_styleset = 315 Core::HID::NpadStyleSet supported_styleset =
323 GetResourceManager() 316 GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw;
324 ->GetController<Controller_NPad>(HidController::NPad)
325 .GetSupportedStyleSet()
326 .raw;
327 317
328 IPC::ResponseBuilder rb{ctx, 3}; 318 IPC::ResponseBuilder rb{ctx, 3};
329 rb.Push(ResultSuccess); 319 rb.Push(ResultSuccess);
@@ -337,10 +327,8 @@ void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) {
337 LOG_DEBUG(Service_HID, "called, npad_id_type={}", 327 LOG_DEBUG(Service_HID, "called, npad_id_type={}",
338 npad_id_type); // Spams a lot when controller applet is running 328 npad_id_type); // Spams a lot when controller applet is running
339 329
340 const Service::HID::Controller_NPad::AppletDetailedUiType detailed_ui_type = 330 const NPad::AppletDetailedUiType detailed_ui_type =
341 GetResourceManager() 331 GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type);
342 ->GetController<Controller_NPad>(HidController::NPad)
343 .GetAppletDetailedUiType(npad_id_type);
344 332
345 IPC::ResponseBuilder rb{ctx, 3}; 333 IPC::ResponseBuilder rb{ctx, 3};
346 rb.Push(ResultSuccess); 334 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/hid/hid_util.h b/src/core/hle/service/hid/hid_util.h
new file mode 100644
index 000000000..b87cc10e3
--- /dev/null
+++ b/src/core/hle/service/hid/hid_util.h
@@ -0,0 +1,146 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hid/hid_types.h"
7#include "core/hle/service/hid/errors.h"
8
9namespace Service::HID {
10
11constexpr bool IsNpadIdValid(const Core::HID::NpadIdType npad_id) {
12 switch (npad_id) {
13 case Core::HID::NpadIdType::Player1:
14 case Core::HID::NpadIdType::Player2:
15 case Core::HID::NpadIdType::Player3:
16 case Core::HID::NpadIdType::Player4:
17 case Core::HID::NpadIdType::Player5:
18 case Core::HID::NpadIdType::Player6:
19 case Core::HID::NpadIdType::Player7:
20 case Core::HID::NpadIdType::Player8:
21 case Core::HID::NpadIdType::Other:
22 case Core::HID::NpadIdType::Handheld:
23 return true;
24 default:
25 return false;
26 }
27}
28
29constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& handle) {
30 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id));
31 const bool device_index = handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
32
33 if (!npad_id) {
34 return InvalidNpadId;
35 }
36 if (!device_index) {
37 return NpadDeviceIndexOutOfRange;
38 }
39
40 return ResultSuccess;
41}
42
43constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) {
44 switch (handle.npad_type) {
45 case Core::HID::NpadStyleIndex::ProController:
46 case Core::HID::NpadStyleIndex::Handheld:
47 case Core::HID::NpadStyleIndex::JoyconDual:
48 case Core::HID::NpadStyleIndex::JoyconLeft:
49 case Core::HID::NpadStyleIndex::JoyconRight:
50 case Core::HID::NpadStyleIndex::GameCube:
51 case Core::HID::NpadStyleIndex::N64:
52 case Core::HID::NpadStyleIndex::SystemExt:
53 case Core::HID::NpadStyleIndex::System:
54 // These support vibration
55 break;
56 default:
57 return VibrationInvalidStyleIndex;
58 }
59
60 if (!IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id))) {
61 return VibrationInvalidNpadId;
62 }
63
64 if (handle.device_index >= Core::HID::DeviceIndex::MaxDeviceIndex) {
65 return VibrationDeviceIndexOutOfRange;
66 }
67
68 return ResultSuccess;
69}
70
71/// Converts a Core::HID::NpadIdType to an array index.
72constexpr size_t NpadIdTypeToIndex(Core::HID::NpadIdType npad_id_type) {
73 switch (npad_id_type) {
74 case Core::HID::NpadIdType::Player1:
75 return 0;
76 case Core::HID::NpadIdType::Player2:
77 return 1;
78 case Core::HID::NpadIdType::Player3:
79 return 2;
80 case Core::HID::NpadIdType::Player4:
81 return 3;
82 case Core::HID::NpadIdType::Player5:
83 return 4;
84 case Core::HID::NpadIdType::Player6:
85 return 5;
86 case Core::HID::NpadIdType::Player7:
87 return 6;
88 case Core::HID::NpadIdType::Player8:
89 return 7;
90 case Core::HID::NpadIdType::Handheld:
91 return 8;
92 case Core::HID::NpadIdType::Other:
93 return 9;
94 default:
95 return 8;
96 }
97}
98
99/// Converts an array index to a Core::HID::NpadIdType
100constexpr Core::HID::NpadIdType IndexToNpadIdType(size_t index) {
101 switch (index) {
102 case 0:
103 return Core::HID::NpadIdType::Player1;
104 case 1:
105 return Core::HID::NpadIdType::Player2;
106 case 2:
107 return Core::HID::NpadIdType::Player3;
108 case 3:
109 return Core::HID::NpadIdType::Player4;
110 case 4:
111 return Core::HID::NpadIdType::Player5;
112 case 5:
113 return Core::HID::NpadIdType::Player6;
114 case 6:
115 return Core::HID::NpadIdType::Player7;
116 case 7:
117 return Core::HID::NpadIdType::Player8;
118 case 8:
119 return Core::HID::NpadIdType::Handheld;
120 case 9:
121 return Core::HID::NpadIdType::Other;
122 default:
123 return Core::HID::NpadIdType::Invalid;
124 }
125}
126
127constexpr Core::HID::NpadStyleSet GetStylesetByIndex(std::size_t index) {
128 switch (index) {
129 case 0:
130 return Core::HID::NpadStyleSet::Fullkey;
131 case 1:
132 return Core::HID::NpadStyleSet::Handheld;
133 case 2:
134 return Core::HID::NpadStyleSet::JoyDual;
135 case 3:
136 return Core::HID::NpadStyleSet::JoyLeft;
137 case 4:
138 return Core::HID::NpadStyleSet::JoyRight;
139 case 5:
140 return Core::HID::NpadStyleSet::Palma;
141 default:
142 return Core::HID::NpadStyleSet::None;
143 }
144}
145
146} // namespace Service::HID
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
index d383a266d..39b9a4474 100644
--- a/src/core/hle/service/hid/irs.cpp
+++ b/src/core/hle/service/hid/irs.cpp
@@ -12,6 +12,7 @@
12#include "core/hle/kernel/k_transfer_memory.h" 12#include "core/hle/kernel/k_transfer_memory.h"
13#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
14#include "core/hle/service/hid/errors.h" 14#include "core/hle/service/hid/errors.h"
15#include "core/hle/service/hid/hid_util.h"
15#include "core/hle/service/hid/irs.h" 16#include "core/hle/service/hid/irs.h"
16#include "core/hle/service/hid/irsensor/clustering_processor.h" 17#include "core/hle/service/hid/irsensor/clustering_processor.h"
17#include "core/hle/service/hid/irsensor/image_transfer_processor.h" 18#include "core/hle/service/hid/irsensor/image_transfer_processor.h"
@@ -320,7 +321,7 @@ void IRS::GetNpadIrCameraHandle(HLERequestContext& ctx) {
320 } 321 }
321 322
322 Core::IrSensor::IrCameraHandle camera_handle{ 323 Core::IrSensor::IrCameraHandle camera_handle{
323 .npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)), 324 .npad_id = static_cast<u8>(HID::NpadIdTypeToIndex(npad_id)),
324 .npad_type = Core::HID::NpadStyleIndex::None, 325 .npad_type = Core::HID::NpadStyleIndex::None,
325 }; 326 };
326 327
@@ -545,7 +546,7 @@ void IRS::ActivateIrsensorWithFunctionLevel(HLERequestContext& ctx) {
545 546
546Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const { 547Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const {
547 if (camera_handle.npad_id > 548 if (camera_handle.npad_id >
548 static_cast<u8>(NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) { 549 static_cast<u8>(HID::NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) {
549 return InvalidIrCameraHandle; 550 return InvalidIrCameraHandle;
550 } 551 }
551 if (camera_handle.npad_type != Core::HID::NpadStyleIndex::None) { 552 if (camera_handle.npad_type != Core::HID::NpadStyleIndex::None) {
diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp
index d6f42c646..e76d4eea9 100644
--- a/src/core/hle/service/hid/resource_manager.cpp
+++ b/src/core/hle/service/hid/resource_manager.cpp
@@ -9,14 +9,15 @@
9#include "core/hle/service/hid/resource_manager.h" 9#include "core/hle/service/hid/resource_manager.h"
10#include "core/hle/service/ipc_helpers.h" 10#include "core/hle/service/ipc_helpers.h"
11 11
12#include "core/hle/service/hid/controllers/console_sixaxis.h" 12#include "core/hle/service/hid/controllers/console_six_axis.h"
13#include "core/hle/service/hid/controllers/controller_base.h"
14#include "core/hle/service/hid/controllers/debug_pad.h" 13#include "core/hle/service/hid/controllers/debug_pad.h"
15#include "core/hle/service/hid/controllers/gesture.h" 14#include "core/hle/service/hid/controllers/gesture.h"
16#include "core/hle/service/hid/controllers/keyboard.h" 15#include "core/hle/service/hid/controllers/keyboard.h"
17#include "core/hle/service/hid/controllers/mouse.h" 16#include "core/hle/service/hid/controllers/mouse.h"
18#include "core/hle/service/hid/controllers/npad.h" 17#include "core/hle/service/hid/controllers/npad.h"
19#include "core/hle/service/hid/controllers/palma.h" 18#include "core/hle/service/hid/controllers/palma.h"
19#include "core/hle/service/hid/controllers/seven_six_axis.h"
20#include "core/hle/service/hid/controllers/six_axis.h"
20#include "core/hle/service/hid/controllers/stubbed.h" 21#include "core/hle/service/hid/controllers/stubbed.h"
21#include "core/hle/service/hid/controllers/touchscreen.h" 22#include "core/hle/service/hid/controllers/touchscreen.h"
22#include "core/hle/service/hid/controllers/xpad.h" 23#include "core/hle/service/hid/controllers/xpad.h"
@@ -42,76 +43,132 @@ void ResourceManager::Initialize() {
42 } 43 }
43 44
44 u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer(); 45 u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
45 MakeController<Controller_DebugPad>(HidController::DebugPad, shared_memory); 46 debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory);
46 MakeController<Controller_Touchscreen>(HidController::Touchscreen, shared_memory); 47 mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory);
47 MakeController<Controller_Mouse>(HidController::Mouse, shared_memory); 48 debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory);
48 MakeController<Controller_Keyboard>(HidController::Keyboard, shared_memory); 49 keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory);
49 MakeController<Controller_XPad>(HidController::XPad, shared_memory); 50 unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory);
50 MakeController<Controller_Stubbed>(HidController::HomeButton, shared_memory); 51 npad = std::make_shared<NPad>(system.HIDCore(), shared_memory, service_context);
51 MakeController<Controller_Stubbed>(HidController::SleepButton, shared_memory); 52 gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory);
52 MakeController<Controller_Stubbed>(HidController::CaptureButton, shared_memory); 53 touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory);
53 MakeController<Controller_Stubbed>(HidController::InputDetector, shared_memory); 54 xpad = std::make_shared<XPad>(system.HIDCore(), shared_memory);
54 MakeController<Controller_Stubbed>(HidController::UniquePad, shared_memory); 55
55 MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory); 56 palma = std::make_shared<Palma>(system.HIDCore(), shared_memory, service_context);
56 MakeController<Controller_Gesture>(HidController::Gesture, shared_memory); 57
57 MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory); 58 home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory);
58 MakeController<Controller_Stubbed>(HidController::DebugMouse, shared_memory); 59 sleep_button = std::make_shared<SleepButton>(system.HIDCore(), shared_memory);
59 MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory); 60 capture_button = std::make_shared<CaptureButton>(system.HIDCore(), shared_memory);
61
62 six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
63 console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory);
64 seven_six_axis = std::make_shared<SevenSixAxis>(system);
65
66 home_button->SetCommonHeaderOffset(0x4C00);
67 sleep_button->SetCommonHeaderOffset(0x4E00);
68 capture_button->SetCommonHeaderOffset(0x5000);
69 unique_pad->SetCommonHeaderOffset(0x5A00);
70 debug_mouse->SetCommonHeaderOffset(0x3DC00);
60 71
61 // Homebrew doesn't try to activate some controllers, so we activate them by default 72 // Homebrew doesn't try to activate some controllers, so we activate them by default
62 GetController<Controller_NPad>(HidController::NPad).Activate(); 73 npad->Activate();
63 GetController<Controller_Touchscreen>(HidController::Touchscreen).Activate(); 74 six_axis->Activate();
64 75 touch_screen->Activate();
65 GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
66 GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
67 GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
68 GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
69 GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
70 GetController<Controller_Stubbed>(HidController::DebugMouse).SetCommonHeaderOffset(0x3DC00);
71 76
72 system.HIDCore().ReloadInputDevices(); 77 system.HIDCore().ReloadInputDevices();
73 is_initialized = true; 78 is_initialized = true;
74} 79}
80std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const {
81 return capture_button;
82}
83
84std::shared_ptr<ConsoleSixAxis> ResourceManager::GetConsoleSixAxis() const {
85 return console_six_axis;
86}
87
88std::shared_ptr<DebugMouse> ResourceManager::GetDebugMouse() const {
89 return debug_mouse;
90}
91
92std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
93 return debug_pad;
94}
95
96std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
97 return gesture;
98}
99
100std::shared_ptr<HomeButton> ResourceManager::GetHomeButton() const {
101 return home_button;
102}
103
104std::shared_ptr<Keyboard> ResourceManager::GetKeyboard() const {
105 return keyboard;
106}
107
108std::shared_ptr<Mouse> ResourceManager::GetMouse() const {
109 return mouse;
110}
111
112std::shared_ptr<NPad> ResourceManager::GetNpad() const {
113 return npad;
114}
115
116std::shared_ptr<Palma> ResourceManager::GetPalma() const {
117 return palma;
118}
119
120std::shared_ptr<SevenSixAxis> ResourceManager::GetSevenSixAxis() const {
121 return seven_six_axis;
122}
123
124std::shared_ptr<SixAxis> ResourceManager::GetSixAxis() const {
125 return six_axis;
126}
127
128std::shared_ptr<SleepButton> ResourceManager::GetSleepButton() const {
129 return sleep_button;
130}
131
132std::shared_ptr<TouchScreen> ResourceManager::GetTouchScreen() const {
133 return touch_screen;
134}
135
136std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const {
137 return unique_pad;
138}
75 139
76void ResourceManager::UpdateControllers(std::uintptr_t user_data, 140void ResourceManager::UpdateControllers(std::uintptr_t user_data,
77 std::chrono::nanoseconds ns_late) { 141 std::chrono::nanoseconds ns_late) {
78 auto& core_timing = system.CoreTiming(); 142 auto& core_timing = system.CoreTiming();
79 143 debug_pad->OnUpdate(core_timing);
80 for (const auto& controller : controllers) { 144 unique_pad->OnUpdate(core_timing);
81 // Keyboard has it's own update event 145 gesture->OnUpdate(core_timing);
82 if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) { 146 touch_screen->OnUpdate(core_timing);
83 continue; 147 palma->OnUpdate(core_timing);
84 } 148 home_button->OnUpdate(core_timing);
85 // Mouse has it's own update event 149 sleep_button->OnUpdate(core_timing);
86 if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) { 150 capture_button->OnUpdate(core_timing);
87 continue; 151 xpad->OnUpdate(core_timing);
88 }
89 // Npad has it's own update event
90 if (controller == controllers[static_cast<size_t>(HidController::NPad)]) {
91 continue;
92 }
93 controller->OnUpdate(core_timing);
94 }
95} 152}
96 153
97void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { 154void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
98 auto& core_timing = system.CoreTiming(); 155 auto& core_timing = system.CoreTiming();
99 156 npad->OnUpdate(core_timing);
100 controllers[static_cast<size_t>(HidController::NPad)]->OnUpdate(core_timing);
101} 157}
102 158
103void ResourceManager::UpdateMouseKeyboard(std::uintptr_t user_data, 159void ResourceManager::UpdateMouseKeyboard(std::uintptr_t user_data,
104 std::chrono::nanoseconds ns_late) { 160 std::chrono::nanoseconds ns_late) {
105 auto& core_timing = system.CoreTiming(); 161 auto& core_timing = system.CoreTiming();
106 162 mouse->OnUpdate(core_timing);
107 controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(core_timing); 163 debug_mouse->OnUpdate(core_timing);
108 controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(core_timing); 164 keyboard->OnUpdate(core_timing);
109} 165}
110 166
111void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { 167void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
112 auto& core_timing = system.CoreTiming(); 168 auto& core_timing = system.CoreTiming();
113 169 six_axis->OnUpdate(core_timing);
114 controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(core_timing); 170 seven_six_axis->OnUpdate(core_timing);
171 console_six_axis->OnUpdate(core_timing);
115} 172}
116 173
117IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource) 174IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource)
diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h
index 34dbf36bc..2b6a9b5e6 100644
--- a/src/core/hle/service/hid/resource_manager.h
+++ b/src/core/hle/service/hid/resource_manager.h
@@ -3,10 +3,6 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <chrono>
7
8#include "core/core.h"
9#include "core/hle/service/hid/controllers/controller_base.h"
10#include "core/hle/service/kernel_helpers.h" 6#include "core/hle/service/kernel_helpers.h"
11#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
12 8
@@ -14,74 +10,85 @@ namespace Core::Timing {
14struct EventType; 10struct EventType;
15} 11}
16 12
17namespace Core::HID {
18class HIDCore;
19}
20
21namespace Service::HID { 13namespace Service::HID {
14class Controller_Stubbed;
15class ConsoleSixAxis;
16class DebugPad;
17class Gesture;
18class Keyboard;
19class Mouse;
20class NPad;
21class Palma;
22class SevenSixAxis;
23class SixAxis;
24class TouchScreen;
25class XPad;
26
27using CaptureButton = Controller_Stubbed;
28using DebugMouse = Controller_Stubbed;
29using HomeButton = Controller_Stubbed;
30using SleepButton = Controller_Stubbed;
31using UniquePad = Controller_Stubbed;
22 32
23enum class HidController : std::size_t {
24 DebugPad,
25 Touchscreen,
26 Mouse,
27 Keyboard,
28 XPad,
29 HomeButton,
30 SleepButton,
31 CaptureButton,
32 InputDetector,
33 UniquePad,
34 NPad,
35 Gesture,
36 ConsoleSixAxisSensor,
37 DebugMouse,
38 Palma,
39
40 MaxControllers,
41};
42class ResourceManager { 33class ResourceManager {
34
43public: 35public:
44 explicit ResourceManager(Core::System& system_); 36 explicit ResourceManager(Core::System& system_);
45 ~ResourceManager(); 37 ~ResourceManager();
46 38
47 template <typename T>
48 T& GetController(HidController controller) {
49 return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
50 }
51
52 template <typename T>
53 const T& GetController(HidController controller) const {
54 return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
55 }
56
57 void Initialize(); 39 void Initialize();
58 40
41 std::shared_ptr<CaptureButton> GetCaptureButton() const;
42 std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const;
43 std::shared_ptr<DebugMouse> GetDebugMouse() const;
44 std::shared_ptr<DebugPad> GetDebugPad() const;
45 std::shared_ptr<Gesture> GetGesture() const;
46 std::shared_ptr<HomeButton> GetHomeButton() const;
47 std::shared_ptr<Keyboard> GetKeyboard() const;
48 std::shared_ptr<Mouse> GetMouse() const;
49 std::shared_ptr<NPad> GetNpad() const;
50 std::shared_ptr<Palma> GetPalma() const;
51 std::shared_ptr<SevenSixAxis> GetSevenSixAxis() const;
52 std::shared_ptr<SixAxis> GetSixAxis() const;
53 std::shared_ptr<SleepButton> GetSleepButton() const;
54 std::shared_ptr<TouchScreen> GetTouchScreen() const;
55 std::shared_ptr<UniquePad> GetUniquePad() const;
56
59 void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); 57 void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
60 void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); 58 void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
61 void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); 59 void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
62 void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); 60 void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
63 61
64private: 62private:
65 template <typename T>
66 void MakeController(HidController controller, u8* shared_memory) {
67 if constexpr (std::is_constructible_v<T, Core::System&, u8*>) {
68 controllers[static_cast<std::size_t>(controller)] =
69 std::make_unique<T>(system, shared_memory);
70 } else {
71 controllers[static_cast<std::size_t>(controller)] =
72 std::make_unique<T>(system.HIDCore(), shared_memory);
73 }
74 }
75
76 template <typename T>
77 void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
78 controllers[static_cast<std::size_t>(controller)] =
79 std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
80 }
81
82 bool is_initialized{false}; 63 bool is_initialized{false};
83 std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)> 64
84 controllers{}; 65 std::shared_ptr<CaptureButton> capture_button = nullptr;
66 std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr;
67 std::shared_ptr<DebugMouse> debug_mouse = nullptr;
68 std::shared_ptr<DebugPad> debug_pad = nullptr;
69 std::shared_ptr<Gesture> gesture = nullptr;
70 std::shared_ptr<HomeButton> home_button = nullptr;
71 std::shared_ptr<Keyboard> keyboard = nullptr;
72 std::shared_ptr<Mouse> mouse = nullptr;
73 std::shared_ptr<NPad> npad = nullptr;
74 std::shared_ptr<Palma> palma = nullptr;
75 std::shared_ptr<SevenSixAxis> seven_six_axis = nullptr;
76 std::shared_ptr<SixAxis> six_axis = nullptr;
77 std::shared_ptr<SleepButton> sleep_button = nullptr;
78 std::shared_ptr<TouchScreen> touch_screen = nullptr;
79 std::shared_ptr<UniquePad> unique_pad = nullptr;
80 std::shared_ptr<XPad> xpad = nullptr;
81
82 // TODO: Create these resources
83 // std::shared_ptr<AudioControl> audio_control = nullptr;
84 // std::shared_ptr<ButtonConfig> button_config = nullptr;
85 // std::shared_ptr<Config> config = nullptr;
86 // std::shared_ptr<Connection> connection = nullptr;
87 // std::shared_ptr<CustomConfig> custom_config = nullptr;
88 // std::shared_ptr<Digitizer> digitizer = nullptr;
89 // std::shared_ptr<Hdls> hdls = nullptr;
90 // std::shared_ptr<PlayReport> play_report = nullptr;
91 // std::shared_ptr<Rail> rail = nullptr;
85 92
86 Core::System& system; 93 Core::System& system;
87 KernelHelpers::ServiceContext service_context; 94 KernelHelpers::ServiceContext service_context;
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp
index a71d26157..ad534177d 100644
--- a/src/core/hle/service/nfc/common/device_manager.cpp
+++ b/src/core/hle/service/nfc/common/device_manager.cpp
@@ -7,6 +7,7 @@
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hid/hid_types.h" 8#include "core/hid/hid_types.h"
9#include "core/hle/kernel/k_event.h" 9#include "core/hle/kernel/k_event.h"
10#include "core/hle/service/hid/hid_util.h"
10#include "core/hle/service/ipc_helpers.h" 11#include "core/hle/service/ipc_helpers.h"
11#include "core/hle/service/nfc/common/device.h" 12#include "core/hle/service/nfc/common/device.h"
12#include "core/hle/service/nfc/common/device_manager.h" 13#include "core/hle/service/nfc/common/device_manager.h"
@@ -24,7 +25,7 @@ DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContex
24 25
25 for (u32 device_index = 0; device_index < devices.size(); device_index++) { 26 for (u32 device_index = 0; device_index < devices.size(); device_index++) {
26 devices[device_index] = 27 devices[device_index] =
27 std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system, 28 std::make_shared<NfcDevice>(HID::IndexToNpadIdType(device_index), system,
28 service_context, availability_change_event); 29 service_context, availability_change_event);
29 } 30 }
30 31
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index da140c01c..db30ba598 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -68,10 +68,7 @@ u64 StandardVmCallbacks::HidKeysDown() {
68 return 0; 68 return 0;
69 } 69 }
70 70
71 const auto press_state = 71 const auto press_state = applet_resource->GetNpad()->GetAndResetPressState();
72 applet_resource
73 ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)
74 .GetAndResetPressState();
75 return static_cast<u64>(press_state & HID::NpadButton::All); 72 return static_cast<u64>(press_state & HID::NpadButton::All);
76} 73}
77 74
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
4add_library(frontend_common STATIC
5 config.cpp
6 config.h
7)
8
9create_target_directory_groups(frontend_common)
10target_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
21namespace FS = Common::FS;
22
23Config::Config(const ConfigType config_type)
24 : type(config_type), global{config_type == ConfigType::GlobalConfig} {}
25
26void 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
51void 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
60void 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
81void 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
110bool Config::IsCustomConfig() const {
111 return type == ConfigType::PerGameConfig;
112}
113
114void 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
169void 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
180void 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
189void 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
216void 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
247void Config::ReadCoreValues() {
248 BeginGroup(Settings::TranslateCategory(Settings::Category::Core));
249
250 ReadCategory(Settings::Category::Core);
251
252 EndGroup();
253}
254
255void 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
269void 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
282void Config::ReadServiceValues() {
283 BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
284
285 ReadCategory(Settings::Category::Services);
286
287 EndGroup();
288}
289
290void 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
312void Config::ReadMiscellaneousValues() {
313 BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous));
314
315 ReadCategory(Settings::Category::Miscellaneous);
316
317 EndGroup();
318}
319
320void 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
330void 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
340void 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
350void 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
359void Config::ReadWebServiceValues() {
360 BeginGroup(Settings::TranslateCategory(Settings::Category::WebService));
361
362 ReadCategory(Settings::Category::WebService);
363
364 EndGroup();
365}
366
367void Config::ReadNetworkValues() {
368 BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
369
370 ReadCategory(Settings::Category::Network);
371
372 EndGroup();
373}
374
375void 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
393void 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
432void 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
445void 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
464void 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
483void 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
492void 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
511void Config::SaveCoreValues() {
512 BeginGroup(Settings::TranslateCategory(Settings::Category::Core));
513
514 WriteCategory(Settings::Category::Core);
515
516 EndGroup();
517}
518
519void 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
538void 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
550void Config::SaveNetworkValues() {
551 BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
552
553 WriteCategory(Settings::Category::Network);
554
555 EndGroup();
556}
557
558void 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
580void Config::SaveMiscellaneousValues() {
581 BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous));
582
583 WriteCategory(Settings::Category::Miscellaneous);
584
585 EndGroup();
586}
587
588void 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
598void 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
608void 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
618void 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
627void Config::SaveWebServiceValues() {
628 BeginGroup(Settings::TranslateCategory(Settings::Category::WebService));
629
630 WriteCategory(Settings::Category::WebService);
631
632 EndGroup();
633}
634
635bool 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
650s64 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
676u64 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
703double 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
721std::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
743bool 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
748template <typename Type>
749void 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
787void Config::WriteSettingInternal(const std::string& key, const std::string& value) {
788 config->SetValue(GetSection().c_str(), key.c_str(), value.c_str());
789}
790
791void Config::Reload() {
792 ReadValues();
793 // To apply default value changes
794 SaveValues();
795}
796
797void Config::Save() {
798 SaveValues();
799}
800
801void 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
813const std::string& Config::GetConfigFilePath() const {
814 return config_loc;
815}
816
817void 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
822void 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
827void 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
855void 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
877void 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
884void 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
894std::string Config::GetSection() {
895 if (key_stack.empty()) {
896 return std::string{""};
897 }
898
899 return key_stack.front();
900}
901
902std::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
914std::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
921std::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
945std::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
964int 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
972void 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
994void 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
21namespace Core {
22class System;
23}
24
25class Config {
26public:
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
41protected:
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
198private:
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/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h
index 78b42b518..efa9adf7a 100644
--- a/src/video_core/query_cache/query_cache.h
+++ b/src/video_core/query_cache/query_cache.h
@@ -266,7 +266,7 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
266 return; 266 return;
267 } 267 }
268 if (False(query_base->flags & QueryFlagBits::IsFinalValueSynced)) [[unlikely]] { 268 if (False(query_base->flags & QueryFlagBits::IsFinalValueSynced)) [[unlikely]] {
269 UNREACHABLE(); 269 ASSERT(false);
270 return; 270 return;
271 } 271 }
272 query_base->value += streamer->GetAmmendValue(); 272 query_base->value += streamer->GetAmmendValue();
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index de34f6d49..5dbec2e62 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1785,8 +1785,22 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
1785 : VideoCommon::ImageViewBase{info, view_info, gpu_addr_}, 1785 : VideoCommon::ImageViewBase{info, view_info, gpu_addr_},
1786 buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {} 1786 buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {}
1787 1787
1788ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams& params) 1788ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageViewParams& params)
1789 : VideoCommon::ImageViewBase{params} {} 1789 : VideoCommon::ImageViewBase{params}, device{&runtime.device} {
1790 if (device->HasNullDescriptor()) {
1791 return;
1792 }
1793
1794 // Handle fallback for devices without nullDescriptor
1795 ImageInfo info{};
1796 info.format = PixelFormat::A8B8G8R8_UNORM;
1797
1798 null_image = MakeImage(*device, runtime.memory_allocator, info, {});
1799 image_handle = *null_image;
1800 for (u32 i = 0; i < Shader::NUM_TEXTURE_TYPES; i++) {
1801 image_views[i] = MakeView(VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_IMAGE_ASPECT_COLOR_BIT);
1802 }
1803}
1790 1804
1791ImageView::~ImageView() = default; 1805ImageView::~ImageView() = default;
1792 1806
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 7a0807709..edf5d7635 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -267,6 +267,7 @@ private:
267 vk::ImageView depth_view; 267 vk::ImageView depth_view;
268 vk::ImageView stencil_view; 268 vk::ImageView stencil_view;
269 vk::ImageView color_view; 269 vk::ImageView color_view;
270 vk::Image null_image;
270 VkImage image_handle = VK_NULL_HANDLE; 271 VkImage image_handle = VK_NULL_HANDLE;
271 VkImageView render_target = VK_NULL_HANDLE; 272 VkImageView render_target = VK_NULL_HANDLE;
272 VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; 273 VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
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
378create_target_directory_groups(yuzu) 378create_target_directory_groups(yuzu)
379 379
380target_link_libraries(yuzu PRIVATE common core input_common network video_core) 380target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core)
381target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets) 381target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets)
382target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) 382target_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
20namespace FS = Common::FS;
21
22Config::Config(const std::string& config_name, ConfigType config_type)
23 : type(config_type), global{config_type == ConfigType::GlobalConfig} {
24 Initialize(config_name);
25}
26
27Config::~Config() {
28 if (global) {
29 Save();
30 }
31}
32
33const 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
41const std::array<int, Settings::NativeMotion::NumMotions> Config::default_motions = {
42 Qt::Key_7,
43 Qt::Key_8,
44};
45
46const 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
61const std::array<int, 2> Config::default_stick_mod = {
62 Qt::Key_Shift,
63 0,
64};
65
66const std::array<int, 2> Config::default_ringcon_analogs{{
67 Qt::Key_A,
68 Qt::Key_D,
69}};
70
71const 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
77const 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
90const 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
95const 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
101const 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
107const 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
118const 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
145void 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
174bool Config::IsCustomConfig() {
175 return type == ConfigType::PerGameConfig;
176}
177
178void 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
300void 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
334void 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
346void 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
360void 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
369void 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
398void 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
435void Config::ReadCoreValues() {
436 qt_config->beginGroup(QStringLiteral("Core"));
437
438 ReadCategory(Settings::Category::Core);
439
440 qt_config->endGroup();
441}
442
443void 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
486void 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
499void Config::ReadServiceValues() {
500 qt_config->beginGroup(QStringLiteral("Services"));
501
502 ReadCategory(Settings::Category::Services);
503
504 qt_config->endGroup();
505}
506
507void 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
526void Config::ReadMiscellaneousValues() {
527 qt_config->beginGroup(QStringLiteral("Miscellaneous"));
528
529 ReadCategory(Settings::Category::Miscellaneous);
530
531 qt_config->endGroup();
532}
533
534void 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
576void 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
586void 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
596void 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
611void 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
634void 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
643void 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
665void 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
681void 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
698void Config::ReadWebServiceValues() {
699 qt_config->beginGroup(QStringLiteral("WebService"));
700
701 ReadCategory(Settings::Category::WebService);
702
703 qt_config->endGroup();
704}
705
706void 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
732void Config::ReadNetworkValues() {
733 qt_config->beginGroup(QString::fromStdString("Services"));
734
735 ReadCategory(Settings::Category::Network);
736
737 qt_config->endGroup();
738}
739
740void 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
759void 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
824void 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
843void 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
853void 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
873void 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
881void 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
901void 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
910void 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
931void Config::SaveCoreValues() {
932 qt_config->beginGroup(QStringLiteral("Core"));
933
934 WriteCategory(Settings::Category::Core);
935
936 qt_config->endGroup();
937}
938
939void 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
963void 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
975void Config::SaveNetworkValues() {
976 qt_config->beginGroup(QStringLiteral("Services"));
977
978 WriteCategory(Settings::Category::Network);
979
980 qt_config->endGroup();
981}
982
983void 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
1002void Config::SaveMiscellaneousValues() {
1003 qt_config->beginGroup(QStringLiteral("Miscellaneous"));
1004
1005 WriteCategory(Settings::Category::Miscellaneous);
1006
1007 qt_config->endGroup();
1008}
1009
1010void 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
1030void 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
1040void 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
1050void 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
1060void 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
1083void 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
1092void 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
1111void 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
1127void 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
1142void Config::SaveWebServiceValues() {
1143 qt_config->beginGroup(QStringLiteral("WebService"));
1144
1145 WriteCategory(Settings::Category::WebService);
1146
1147 qt_config->endGroup();
1148}
1149
1150void 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
1174QVariant Config::ReadSetting(const QString& name) const {
1175 return qt_config->value(name);
1176}
1177
1178QVariant 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
1188void Config::WriteSetting(const QString& name, const QVariant& value) {
1189 qt_config->setValue(name, value);
1190}
1191
1192void 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
1198void 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
1209void Config::Reload() {
1210 ReadValues();
1211 // To apply default value changes
1212 SaveValues();
1213}
1214
1215void Config::Save() {
1216 SaveValues();
1217}
1218
1219void Config::ReadControlPlayerValue(std::size_t player_index) {
1220 qt_config->beginGroup(QStringLiteral("Controls"));
1221 ReadPlayerValue(player_index);
1222 qt_config->endGroup();
1223}
1224
1225void Config::SaveControlPlayerValue(std::size_t player_index) {
1226 qt_config->beginGroup(QStringLiteral("Controls"));
1227 SavePlayerValue(player_index);
1228 qt_config->endGroup();
1229}
1230
1231void 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
1238const std::string& Config::GetConfigFilePath() const {
1239 return qt_config_loc;
1240}
1241
1242static 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
1250void 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
1256void 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
1262void 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
1289void 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
15class QSettings;
16
17namespace Core {
18class System;
19}
20
21class Config {
22public:
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
68private:
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
169Q_DECLARE_METATYPE(Settings::CpuAccuracy);
170Q_DECLARE_METATYPE(Settings::GpuAccuracy);
171Q_DECLARE_METATYPE(Settings::FullscreenMode);
172Q_DECLARE_METATYPE(Settings::NvdecEmulation);
173Q_DECLARE_METATYPE(Settings::ResolutionSetup);
174Q_DECLARE_METATYPE(Settings::ScalingFilter);
175Q_DECLARE_METATYPE(Settings::AntiAliasing);
176Q_DECLARE_METATYPE(Settings::RendererBackend);
177Q_DECLARE_METATYPE(Settings::ShaderBackend);
178Q_DECLARE_METATYPE(Settings::AstcRecompression);
179Q_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
19ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_) 19ConfigureCamera::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
18constexpr int name_column = 0; 19constexpr int name_column = 0;
@@ -62,18 +63,21 @@ ConfigureHotkeys::~ConfigureHotkeys() = default;
62 63
63void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { 64void 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) {
319void ConfigureHotkeys::RestoreDefaults() { 323void 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
380void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) { 385void 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
394void ConfigureHotkeys::RestoreHotkey(QModelIndex index) { 399void 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
13ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, Config* config_, 13ConfigureInputPerGame::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
13class QComboBox; 14class QComboBox;
14 15
@@ -22,7 +23,7 @@ class ConfigureInputPerGame : public QWidget {
22 Q_OBJECT 23 Q_OBJECT
23 24
24public: 25public:
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
114void ConfigurePerGame::changeEvent(QEvent* event) { 113void 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
20namespace Core { 21namespace 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
21const std::array<std::string, ConfigureRingController::ANALOG_SUB_BUTTONS_NUM> 21const std::array<std::string, ConfigureRingController::ANALOG_SUB_BUTTONS_NUM>
@@ -270,7 +270,7 @@ void ConfigureRingController::LoadConfiguration() {
270 270
271void ConfigureRingController::RestoreDefaults() { 271void 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
9ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent) 9ConfigureTouchscreenAdvanced::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
165void ConfigureUi::ApplyConfiguration() { 165void 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
193void ConfigureUi::SetConfiguration() { 193void 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
11namespace FS = Common::FS; 11namespace 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
9namespace Core { 11namespace Core {
10class System; 12class System;
11} 13}
@@ -30,5 +32,5 @@ public:
30private: 32private:
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
8const 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
16const std::array<int, Settings::NativeMotion::NumMotions> QtConfig::default_motions = {
17 Qt::Key_7,
18 Qt::Key_8,
19};
20
21const 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
36const std::array<int, 2> QtConfig::default_stick_mod = {
37 Qt::Key_Shift,
38 0,
39};
40
41const std::array<int, 2> QtConfig::default_ringcon_analogs{{
42 Qt::Key_A,
43 Qt::Key_D,
44}};
45
46QtConfig::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
55QtConfig::~QtConfig() {
56 if (global) {
57 QtConfig::SaveAllValues();
58 }
59}
60
61void QtConfig::ReloadAllValues() {
62 Reload();
63 ReadQtValues();
64 SaveQtValues();
65}
66
67void QtConfig::SaveAllValues() {
68 Save();
69 SaveQtValues();
70}
71
72void QtConfig::ReadQtValues() {
73 if (global) {
74 ReadUIValues();
75 }
76 ReadQtControlValues();
77}
78
79void 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
132void 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
143void 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
169void 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
186void 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
233void 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
258void 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
278void 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
294void QtConfig::ReadUILayoutValues() {
295 BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
296
297 ReadCategory(Settings::Category::UiLayout);
298
299 EndGroup();
300}
301
302void 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
328void QtConfig::SaveQtValues() {
329 if (global) {
330 SaveUIValues();
331 }
332 SaveQtControlValues();
333
334 WriteToIni();
335}
336
337void 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
368void 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
383void 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
390void 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
407void 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
429void 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
457void 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
477void 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
492void QtConfig::SaveUILayoutValues() {
493 BeginGroup(Settings::TranslateCategory(Settings::Category::UiLayout));
494
495 WriteCategory(Settings::Category::UiLayout);
496
497 EndGroup();
498}
499
500void 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
523std::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
531void 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
540void 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
10class QtConfig final : public Config {
11public:
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
22protected:
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
49public:
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
14class QWidget; 15class QWidget;
15 16
@@ -22,4 +23,46 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent);
22 23
23std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent); 24std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent);
24 25
26static 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
32static 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
45static 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
50static 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
56static 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
62static 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
37bool IsDarkTheme() { 37bool 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
871void GameList::RefreshGameDirectory() { 872void 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
54QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) { 54QShortcut* 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
65ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, const QString& action, 66ControllerShortcut* 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
77QKeySequence HotkeyRegistry::GetKeySequence(const QString& group, const QString& action) { 79QKeySequence 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
81Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const QString& group, 83Qt::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
104void ControllerShortcut::SetKey(const QString& buttons_shortcut) { 106void 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
113private: 113private:
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
314GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan) 315GMainWindow::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
1295void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name, 1297void 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
3585void GMainWindow::OnSaveConfig() { 3590void GMainWindow::OnSaveConfig() {
3586 system->ApplySettings(); 3591 system->ApplySettings();
3587 config->Save(); 3592 config->SaveAllValues();
3588} 3593}
3589 3594
3590void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { 3595void 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
4591void GMainWindow::UpdateGPUAccuracyButton() { 4596void 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
4605void GMainWindow::UpdateAPIText() { 4611void 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
4617void GMainWindow::UpdateFilterText() { 4624void 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
4624void GMainWindow::UpdateAAText() { 4631void 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
5082void GMainWindow::UpdateUITheme() { 5090void 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() {
5132void GMainWindow::LoadTranslation() { 5140void 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
5150void GMainWindow::OnLanguageChanged(const QString& locale) { 5159void 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
5274int main(int argc, char* argv[]) { 5283int 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
29class Config; 30class QtConfig;
30class ClickableLabel; 31class ClickableLabel;
31class EmuThread; 32class EmuThread;
32class GameList; 33class GameList;
@@ -185,7 +186,7 @@ class GMainWindow : public QMainWindow {
185public: 186public:
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
21namespace FS = Common::FS;
22
18namespace UISettings { 23namespace UISettings {
19 24
20const Themes themes{{ 25const Themes themes{{
@@ -28,10 +33,8 @@ const Themes themes{{
28 33
29bool IsDarkTheme() { 34bool 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
37Values values = {}; 40Values 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
58void 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
74void 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
18using Settings::Category; 19using Settings::Category;
19using Settings::ConfirmStop; 20using Settings::ConfirmStop;
@@ -37,15 +38,15 @@ namespace UISettings {
37bool IsDarkTheme(); 38bool IsDarkTheme();
38 39
39struct ContextualShortcut { 40struct 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
46struct Shortcut { 47struct 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
62static constexpr Theme default_theme{
63#ifdef _WIN32
64 Theme::DarkColorful
65#else
66 Theme::DefaultColorful
67#endif
68};
69
61using Themes = std::array<std::pair<const char*, const char*>, 6>; 70using Themes = std::array<std::pair<const char*, const char*>, 6>;
62extern const Themes themes; 71extern const Themes themes;
63 72
64struct GameDir { 73struct 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
207u32 CalculateWidth(u32 height, Settings::AspectRatio ratio); 216u32 CalculateWidth(u32 height, Settings::AspectRatio ratio);
208 217
218void SaveWindowState();
219void 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
226const 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
211Q_DECLARE_METATYPE(UISettings::GameDir*); 255Q_DECLARE_METATYPE(UISettings::GameDir*);
256
257// These metatype declarations cannot be in common/settings.h because core is devoid of QT
258Q_DECLARE_METATYPE(Settings::CpuAccuracy);
259Q_DECLARE_METATYPE(Settings::GpuAccuracy);
260Q_DECLARE_METATYPE(Settings::FullscreenMode);
261Q_DECLARE_METATYPE(Settings::NvdecEmulation);
262Q_DECLARE_METATYPE(Settings::ResolutionSetup);
263Q_DECLARE_METATYPE(Settings::ScalingFilter);
264Q_DECLARE_METATYPE(Settings::AntiAliasing);
265Q_DECLARE_METATYPE(Settings::RendererBackend);
266Q_DECLARE_METATYPE(Settings::ShaderBackend);
267Q_DECLARE_METATYPE(Settings::AstcRecompression);
268Q_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)
13endfunction() 13endfunction()
14 14
15add_executable(yuzu-cmd 15add_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
32create_target_directory_groups(yuzu-cmd) 31create_target_directory_groups(yuzu-cmd)
33 32
34target_link_libraries(yuzu-cmd PRIVATE common core input_common) 33target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common)
35target_link_libraries(yuzu-cmd PRIVATE inih::INIReader glad) 34target_link_libraries(yuzu-cmd PRIVATE glad)
36if (MSVC) 35if (MSVC)
37 target_link_libraries(yuzu-cmd PRIVATE getopt) 36 target_link_libraries(yuzu-cmd PRIVATE getopt)
38endif() 37endif()
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
19namespace FS = Common::FS;
20
21const std::filesystem::path default_config_path =
22 FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini";
23
24Config::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
30Config::~Config() = default;
31
32bool 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
53static 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
59static const std::array<int, Settings::NativeMotion::NumMotions> default_motions = {
60 SDL_SCANCODE_7,
61 SDL_SCANCODE_8,
62};
63
64static 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
81template <>
82void 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
90template <>
91void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) {
92 setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
93}
94
95template <typename Type, bool ranged>
96void 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
101void 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
117void 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
276void 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
13class INIReader;
14
15class 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
22public:
23 explicit Config(std::optional<std::filesystem::path> config_path);
24 ~Config();
25
26 void Reload();
27
28private:
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
6namespace DefaultINI {
7
8const 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
18connected=
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
35button_a=
36button_b=
37button_x=
38button_y=
39button_lstick=
40button_rstick=
41button_l=
42button_r=
43button_zl=
44button_zr=
45button_plus=
46button_minus=
47button_dleft=
48button_dup=
49button_dright=
50button_ddown=
51button_lstick_left=
52button_lstick_up=
53button_lstick_right=
54button_lstick_down=
55button_sl=
56button_sr=
57button_home=
58button_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)
72lstick=
73rstick=
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
87motionleft=
88motionright=
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
96debug_pad_enabled =
97
98# Enable sdl raw input. Allows to configure up to 8 xinput controllers.
99# 0 (default): Disabled, 1: Enabled
100enable_raw_input =
101
102# Enable yuzu joycon driver instead of SDL drive.
103# 0: Disabled, 1 (default): Enabled
104enable_joycon_driver =
105
106# Emulates an analog input from buttons. Allowing to dial any angle.
107# 0 (default): Disabled, 1: Enabled
108emulate_analog_keyboard =
109
110# Whether to enable or disable vibration
111# 0: Disabled, 1 (default): Enabled
112vibration_enabled=
113
114# Whether to enable or disable accurate vibrations
115# 0 (default): Disabled, 1: Enabled
116enable_accurate_vibrations=
117
118# Enables controller motion inputs
119# 0: Disabled, 1 (default): Enabled
120motion_enabled =
121
122# Defines the udp device's touch screen coordinate system for cemuhookudp devices
123# - "min_x", "min_y", "max_x", "max_y"
124touch_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
137udp_input_servers =
138
139# Enable controlling an axis via a mouse input.
140# 0 (default): Off, 1: On
141mouse_panning =
142
143# Set mouse panning horizontal sensitivity.
144# Default: 50.0
145mouse_panning_x_sensitivity =
146
147# Set mouse panning vertical sensitivity.
148# Default: 50.0
149mouse_panning_y_sensitivity =
150
151# Set mouse panning deadzone horizontal counterweight.
152# Default: 0.0
153mouse_panning_deadzone_x_counterweight =
154
155# Set mouse panning deadzone vertical counterweight.
156# Default: 0.0
157mouse_panning_deadzone_y_counterweight =
158
159# Set mouse panning stick decay strength.
160# Default: 22.0
161mouse_panning_decay_strength =
162
163# Set mouse panning stick minimum decay.
164# Default: 5.0
165mouse_panning_minimum_decay =
166
167# Emulate an analog control stick from keyboard inputs.
168# 0 (default): Disabled, 1: Enabled
169emulate_analog_keyboard =
170
171# Enable mouse inputs to the guest
172# 0 (default): Disabled, 1: Enabled
173mouse_enabled =
174
175# Enable keyboard inputs to the guest
176# 0 (default): Disabled, 1: Enabled
177keyboard_enabled =
178
179)"
180 R"(
181[Core]
182# Whether to use multi-core for CPU emulation
183# 0: Disabled, 1 (default): Enabled
184use_multi_core =
185
186# Enable unsafe extended guest system memory layout (8GB DRAM)
187# 0 (default): Disabled, 1: Enabled
188use_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
196cpu_accuracy =
197
198# Allow disabling safe optimizations.
199# 0 (default): Disabled, 1: Enabled
200cpu_debug_mode =
201
202# Enable inline page tables optimization (faster guest memory access)
203# 0: Disabled, 1 (default): Enabled
204cpuopt_page_tables =
205
206# Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps)
207# 0: Disabled, 1 (default): Enabled
208cpuopt_block_linking =
209
210# Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns)
211# 0: Disabled, 1 (default): Enabled
212cpuopt_return_stack_buffer =
213
214# Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture)
215# 0: Disabled, 1 (default): Enabled
216cpuopt_fast_dispatcher =
217
218# Enable context elimination CPU Optimization (reduce host memory use for guest context)
219# 0: Disabled, 1 (default): Enabled
220cpuopt_context_elimination =
221
222# Enable constant propagation CPU optimization (basic IR optimization)
223# 0: Disabled, 1 (default): Enabled
224cpuopt_const_prop =
225
226# Enable miscellaneous CPU optimizations (basic IR optimization)
227# 0: Disabled, 1 (default): Enabled
228cpuopt_misc_ir =
229
230# Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access)
231# 0: Disabled, 1 (default): Enabled
232cpuopt_reduce_misalign_checks =
233
234# Enable Host MMU Emulation (faster guest memory access)
235# 0: Disabled, 1 (default): Enabled
236cpuopt_fastmem =
237
238# Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access)
239# 0: Disabled, 1 (default): Enabled
240cpuopt_fastmem_exclusives =
241
242# Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access)
243# 0: Disabled, 1 (default): Enabled
244cpuopt_recompile_exclusives =
245
246# Enable optimization to ignore invalid memory accesses (faster guest memory access)
247# 0: Disabled, 1 (default): Enabled
248cpuopt_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
253cpuopt_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
258cpuopt_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
263cpuopt_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
268cpuopt_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
273cpuopt_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
278cpuopt_unsafe_ignore_global_monitor =
279
280)"
281 R"(
282[Renderer]
283# Which backend API to use.
284# 0: OpenGL, 1 (default): Vulkan
285backend =
286
287# Whether to enable asynchronous presentation (Vulkan only)
288# 0 (default): Off, 1: On
289async_presentation =
290
291# Enable graphics API debugging mode.
292# 0 (default): Disabled, 1: Enabled
293debug =
294
295# Enable shader feedback.
296# 0 (default): Disabled, 1: Enabled
297renderer_shader_feedback =
298
299# Enable Nsight Aftermath crash dumps
300# 0 (default): Disabled, 1: Enabled
301nsight_aftermath =
302
303# Disable shader loop safety checks, executing the shader without loop logic changes
304# 0 (default): Disabled, 1: Enabled
305disable_shader_loop_safety_checks =
306
307# Which Vulkan physical device to use (defaults to 0)
308vulkan_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)
321resolution_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
330scaling_filter =
331
332# Anti-Aliasing (AA)
333# 0 (default): None, 1: FXAA, 2: SMAA
334anti_aliasing =
335
336# Whether to use fullscreen or borderless window mode
337# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen
338fullscreen_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
342aspect_ratio =
343
344# Anisotropic filtering
345# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x
346max_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
356use_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
361shader_backend =
362
363# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.
364# 0: Off, 1 (default): On
365use_reactive_flushing =
366
367# Whether to allow asynchronous shader building.
368# 0 (default): Off, 1: On
369use_asynchronous_shaders =
370
371# NVDEC emulation.
372# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding
373nvdec_emulation =
374
375# Accelerate ASTC texture decoding.
376# 0: Off, 1 (default): On
377accelerate_astc =
378
379# Decode ASTC textures asynchronously.
380# 0 (default): Off, 1: On
381async_astc =
382
383# Recompress ASTC textures to a different format.
384# 0 (default): Uncompressed, 1: BC1 (Low quality), 2: BC3: (Medium quality)
385async_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)
389use_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)
393speed_limit =
394
395# Whether to use disk based shader cache
396# 0: Off, 1 (default): On
397use_disk_shader_cache =
398
399# Which gpu accuracy level to use
400# 0: Normal, 1 (default): High, 2: Extreme (Very slow)
401gpu_accuracy =
402
403# Whether to use asynchronous GPU emulation
404# 0 : Off (slow), 1 (default): On (fast)
405use_asynchronous_gpu_emulation =
406
407# Inform the guest that GPU operations completed more quickly than they did.
408# 0: Off, 1 (default): On
409use_fast_gpu_time =
410
411# Whether to use garbage collection or not for GPU caches.
412# 0 (default): Off, 1: On
413use_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.
417bg_red =
418bg_blue =
419bg_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
429output_engine =
430
431# Which audio device to use.
432# auto (default): Auto-select
433output_device =
434
435# Output volume.
436# 100 (default): 100%, 0; mute
437volume =
438
439[Data Storage]
440# Whether to create a virtual SD card.
441# 1 (default): Yes, 0: No
442use_virtual_sd =
443
444# Whether or not to enable gamecard emulation
445# 1: Yes, 0 (default): No
446gamecard_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
451gamecard_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
456gamecard_path =
457
458[System]
459# Whether the system is docked
460# 1 (default): Yes, 0: No
461use_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
465rng_seed_enabled =
466rng_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
471custom_rtc_enabled =
472custom_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
478language_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
482region_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
486time_zone_index =
487
488# Sets the sound output mode.
489# 0: Mono, 1 (default): Stereo, 2: Surround
490sound_index =
491
492[Miscellaneous]
493# A filter which removes logs below a certain logging level.
494# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
495log_filter = *:Trace
496
497# Use developer keys
498# 0 (default): Disabled, 1: Enabled
499use_dev_keys =
500
501[Debugging]
502# Record frame time data, can be found in the log directory. Boolean value
503record_frame_times =
504# Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them
505dump_exefs=false
506# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
507dump_nso=false
508# Determines whether or not yuzu will save the filesystem access log.
509enable_fs_access_log=false
510# Enables verbose reporting services
511reporting_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
514quest_flag =
515# Determines whether debug asserts should be enabled, which will throw an exception on asserts.
516# false: Disabled (default), true: Enabled
517use_debug_asserts =
518# Determines whether unimplemented HLE service calls should be automatically stubbed.
519# false: Disabled (default), true: Enabled
520use_auto_stub =
521# Enables/Disables the macro JIT compiler
522disable_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
525use_gdbstub=false
526# The port to use for the GDB server, if it is enabled.
527gdbstub_port=6543
528
529[WebService]
530# Whether or not to enable telemetry
531# 0: No, 1 (default): Yes
532enable_telemetry =
533# URL for Web API
534web_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
537yuzu_username =
538yuzu_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'
544network_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 '|'):
549title_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
11const 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
17const std::array<int, Settings::NativeMotion::NumMotions> SdlConfig::default_motions = {
18 SDL_SCANCODE_7,
19 SDL_SCANCODE_8,
20};
21
22const 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
38const std::array<int, 2> SdlConfig::default_stick_mod = {
39 SDL_SCANCODE_D,
40 0,
41};
42
43const std::array<int, 2> SdlConfig::default_ringcon_analogs{{
44 0,
45 0,
46}};
47
48SdlConfig::SdlConfig(const std::optional<std::string> config_path) {
49 Initialize(config_path);
50 ReadSdlValues();
51 SaveSdlValues();
52}
53
54SdlConfig::~SdlConfig() {
55 if (global) {
56 SdlConfig::SaveAllValues();
57 }
58}
59
60void SdlConfig::ReloadAllValues() {
61 Reload();
62 ReadSdlValues();
63 SaveSdlValues();
64}
65
66void SdlConfig::SaveAllValues() {
67 Save();
68 SaveSdlValues();
69}
70
71void SdlConfig::ReadSdlValues() {
72 ReadSdlControlValues();
73}
74
75void 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
92void 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
145void 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
168void 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
179void SdlConfig::SaveSdlValues() {
180 SaveSdlControlValues();
181
182 WriteToIni();
183}
184
185void 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
202void 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
233void 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
248void 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
255std::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
8class SdlConfig final : public Config {
9public:
10 explicit SdlConfig(std::optional<std::string> config_path);
11 ~SdlConfig() override;
12
13 void ReloadAllValues() override;
14 void SaveAllValues() override;
15
16protected:
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
43public:
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