summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-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/InputHandler.kt38
-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.h44
-rw-r--r--src/core/CMakeLists.txt9
-rw-r--r--src/core/hid/emulated_controller.cpp67
-rw-r--r--src/core/hid/emulated_controller.h1
-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/am/applets/applet_cabinet.cpp3
-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/hle/service/set/set_sys.cpp66
-rw-r--r--src/core/hle/service/set/set_sys.h24
-rw-r--r--src/core/hle/service/time/clock_types.h5
-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.h211
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h97
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h4
-rw-r--r--src/video_core/buffer_cache/usage_tracker.h79
-rw-r--r--src/video_core/query_cache/query_cache.h2
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h17
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp36
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h21
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.cpp29
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.h14
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp28
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.h21
-rw-r--r--src/video_core/renderer_vulkan/vk_smaa.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.h4
-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/video_core/texture_cache/slot_vector.h4
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp3
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h4
-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_debug.cpp3
-rw-r--r--src/yuzu/configuration/configure_debug.ui86
-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.cpp151
-rw-r--r--src/yuzu/main.h9
-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
126 files changed, 4847 insertions, 5089 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)
add_subdirectory(video_core)
add_subdirectory(network)
add_subdirectory(input_common)
+add_subdirectory(frontend_common)
add_subdirectory(shader_recompiler)
if (YUZU_ROOM)
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts
index 021b070e0..5721327e7 100644
--- a/src/android/app/build.gradle.kts
+++ b/src/android/app/build.gradle.kts
@@ -219,7 +219,6 @@ dependencies {
implementation("io.coil-kt:coil:2.2.2")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("androidx.window:window:1.2.0-beta03")
- implementation("org.ini4j:ini4j:0.5.4")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
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 {
*/
external fun onTouchReleased(finger_id: Int)
- external fun reloadSettings()
-
external fun initGameIni(gameID: String?)
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
import android.widget.Toast
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
-import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
+import org.yuzu.yuzu_emu.utils.NativeConfig
object Settings {
private val context get() = YuzuApplication.appContext
@@ -19,7 +19,7 @@ object Settings {
context.getString(R.string.ini_saved),
Toast.LENGTH_SHORT
).show()
- SettingsFile.saveFile(SettingsFile.FILE_NAME_CONFIG)
+ NativeConfig.saveSettings()
} else {
// TODO: Save custom game settings
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
import com.google.android.material.color.MaterialColors
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import org.yuzu.yuzu_emu.NativeLibrary
import java.io.IOException
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
@@ -165,11 +164,12 @@ class SettingsActivity : AppCompatActivity() {
settingsViewModel.shouldSave = false
// Delete settings file because the user may have changed values that do not exist in the UI
+ NativeConfig.unloadConfig()
val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG)
if (!settingsFile.delete()) {
throw IOException("Failed to delete $settingsFile")
}
- NativeLibrary.reloadSettings()
+ NativeConfig.initializeConfig()
Toast.makeText(
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 @@
package org.yuzu.yuzu_emu.features.settings.utils
-import android.widget.Toast
import java.io.*
-import org.ini4j.Wini
-import org.yuzu.yuzu_emu.R
-import org.yuzu.yuzu_emu.YuzuApplication
-import org.yuzu.yuzu_emu.features.settings.model.*
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
-import org.yuzu.yuzu_emu.utils.Log
-import org.yuzu.yuzu_emu.utils.NativeConfig
/**
* Contains static methods for interacting with .ini files in which settings are stored.
@@ -19,41 +12,6 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
object SettingsFile {
const val FILE_NAME_CONFIG = "config"
- /**
- * Saves a Settings HashMap to a given .ini file on disk. If unsuccessful, outputs an error
- * telling why it failed.
- *
- * @param fileName The target filename without a path or extension.
- */
- fun saveFile(fileName: String) {
- val ini = getSettingsFile(fileName)
- try {
- val wini = Wini(ini)
- for (specificCategory in Settings.Category.values()) {
- val categoryHeader = NativeConfig.getConfigHeader(specificCategory.ordinal)
- for (setting in Settings.settingsList) {
- if (setting.key!!.isEmpty()) continue
-
- val settingCategoryHeader =
- NativeConfig.getConfigHeader(setting.category.ordinal)
- val iniSetting: String? = wini.get(categoryHeader, setting.key)
- if (iniSetting != null || settingCategoryHeader == categoryHeader) {
- wini.put(settingCategoryHeader, setting.key, setting.valueAsString)
- }
- }
- }
- wini.store()
- } catch (e: IOException) {
- Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.message)
- val context = YuzuApplication.appContext
- Toast.makeText(
- context,
- context.getString(R.string.error_saving, fileName, e.message),
- Toast.LENGTH_SHORT
- ).show()
- }
- }
-
fun getSettingsFile(fileName: String): File =
File(DirectoryInitialization.userDirectory + "/config/" + fileName + ".ini")
}
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 {
}
// Clear existing user data
+ NativeConfig.unloadConfig()
File(DirectoryInitialization.userDirectory!!).deleteRecursively()
// Copy archive to internal storage
@@ -643,6 +644,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
// Reinitialize relevant data
NativeLibrary.initializeSystem(true)
+ NativeConfig.initializeConfig()
gamesViewModel.reloadGames(false)
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 {
if (!areDirectoriesReady) {
initializeInternalStorage()
NativeLibrary.initializeSystem(false)
+ NativeConfig.initializeConfig()
areDirectoriesReady = true
}
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InputHandler.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InputHandler.kt
index 47bde5081..e63382e1d 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InputHandler.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InputHandler.kt
@@ -27,6 +27,8 @@ object InputHandler {
0x054C -> getInputDS5ButtonKey(event.keyCode)
0x057E -> getInputJoyconButtonKey(event.keyCode)
0x1532 -> getInputRazerButtonKey(event.keyCode)
+ 0x3537 -> getInputRedmagicButtonKey(event.keyCode)
+ 0x358A -> getInputBackboneLabsButtonKey(event.keyCode)
else -> getInputGenericButtonKey(event.keyCode)
}
@@ -227,6 +229,42 @@ object InputHandler {
}
}
+ private fun getInputRedmagicButtonKey(key: Int): Int {
+ return when (key) {
+ KeyEvent.KEYCODE_BUTTON_A -> NativeLibrary.ButtonType.BUTTON_B
+ KeyEvent.KEYCODE_BUTTON_B -> NativeLibrary.ButtonType.BUTTON_A
+ KeyEvent.KEYCODE_BUTTON_X -> NativeLibrary.ButtonType.BUTTON_Y
+ KeyEvent.KEYCODE_BUTTON_Y -> NativeLibrary.ButtonType.BUTTON_X
+ KeyEvent.KEYCODE_BUTTON_L1 -> NativeLibrary.ButtonType.TRIGGER_L
+ KeyEvent.KEYCODE_BUTTON_R1 -> NativeLibrary.ButtonType.TRIGGER_R
+ KeyEvent.KEYCODE_BUTTON_L2 -> NativeLibrary.ButtonType.TRIGGER_ZL
+ KeyEvent.KEYCODE_BUTTON_R2 -> NativeLibrary.ButtonType.TRIGGER_ZR
+ KeyEvent.KEYCODE_BUTTON_THUMBL -> NativeLibrary.ButtonType.STICK_L
+ KeyEvent.KEYCODE_BUTTON_THUMBR -> NativeLibrary.ButtonType.STICK_R
+ KeyEvent.KEYCODE_BUTTON_START -> NativeLibrary.ButtonType.BUTTON_PLUS
+ KeyEvent.KEYCODE_BUTTON_SELECT -> NativeLibrary.ButtonType.BUTTON_MINUS
+ else -> -1
+ }
+ }
+
+ private fun getInputBackboneLabsButtonKey(key: Int): Int {
+ return when (key) {
+ KeyEvent.KEYCODE_BUTTON_A -> NativeLibrary.ButtonType.BUTTON_B
+ KeyEvent.KEYCODE_BUTTON_B -> NativeLibrary.ButtonType.BUTTON_A
+ KeyEvent.KEYCODE_BUTTON_X -> NativeLibrary.ButtonType.BUTTON_Y
+ KeyEvent.KEYCODE_BUTTON_Y -> NativeLibrary.ButtonType.BUTTON_X
+ KeyEvent.KEYCODE_BUTTON_L1 -> NativeLibrary.ButtonType.TRIGGER_L
+ KeyEvent.KEYCODE_BUTTON_R1 -> NativeLibrary.ButtonType.TRIGGER_R
+ KeyEvent.KEYCODE_BUTTON_L2 -> NativeLibrary.ButtonType.TRIGGER_ZL
+ KeyEvent.KEYCODE_BUTTON_R2 -> NativeLibrary.ButtonType.TRIGGER_ZR
+ KeyEvent.KEYCODE_BUTTON_THUMBL -> NativeLibrary.ButtonType.STICK_L
+ KeyEvent.KEYCODE_BUTTON_THUMBR -> NativeLibrary.ButtonType.STICK_R
+ KeyEvent.KEYCODE_BUTTON_START -> NativeLibrary.ButtonType.BUTTON_PLUS
+ KeyEvent.KEYCODE_BUTTON_SELECT -> NativeLibrary.ButtonType.BUTTON_MINUS
+ else -> -1
+ }
+ }
+
private fun getInputGenericButtonKey(key: Int): Int {
return when (key) {
KeyEvent.KEYCODE_BUTTON_A -> NativeLibrary.ButtonType.BUTTON_A
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 @@
package org.yuzu.yuzu_emu.utils
object NativeConfig {
+ /**
+ * Creates a Config object and opens the emulation config.
+ */
+ @Synchronized
+ external fun initializeConfig()
+
+ /**
+ * Destroys the stored config object. This automatically saves the existing config.
+ */
+ @Synchronized
+ external fun unloadConfig()
+
+ /**
+ * Reads values saved to the config file and saves them.
+ */
+ @Synchronized
+ external fun reloadSettings()
+
+ /**
+ * Saves settings values in memory to disk.
+ */
+ @Synchronized
+ external fun saveSettings()
+
external fun getBoolean(key: String, getDefault: Boolean): Boolean
external fun setBoolean(key: String, value: Boolean)
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
android_common/android_common.h
applets/software_keyboard.cpp
applets/software_keyboard.h
- config.cpp
- config.h
- default_ini.h
emu_window/emu_window.cpp
emu_window/emu_window.h
id_cache.cpp
@@ -16,15 +13,17 @@ add_library(yuzu-android SHARED
native.cpp
native.h
native_config.cpp
- uisettings.cpp
+ android_settings.cpp
game_metadata.cpp
native_log.cpp
+ android_config.cpp
+ android_config.h
)
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
-target_link_libraries(yuzu-android PRIVATE audio_core common core input_common)
-target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics log)
+target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common)
+target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
if (ARCHITECTURE_arm64)
target_link_libraries(yuzu-android PRIVATE adrenotools)
endif()
diff --git a/src/android/app/src/main/jni/android_config.cpp b/src/android/app/src/main/jni/android_config.cpp
new file mode 100644
index 000000000..3041c25c9
--- /dev/null
+++ b/src/android/app/src/main/jni/android_config.cpp
@@ -0,0 +1,70 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "android_config.h"
+#include "android_settings.h"
+#include "common/settings_setting.h"
+
+AndroidConfig::AndroidConfig(const std::string& config_name, ConfigType config_type)
+ : Config(config_type) {
+ Initialize(config_name);
+ if (config_type != ConfigType::InputProfile) {
+ ReadAndroidValues();
+ SaveAndroidValues();
+ }
+}
+
+AndroidConfig::~AndroidConfig() {
+ if (global) {
+ AndroidConfig::SaveAllValues();
+ }
+}
+
+void AndroidConfig::ReloadAllValues() {
+ Reload();
+ ReadAndroidValues();
+ SaveAndroidValues();
+}
+
+void AndroidConfig::SaveAllValues() {
+ Save();
+ SaveAndroidValues();
+}
+
+void AndroidConfig::ReadAndroidValues() {
+ if (global) {
+ ReadAndroidUIValues();
+ }
+}
+
+void AndroidConfig::ReadAndroidUIValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Android));
+
+ ReadCategory(Settings::Category::Android);
+
+ EndGroup();
+}
+
+void AndroidConfig::SaveAndroidValues() {
+ if (global) {
+ SaveAndroidUIValues();
+ }
+
+ WriteToIni();
+}
+
+void AndroidConfig::SaveAndroidUIValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Android));
+
+ WriteCategory(Settings::Category::Android);
+
+ EndGroup();
+}
+
+std::vector<Settings::BasicSetting*>& AndroidConfig::FindRelevantList(Settings::Category category) {
+ auto& map = Settings::values.linkage.by_category;
+ if (map.contains(category)) {
+ return Settings::values.linkage.by_category[category];
+ }
+ return AndroidSettings::values.linkage.by_category[category];
+}
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 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "frontend_common/config.h"
+
+class AndroidConfig final : public Config {
+public:
+ explicit AndroidConfig(const std::string& config_name = "config",
+ ConfigType config_type = ConfigType::GlobalConfig);
+ ~AndroidConfig() override;
+
+ void ReloadAllValues() override;
+ void SaveAllValues() override;
+
+protected:
+ void ReadAndroidValues();
+ void ReadAndroidUIValues();
+ void ReadHidbusValues() override {}
+ void ReadDebugControlValues() override {}
+ void ReadPathValues() override {}
+ void ReadShortcutValues() override {}
+ void ReadUIValues() override {}
+ void ReadUIGamelistValues() override {}
+ void ReadUILayoutValues() override {}
+ void ReadMultiplayerValues() override {}
+
+ void SaveAndroidValues();
+ void SaveAndroidUIValues();
+ void SaveHidbusValues() override {}
+ void SaveDebugControlValues() override {}
+ void SavePathValues() override {}
+ void SaveShortcutValues() override {}
+ void SaveUIValues() override {}
+ void SaveUIGamelistValues() override {}
+ void SaveUILayoutValues() override {}
+ void SaveMultiplayerValues() override {}
+
+ std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override;
+};
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 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "uisettings.h"
+#include "android_settings.h"
namespace AndroidSettings {
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 @@
-// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <memory>
-#include <optional>
-#include <sstream>
-
-#include <INIReader.h>
-#include "common/fs/file.h"
-#include "common/fs/fs.h"
-#include "common/fs/path_util.h"
-#include "common/logging/log.h"
-#include "common/settings.h"
-#include "common/settings_enums.h"
-#include "core/hle/service/acc/profile_manager.h"
-#include "input_common/main.h"
-#include "jni/config.h"
-#include "jni/default_ini.h"
-#include "uisettings.h"
-
-namespace FS = Common::FS;
-
-Config::Config(const std::string& config_name, ConfigType config_type)
- : type(config_type), global{config_type == ConfigType::GlobalConfig} {
- Initialize(config_name);
-}
-
-Config::~Config() = default;
-
-bool Config::LoadINI(const std::string& default_contents, bool retry) {
- void(FS::CreateParentDir(config_loc));
- config = std::make_unique<INIReader>(FS::PathToUTF8String(config_loc));
- const auto config_loc_str = FS::PathToUTF8String(config_loc);
- if (config->ParseError() < 0) {
- if (retry) {
- LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...",
- config_loc_str);
-
- void(FS::CreateParentDir(config_loc));
- void(FS::WriteStringToFile(config_loc, FS::FileType::TextFile, default_contents));
-
- config = std::make_unique<INIReader>(config_loc_str);
-
- return LoadINI(default_contents, false);
- }
- LOG_ERROR(Config, "Failed.");
- return false;
- }
- LOG_INFO(Config, "Successfully loaded {}", config_loc_str);
- return true;
-}
-
-template <>
-void Config::ReadSetting(const std::string& group, Settings::Setting<std::string>& setting) {
- std::string setting_value = config->Get(group, setting.GetLabel(), setting.GetDefault());
- if (setting_value.empty()) {
- setting_value = setting.GetDefault();
- }
- setting = std::move(setting_value);
-}
-
-template <>
-void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) {
- setting = config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
-}
-
-template <typename Type, bool ranged>
-void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) {
- setting = static_cast<Type>(
- config->GetInteger(group, setting.GetLabel(), static_cast<long>(setting.GetDefault())));
-}
-
-void Config::ReadValues() {
- ReadSetting("ControlsGeneral", Settings::values.mouse_enabled);
- ReadSetting("ControlsGeneral", Settings::values.touch_device);
- ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled);
- ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled);
- ReadSetting("ControlsGeneral", Settings::values.vibration_enabled);
- ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations);
- ReadSetting("ControlsGeneral", Settings::values.motion_enabled);
- Settings::values.touchscreen.enabled =
- config->GetBoolean("ControlsGeneral", "touch_enabled", true);
- Settings::values.touchscreen.rotation_angle =
- config->GetInteger("ControlsGeneral", "touch_angle", 0);
- Settings::values.touchscreen.diameter_x =
- config->GetInteger("ControlsGeneral", "touch_diameter_x", 15);
- Settings::values.touchscreen.diameter_y =
- config->GetInteger("ControlsGeneral", "touch_diameter_y", 15);
-
- int num_touch_from_button_maps =
- config->GetInteger("ControlsGeneral", "touch_from_button_map", 0);
- if (num_touch_from_button_maps > 0) {
- for (int i = 0; i < num_touch_from_button_maps; ++i) {
- Settings::TouchFromButtonMap map;
- map.name = config->Get("ControlsGeneral",
- std::string("touch_from_button_maps_") + std::to_string(i) +
- std::string("_name"),
- "default");
- const int num_touch_maps = config->GetInteger(
- "ControlsGeneral",
- std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"),
- 0);
- map.buttons.reserve(num_touch_maps);
-
- for (int j = 0; j < num_touch_maps; ++j) {
- std::string touch_mapping =
- config->Get("ControlsGeneral",
- std::string("touch_from_button_maps_") + std::to_string(i) +
- std::string("_bind_") + std::to_string(j),
- "");
- map.buttons.emplace_back(std::move(touch_mapping));
- }
-
- Settings::values.touch_from_button_maps.emplace_back(std::move(map));
- }
- } else {
- Settings::values.touch_from_button_maps.emplace_back(
- Settings::TouchFromButtonMap{"default", {}});
- num_touch_from_button_maps = 1;
- }
- Settings::values.touch_from_button_map_index = std::clamp(
- Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
-
- ReadSetting("ControlsGeneral", Settings::values.udp_input_servers);
-
- // Data Storage
- ReadSetting("Data Storage", Settings::values.use_virtual_sd);
- FS::SetYuzuPath(FS::YuzuPath::NANDDir,
- config->Get("Data Storage", "nand_directory",
- FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
- FS::SetYuzuPath(FS::YuzuPath::SDMCDir,
- config->Get("Data Storage", "sdmc_directory",
- FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
- FS::SetYuzuPath(FS::YuzuPath::LoadDir,
- config->Get("Data Storage", "load_directory",
- FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
- FS::SetYuzuPath(FS::YuzuPath::DumpDir,
- config->Get("Data Storage", "dump_directory",
- FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
- ReadSetting("Data Storage", Settings::values.gamecard_inserted);
- ReadSetting("Data Storage", Settings::values.gamecard_current_game);
- ReadSetting("Data Storage", Settings::values.gamecard_path);
-
- // System
- ReadSetting("System", Settings::values.current_user);
- Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0,
- Service::Account::MAX_USERS - 1);
-
- // Disable docked mode by default on Android
- Settings::values.use_docked_mode.SetValue(config->GetBoolean("System", "use_docked_mode", false)
- ? Settings::ConsoleMode::Docked
- : Settings::ConsoleMode::Handheld);
-
- const auto rng_seed_enabled = config->GetBoolean("System", "rng_seed_enabled", false);
- if (rng_seed_enabled) {
- Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0));
- } else {
- Settings::values.rng_seed.SetValue(0);
- }
- Settings::values.rng_seed_enabled.SetValue(rng_seed_enabled);
-
- const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false);
- if (custom_rtc_enabled) {
- Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0);
- } else {
- Settings::values.custom_rtc = 0;
- }
- Settings::values.custom_rtc_enabled = custom_rtc_enabled;
-
- ReadSetting("System", Settings::values.language_index);
- ReadSetting("System", Settings::values.region_index);
- ReadSetting("System", Settings::values.time_zone_index);
- ReadSetting("System", Settings::values.sound_index);
-
- // Core
- ReadSetting("Core", Settings::values.use_multi_core);
- ReadSetting("Core", Settings::values.memory_layout_mode);
-
- // Cpu
- ReadSetting("Cpu", Settings::values.cpu_accuracy);
- ReadSetting("Cpu", Settings::values.cpu_debug_mode);
- ReadSetting("Cpu", Settings::values.cpuopt_page_tables);
- ReadSetting("Cpu", Settings::values.cpuopt_block_linking);
- ReadSetting("Cpu", Settings::values.cpuopt_return_stack_buffer);
- ReadSetting("Cpu", Settings::values.cpuopt_fast_dispatcher);
- ReadSetting("Cpu", Settings::values.cpuopt_context_elimination);
- ReadSetting("Cpu", Settings::values.cpuopt_const_prop);
- ReadSetting("Cpu", Settings::values.cpuopt_misc_ir);
- ReadSetting("Cpu", Settings::values.cpuopt_reduce_misalign_checks);
- ReadSetting("Cpu", Settings::values.cpuopt_fastmem);
- ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives);
- ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives);
- ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts);
- ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma);
- ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error);
- ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
- ReadSetting("Cpu", Settings::values.cpuopt_unsafe_inaccurate_nan);
- ReadSetting("Cpu", Settings::values.cpuopt_unsafe_fastmem_check);
- ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_global_monitor);
-
- // Renderer
- ReadSetting("Renderer", Settings::values.renderer_backend);
- ReadSetting("Renderer", Settings::values.renderer_debug);
- ReadSetting("Renderer", Settings::values.renderer_shader_feedback);
- ReadSetting("Renderer", Settings::values.enable_nsight_aftermath);
- ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks);
- ReadSetting("Renderer", Settings::values.vulkan_device);
-
- ReadSetting("Renderer", Settings::values.resolution_setup);
- ReadSetting("Renderer", Settings::values.scaling_filter);
- ReadSetting("Renderer", Settings::values.fsr_sharpening_slider);
- ReadSetting("Renderer", Settings::values.anti_aliasing);
- ReadSetting("Renderer", Settings::values.fullscreen_mode);
- ReadSetting("Renderer", Settings::values.aspect_ratio);
- ReadSetting("Renderer", Settings::values.max_anisotropy);
- ReadSetting("Renderer", Settings::values.use_speed_limit);
- ReadSetting("Renderer", Settings::values.speed_limit);
- ReadSetting("Renderer", Settings::values.use_disk_shader_cache);
- ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation);
- ReadSetting("Renderer", Settings::values.vsync_mode);
- ReadSetting("Renderer", Settings::values.shader_backend);
- ReadSetting("Renderer", Settings::values.use_asynchronous_shaders);
- ReadSetting("Renderer", Settings::values.nvdec_emulation);
- ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
- ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
-
- ReadSetting("Renderer", Settings::values.bg_red);
- ReadSetting("Renderer", Settings::values.bg_green);
- ReadSetting("Renderer", Settings::values.bg_blue);
-
- // Use GPU accuracy normal by default on Android
- Settings::values.gpu_accuracy = static_cast<Settings::GpuAccuracy>(config->GetInteger(
- "Renderer", "gpu_accuracy", static_cast<u32>(Settings::GpuAccuracy::Normal)));
-
- // Use GPU default anisotropic filtering on Android
- Settings::values.max_anisotropy =
- static_cast<Settings::AnisotropyMode>(config->GetInteger("Renderer", "max_anisotropy", 1));
-
- // Disable ASTC compute by default on Android
- Settings::values.accelerate_astc.SetValue(
- config->GetBoolean("Renderer", "accelerate_astc", false) ? Settings::AstcDecodeMode::Gpu
- : Settings::AstcDecodeMode::Cpu);
-
- // Enable asynchronous presentation by default on Android
- Settings::values.async_presentation =
- config->GetBoolean("Renderer", "async_presentation", true);
-
- // Disable force_max_clock by default on Android
- Settings::values.renderer_force_max_clock =
- config->GetBoolean("Renderer", "force_max_clock", false);
-
- // Disable use_reactive_flushing by default on Android
- Settings::values.use_reactive_flushing =
- config->GetBoolean("Renderer", "use_reactive_flushing", false);
-
- // Audio
- ReadSetting("Audio", Settings::values.sink_id);
- ReadSetting("Audio", Settings::values.audio_output_device_id);
- ReadSetting("Audio", Settings::values.volume);
-
- // Miscellaneous
- // log_filter has a different default here than from common
- Settings::values.log_filter = "*:Info";
- ReadSetting("Miscellaneous", Settings::values.use_dev_keys);
-
- // Debugging
- Settings::values.record_frame_times =
- config->GetBoolean("Debugging", "record_frame_times", false);
- ReadSetting("Debugging", Settings::values.dump_exefs);
- ReadSetting("Debugging", Settings::values.dump_nso);
- ReadSetting("Debugging", Settings::values.enable_fs_access_log);
- ReadSetting("Debugging", Settings::values.reporting_services);
- ReadSetting("Debugging", Settings::values.quest_flag);
- ReadSetting("Debugging", Settings::values.use_debug_asserts);
- ReadSetting("Debugging", Settings::values.use_auto_stub);
- ReadSetting("Debugging", Settings::values.disable_macro_jit);
- ReadSetting("Debugging", Settings::values.disable_macro_hle);
- ReadSetting("Debugging", Settings::values.use_gdbstub);
- ReadSetting("Debugging", Settings::values.gdbstub_port);
-
- const auto title_list = config->Get("AddOns", "title_ids", "");
- std::stringstream ss(title_list);
- std::string line;
- while (std::getline(ss, line, '|')) {
- const auto title_id = std::strtoul(line.c_str(), nullptr, 16);
- const auto disabled_list = config->Get("AddOns", "disabled_" + line, "");
-
- std::stringstream inner_ss(disabled_list);
- std::string inner_line;
- std::vector<std::string> out;
- while (std::getline(inner_ss, inner_line, '|')) {
- out.push_back(inner_line);
- }
-
- Settings::values.disabled_addons.insert_or_assign(title_id, out);
- }
-
- // Web Service
- ReadSetting("WebService", Settings::values.enable_telemetry);
- ReadSetting("WebService", Settings::values.web_api_url);
- ReadSetting("WebService", Settings::values.yuzu_username);
- ReadSetting("WebService", Settings::values.yuzu_token);
-
- // Network
- ReadSetting("Network", Settings::values.network_interface);
-
- // Android
- ReadSetting("Android", AndroidSettings::values.picture_in_picture);
- ReadSetting("Android", AndroidSettings::values.screen_layout);
-}
-
-void Config::Initialize(const std::string& config_name) {
- const auto fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir);
- const auto config_file = fmt::format("{}.ini", config_name);
-
- switch (type) {
- case ConfigType::GlobalConfig:
- config_loc = FS::PathToUTF8String(fs_config_loc / config_file);
- break;
- case ConfigType::PerGameConfig:
- config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file));
- break;
- case ConfigType::InputProfile:
- config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file);
- LoadINI(DefaultINI::android_config_file);
- return;
- }
- LoadINI(DefaultINI::android_config_file);
- ReadValues();
-}
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 @@
-// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <filesystem>
-#include <memory>
-#include <optional>
-#include <string>
-
-#include "common/settings.h"
-
-class INIReader;
-
-class Config {
- bool LoadINI(const std::string& default_contents = "", bool retry = true);
-
-public:
- enum class ConfigType {
- GlobalConfig,
- PerGameConfig,
- InputProfile,
- };
-
- explicit Config(const std::string& config_name = "config",
- ConfigType config_type = ConfigType::GlobalConfig);
- ~Config();
-
- void Initialize(const std::string& config_name);
-
-private:
- /**
- * Applies a value read from the config to a Setting.
- *
- * @param group The name of the INI group
- * @param setting The yuzu setting to modify
- */
- template <typename Type, bool ranged>
- void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
-
- void ReadValues();
-
- const ConfigType type;
- std::unique_ptr<INIReader> config;
- std::string config_loc;
- const bool global;
-};
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 @@
-// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-namespace DefaultINI {
-
-const char* android_config_file = R"(
-
-[ControlsP0]
-# The input devices and parameters for each Switch native input
-# The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ...
-# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
-# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
-
-# Indicates if this player should be connected at boot
-connected=
-
-# for button input, the following devices are available:
-# - "keyboard" (default) for keyboard input. Required parameters:
-# - "code": the code of the key to bind
-# - "sdl" for joystick input using SDL. Required parameters:
-# - "guid": SDL identification GUID of the joystick
-# - "port": the index of the joystick to bind
-# - "button"(optional): the index of the button to bind
-# - "hat"(optional): the index of the hat to bind as direction buttons
-# - "axis"(optional): the index of the axis to bind
-# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right"
-# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
-# triggered if the axis value crosses
-# - "direction"(only used for axis): "+" means the button is triggered when the axis value
-# is greater than the threshold; "-" means the button is triggered when the axis value
-# is smaller than the threshold
-button_a=
-button_b=
-button_x=
-button_y=
-button_lstick=
-button_rstick=
-button_l=
-button_r=
-button_zl=
-button_zr=
-button_plus=
-button_minus=
-button_dleft=
-button_dup=
-button_dright=
-button_ddown=
-button_lstick_left=
-button_lstick_up=
-button_lstick_right=
-button_lstick_down=
-button_sl=
-button_sr=
-button_home=
-button_screenshot=
-
-# for analog input, the following devices are available:
-# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters:
-# - "up", "down", "left", "right": sub-devices for each direction.
-# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00"
-# - "modifier": sub-devices as a modifier.
-# - "modifier_scale": a float number representing the applied modifier scale to the analog input.
-# Must be in range of 0.0-1.0. Defaults to 0.5
-# - "sdl" for joystick input using SDL. Required parameters:
-# - "guid": SDL identification GUID of the joystick
-# - "port": the index of the joystick to bind
-# - "axis_x": the index of the axis to bind as x-axis (default to 0)
-# - "axis_y": the index of the axis to bind as y-axis (default to 1)
-lstick=
-rstick=
-
-# for motion input, the following devices are available:
-# - "keyboard" (default) for emulating random motion input from buttons. Required parameters:
-# - "code": the code of the key to bind
-# - "sdl" for motion input using SDL. Required parameters:
-# - "guid": SDL identification GUID of the joystick
-# - "port": the index of the joystick to bind
-# - "motion": the index of the motion sensor to bind
-# - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters:
-# - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001"
-# - "port": the port of the cemu hook server
-# - "pad": the index of the joystick
-# - "motion": the index of the motion sensor of the joystick to bind
-motionleft=
-motionright=
-
-[ControlsGeneral]
-# To use the debug_pad, prepend `debug_pad_` before each button setting above.
-# i.e. debug_pad_button_a=
-
-# Enable debug pad inputs to the guest
-# 0 (default): Disabled, 1: Enabled
-debug_pad_enabled =
-
-# Whether to enable or disable vibration
-# 0: Disabled, 1 (default): Enabled
-vibration_enabled=
-
-# Whether to enable or disable accurate vibrations
-# 0 (default): Disabled, 1: Enabled
-enable_accurate_vibrations=
-
-# Enables controller motion inputs
-# 0: Disabled, 1 (default): Enabled
-motion_enabled =
-
-# Defines the udp device's touch screen coordinate system for cemuhookudp devices
-# - "min_x", "min_y", "max_x", "max_y"
-touch_device=
-
-# for mapping buttons to touch inputs.
-#touch_from_button_map=1
-#touch_from_button_maps_0_name=default
-#touch_from_button_maps_0_count=2
-#touch_from_button_maps_0_bind_0=foo
-#touch_from_button_maps_0_bind_1=bar
-# etc.
-
-# List of Cemuhook UDP servers, delimited by ','.
-# Default: 127.0.0.1:26760
-# Example: 127.0.0.1:26760,123.4.5.67:26761
-udp_input_servers =
-
-# Enable controlling an axis via a mouse input.
-# 0 (default): Off, 1: On
-mouse_panning =
-
-# Set mouse sensitivity.
-# Default: 1.0
-mouse_panning_sensitivity =
-
-# Emulate an analog control stick from keyboard inputs.
-# 0 (default): Disabled, 1: Enabled
-emulate_analog_keyboard =
-
-# Enable mouse inputs to the guest
-# 0 (default): Disabled, 1: Enabled
-mouse_enabled =
-
-# Enable keyboard inputs to the guest
-# 0 (default): Disabled, 1: Enabled
-keyboard_enabled =
-
-[Core]
-# Whether to use multi-core for CPU emulation
-# 0: Disabled, 1 (default): Enabled
-use_multi_core =
-
-# Enable unsafe extended guest system memory layout (8GB DRAM)
-# 0 (default): Disabled, 1: Enabled
-use_unsafe_extended_memory_layout =
-
-[Cpu]
-# Adjusts various optimizations.
-# Auto-select mode enables choice unsafe optimizations.
-# Accurate enables only safe optimizations.
-# Unsafe allows any unsafe optimizations.
-# 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations
-cpu_accuracy =
-
-# Allow disabling safe optimizations.
-# 0 (default): Disabled, 1: Enabled
-cpu_debug_mode =
-
-# Enable inline page tables optimization (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_page_tables =
-
-# Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_block_linking =
-
-# Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_return_stack_buffer =
-
-# Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_fast_dispatcher =
-
-# Enable context elimination CPU Optimization (reduce host memory use for guest context)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_context_elimination =
-
-# Enable constant propagation CPU optimization (basic IR optimization)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_const_prop =
-
-# Enable miscellaneous CPU optimizations (basic IR optimization)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_misc_ir =
-
-# Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_reduce_misalign_checks =
-
-# Enable Host MMU Emulation (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_fastmem =
-
-# Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_fastmem_exclusives =
-
-# Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_recompile_exclusives =
-
-# Enable optimization to ignore invalid memory accesses (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_ignore_memory_aborts =
-
-# Enable unfuse FMA (improve performance on CPUs without FMA)
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_unfuse_fma =
-
-# Enable faster FRSQRTE and FRECPE
-# Only enabled if cpu_accuracy is set to Unsafe.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_reduce_fp_error =
-
-# Enable faster ASIMD instructions (32 bits only)
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_ignore_standard_fpcr =
-
-# Enable inaccurate NaN handling
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_inaccurate_nan =
-
-# Disable address space checks (64 bits only)
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_fastmem_check =
-
-# Enable faster exclusive instructions
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_ignore_global_monitor =
-
-[Renderer]
-# Which backend API to use.
-# 0: OpenGL (unsupported), 1 (default): Vulkan, 2: Null
-backend =
-
-# Whether to enable asynchronous presentation (Vulkan only)
-# 0: Off, 1 (default): On
-async_presentation =
-
-# Forces the GPU to run at the maximum possible clocks (thermal constraints will still be applied).
-# 0 (default): Disabled, 1: Enabled
-force_max_clock =
-
-# Enable graphics API debugging mode.
-# 0 (default): Disabled, 1: Enabled
-debug =
-
-# Enable shader feedback.
-# 0 (default): Disabled, 1: Enabled
-renderer_shader_feedback =
-
-# Enable Nsight Aftermath crash dumps
-# 0 (default): Disabled, 1: Enabled
-nsight_aftermath =
-
-# Disable shader loop safety checks, executing the shader without loop logic changes
-# 0 (default): Disabled, 1: Enabled
-disable_shader_loop_safety_checks =
-
-# Which Vulkan physical device to use (defaults to 0)
-vulkan_device =
-
-# 0: 0.5x (360p/540p) [EXPERIMENTAL]
-# 1: 0.75x (540p/810p) [EXPERIMENTAL]
-# 2 (default): 1x (720p/1080p)
-# 3: 2x (1440p/2160p)
-# 4: 3x (2160p/3240p)
-# 5: 4x (2880p/4320p)
-# 6: 5x (3600p/5400p)
-# 7: 6x (4320p/6480p)
-resolution_setup =
-
-# Pixel filter to use when up- or down-sampling rendered frames.
-# 0: Nearest Neighbor
-# 1 (default): Bilinear
-# 2: Bicubic
-# 3: Gaussian
-# 4: ScaleForce
-# 5: AMD FidelityFX™️ Super Resolution [Vulkan Only]
-scaling_filter =
-
-# Anti-Aliasing (AA)
-# 0 (default): None, 1: FXAA
-anti_aliasing =
-
-# Whether to use fullscreen or borderless window mode
-# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen
-fullscreen_mode =
-
-# Aspect ratio
-# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Force 16:10, 4: Stretch to Window
-aspect_ratio =
-
-# Anisotropic filtering
-# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x
-max_anisotropy =
-
-# Whether to enable VSync or not.
-# OpenGL: Values other than 0 enable VSync
-# Vulkan: FIFO is selected if the requested mode is not supported by the driver.
-# FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate.
-# FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down.
-# Mailbox can have lower latency than FIFO and does not tear but may drop frames.
-# Immediate (no synchronization) just presents whatever is available and can exhibit tearing.
-# 0: Immediate (Off), 1 (Default): Mailbox (On), 2: FIFO, 3: FIFO Relaxed
-use_vsync =
-
-# Selects the OpenGL shader backend. NV_gpu_program5 is required for GLASM. If NV_gpu_program5 is
-# not available and GLASM is selected, GLSL will be used.
-# 0: GLSL, 1 (default): GLASM, 2: SPIR-V
-shader_backend =
-
-# Whether to allow asynchronous shader building.
-# 0 (default): Off, 1: On
-use_asynchronous_shaders =
-
-# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.
-# 0 (default): Off, 1: On
-use_reactive_flushing =
-
-# NVDEC emulation.
-# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding
-nvdec_emulation =
-
-# Accelerate ASTC texture decoding.
-# 0 (default): Off, 1: On
-accelerate_astc =
-
-# Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value
-# 0: Off, 1: On (default)
-use_speed_limit =
-
-# Limits the speed of the game to run no faster than this value as a percentage of target speed
-# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
-speed_limit =
-
-# Whether to use disk based shader cache
-# 0: Off, 1 (default): On
-use_disk_shader_cache =
-
-# Which gpu accuracy level to use
-# 0 (default): Normal, 1: High, 2: Extreme (Very slow)
-gpu_accuracy =
-
-# Whether to use asynchronous GPU emulation
-# 0 : Off (slow), 1 (default): On (fast)
-use_asynchronous_gpu_emulation =
-
-# Inform the guest that GPU operations completed more quickly than they did.
-# 0: Off, 1 (default): On
-use_fast_gpu_time =
-
-# Force unmodified buffers to be flushed, which can cost performance.
-# 0: Off (default), 1: On
-use_pessimistic_flushes =
-
-# Whether to use garbage collection or not for GPU caches.
-# 0 (default): Off, 1: On
-use_caches_gc =
-
-# The clear color for the renderer. What shows up on the sides of the bottom screen.
-# Must be in range of 0-255. Defaults to 0 for all.
-bg_red =
-bg_blue =
-bg_green =
-
-[Audio]
-# Which audio output engine to use.
-# auto (default): Auto-select
-# cubeb: Cubeb audio engine (if available)
-# sdl2: SDL2 audio engine (if available)
-# null: No audio output
-output_engine =
-
-# Which audio device to use.
-# auto (default): Auto-select
-output_device =
-
-# Output volume.
-# 100 (default): 100%, 0; mute
-volume =
-
-[Data Storage]
-# Whether to create a virtual SD card.
-# 1: Yes, 0 (default): No
-use_virtual_sd =
-
-# Whether or not to enable gamecard emulation
-# 1: Yes, 0 (default): No
-gamecard_inserted =
-
-# Whether or not the gamecard should be emulated as the current game
-# If 'gamecard_inserted' is 0 this setting is irrelevant
-# 1: Yes, 0 (default): No
-gamecard_current_game =
-
-# Path to an XCI file to use as the gamecard
-# If 'gamecard_inserted' is 0 this setting is irrelevant
-# If 'gamecard_current_game' is 1 this setting is irrelevant
-gamecard_path =
-
-[System]
-# Whether the system is docked
-# 1 (default): Yes, 0: No
-use_docked_mode =
-
-# Sets the seed for the RNG generator built into the switch
-# rng_seed will be ignored and randomly generated if rng_seed_enabled is false
-rng_seed_enabled =
-rng_seed =
-
-# Sets the current time (in seconds since 12:00 AM Jan 1, 1970) that will be used by the time service
-# This will auto-increment, with the time set being the time the game is started
-# This override will only occur if custom_rtc_enabled is true, otherwise the current time is used
-custom_rtc_enabled =
-custom_rtc =
-
-# Sets the systems language index
-# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese,
-# 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French,
-# 14: Latin American Spanish, 15: Simplified Chinese, 16: Traditional Chinese, 17: Brazilian Portuguese
-language_index =
-
-# The system region that yuzu will use during emulation
-# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan
-region_index =
-
-# The system time zone that yuzu will use during emulation
-# 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone
-time_zone_index =
-
-# Sets the sound output mode.
-# 0: Mono, 1 (default): Stereo, 2: Surround
-sound_index =
-
-[Miscellaneous]
-# A filter which removes logs below a certain logging level.
-# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
-log_filter = *:Trace
-
-# Use developer keys
-# 0 (default): Disabled, 1: Enabled
-use_dev_keys =
-
-[Debugging]
-# Record frame time data, can be found in the log directory. Boolean value
-record_frame_times =
-# Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them
-dump_exefs=false
-# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
-dump_nso=false
-# Determines whether or not yuzu will save the filesystem access log.
-enable_fs_access_log=false
-# Enables verbose reporting services
-reporting_services =
-# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode
-# false: Retail/Normal Mode (default), true: Kiosk Mode
-quest_flag =
-# Determines whether debug asserts should be enabled, which will throw an exception on asserts.
-# false: Disabled (default), true: Enabled
-use_debug_asserts =
-# Determines whether unimplemented HLE service calls should be automatically stubbed.
-# false: Disabled (default), true: Enabled
-use_auto_stub =
-# Enables/Disables the macro JIT compiler
-disable_macro_jit=false
-# Determines whether to enable the GDB stub and wait for the debugger to attach before running.
-# false: Disabled (default), true: Enabled
-use_gdbstub=false
-# The port to use for the GDB server, if it is enabled.
-gdbstub_port=6543
-
-[WebService]
-# Whether or not to enable telemetry
-# 0: No, 1 (default): Yes
-enable_telemetry =
-# URL for Web API
-web_api_url = https://api.yuzu-emu.org
-# Username and token for yuzu Web Service
-# See https://profile.yuzu-emu.org/ for more info
-yuzu_username =
-yuzu_token =
-
-[Network]
-# Name of the network interface device to use with yuzu LAN play.
-# e.g. On *nix: 'enp7s0', 'wlp6s0u1u3u3', 'lo'
-# e.g. On Windows: 'Ethernet', 'Wi-Fi'
-network_interface =
-
-[AddOns]
-# Used to disable add-ons
-# List of title IDs of games that will have add-ons disabled (separated by '|'):
-title_ids =
-# 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 '|')
-# e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey
-)";
-} // 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 @@
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
+#include "frontend_common/config.h"
#include "jni/android_common/android_common.h"
-#include "jni/config.h"
#include "jni/id_cache.h"
#include "jni/native.h"
#include "video_core/renderer_base.h"
@@ -664,8 +664,6 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased(JNIEnv* env, jclass c
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz,
jboolean reload) {
- // Create the default config.ini.
- Config{};
// Initialize the emulated system.
if (!reload) {
EmulationSession::GetInstance().System().Initialize();
@@ -680,17 +678,6 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass cl
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2Ljava_lang_String_2Z(
JNIEnv* env, jclass clazz, jstring j_file, jstring j_savestate, jboolean j_delete_savestate) {}
-void Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadSettings(JNIEnv* env, jclass clazz) {
- Config{};
-}
-
-void Java_org_yuzu_yuzu_1emu_NativeLibrary_initGameIni(JNIEnv* env, jclass clazz,
- jstring j_game_id) {
- std::string_view game_id = env->GetStringUTFChars(j_game_id, 0);
-
- env->ReleaseStringUTFChars(j_game_id, game_id.data());
-}
-
jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jclass clazz) {
jdoubleArray j_stats = env->NewDoubleArray(4);
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 @@
#include <jni.h>
+#include "android_config.h"
+#include "android_settings.h"
#include "common/logging/log.h"
#include "common/settings.h"
+#include "frontend_common/config.h"
#include "jni/android_common/android_common.h"
-#include "jni/config.h"
-#include "uisettings.h"
+
+std::unique_ptr<AndroidConfig> config;
template <typename T>
Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
@@ -28,6 +31,22 @@ Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
extern "C" {
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_initializeConfig(JNIEnv* env, jobject obj) {
+ config = std::make_unique<AndroidConfig>();
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_unloadConfig(JNIEnv* env, jobject obj) {
+ config.reset();
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_reloadSettings(JNIEnv* env, jobject obj) {
+ config->AndroidConfig::ReloadAllValues();
+}
+
+void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_saveSettings(JNIEnv* env, jobject obj) {
+ config->AndroidConfig::SaveAllValues();
+}
+
jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getBoolean(JNIEnv* env, jobject obj,
jstring jkey, jboolean getDefault) {
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) {
case Category::UiAudio:
return "UiAudio";
case Category::UiLayout:
- return "UiLayout";
+ return "UILayout";
case Category::UiGameList:
- return "UiGameList";
+ return "UIGameList";
case Category::Screenshots:
return "Screenshots";
case Category::Shortcuts:
diff --git a/src/common/settings.h b/src/common/settings.h
index e899f1ae6..b929fd957 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -232,7 +232,11 @@ struct Values {
SwitchableSetting<bool> use_asynchronous_gpu_emulation{
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
+#ifdef ANDROID
+ AstcDecodeMode::Cpu,
+#else
AstcDecodeMode::Gpu,
+#endif
AstcDecodeMode::Cpu,
AstcDecodeMode::CpuAsynchronous,
"accelerate_astc",
@@ -304,7 +308,11 @@ struct Values {
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
+#ifdef ANDROID
+ GpuAccuracy::Normal,
+#else
GpuAccuracy::High,
+#endif
GpuAccuracy::Normal,
GpuAccuracy::Extreme,
"gpu_accuracy",
@@ -313,20 +321,38 @@ struct Values {
true,
true};
GpuAccuracy current_gpu_accuracy{GpuAccuracy::High};
- SwitchableSetting<AnisotropyMode, true> max_anisotropy{
- linkage, AnisotropyMode::Automatic, AnisotropyMode::Automatic, AnisotropyMode::X16,
- "max_anisotropy", Category::RendererAdvanced};
+ SwitchableSetting<AnisotropyMode, true> max_anisotropy{linkage,
+#ifdef ANDROID
+ AnisotropyMode::Default,
+#else
+ AnisotropyMode::Automatic,
+#endif
+ AnisotropyMode::Automatic,
+ AnisotropyMode::X16,
+ "max_anisotropy",
+ Category::RendererAdvanced};
SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
AstcRecompression::Uncompressed,
AstcRecompression::Uncompressed,
AstcRecompression::Bc3,
"astc_recompression",
Category::RendererAdvanced};
- SwitchableSetting<bool> async_presentation{linkage, false, "async_presentation",
- Category::RendererAdvanced};
+ SwitchableSetting<bool> async_presentation{linkage,
+#ifdef ANDROID
+ true,
+#else
+ false,
+#endif
+ "async_presentation", Category::RendererAdvanced};
SwitchableSetting<bool> renderer_force_max_clock{linkage, false, "force_max_clock",
Category::RendererAdvanced};
- SwitchableSetting<bool> use_reactive_flushing{linkage, true, "use_reactive_flushing",
+ SwitchableSetting<bool> use_reactive_flushing{linkage,
+#ifdef ANDROID
+ false,
+#else
+ true,
+#endif
+ "use_reactive_flushing",
Category::RendererAdvanced};
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
Category::RendererAdvanced};
@@ -358,6 +384,8 @@ struct Values {
Category::RendererDebug};
// TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control
bool renderer_amdvlk_depth_bias_workaround{};
+ Setting<bool> disable_buffer_reorder{linkage, false, "disable_buffer_reorder",
+ Category::RendererDebug};
// System
SwitchableSetting<Language, true> language_index{linkage,
@@ -390,7 +418,11 @@ struct Values {
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
+#ifdef ANDROID
+ ConsoleMode::Handheld,
+#else
ConsoleMode::Docked,
+#endif
"use_docked_mode",
Category::System,
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
hle/service/hid/hid_server.h
hle/service/hid/hid_system_server.cpp
hle/service/hid/hid_system_server.h
+ hle/service/hid/hid_util.h
hle/service/hid/hidbus.cpp
hle/service/hid/hidbus.h
hle/service/hid/irs.cpp
@@ -540,8 +541,8 @@ add_library(core STATIC
hle/service/hid/xcd.cpp
hle/service/hid/xcd.h
hle/service/hid/errors.h
- hle/service/hid/controllers/console_sixaxis.cpp
- hle/service/hid/controllers/console_sixaxis.h
+ hle/service/hid/controllers/console_six_axis.cpp
+ hle/service/hid/controllers/console_six_axis.h
hle/service/hid/controllers/controller_base.cpp
hle/service/hid/controllers/controller_base.h
hle/service/hid/controllers/debug_pad.cpp
@@ -556,6 +557,10 @@ add_library(core STATIC
hle/service/hid/controllers/npad.h
hle/service/hid/controllers/palma.cpp
hle/service/hid/controllers/palma.h
+ hle/service/hid/controllers/seven_six_axis.cpp
+ hle/service/hid/controllers/seven_six_axis.h
+ hle/service/hid/controllers/six_axis.cpp
+ hle/service/hid/controllers/six_axis.h
hle/service/hid/controllers/stubbed.cpp
hle/service/hid/controllers/stubbed.h
hle/service/hid/controllers/touchscreen.cpp
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 34927cddd..a6e681e15 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -8,6 +8,7 @@
#include "common/thread.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/input_converter.h"
+#include "core/hle/service/hid/hid_util.h"
namespace Core::HID {
constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
@@ -82,7 +83,7 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleInde
}
void EmulatedController::ReloadFromSettings() {
- const auto player_index = NpadIdTypeToIndex(npad_id_type);
+ const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
for (std::size_t index = 0; index < player.buttons.size(); ++index) {
@@ -118,7 +119,7 @@ void EmulatedController::ReloadFromSettings() {
}
void EmulatedController::ReloadColorsFromSettings() {
- const auto player_index = NpadIdTypeToIndex(npad_id_type);
+ const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
// Avoid updating colors if overridden by physical controller
@@ -215,7 +216,7 @@ void EmulatedController::LoadDevices() {
}
void EmulatedController::LoadTASParams() {
- const auto player_index = NpadIdTypeToIndex(npad_id_type);
+ const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
Common::ParamPackage common_params{};
common_params.Set("engine", "tas");
common_params.Set("port", static_cast<int>(player_index));
@@ -264,7 +265,7 @@ void EmulatedController::LoadTASParams() {
}
void EmulatedController::LoadVirtualGamepadParams() {
- const auto player_index = NpadIdTypeToIndex(npad_id_type);
+ const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
Common::ParamPackage common_params{};
common_params.Set("engine", "virtual_gamepad");
common_params.Set("port", static_cast<int>(player_index));
@@ -508,9 +509,11 @@ void EmulatedController::ReloadInput() {
});
}
turbo_button_state = 0;
+ is_initalized = true;
}
void EmulatedController::UnloadInput() {
+ is_initalized = false;
for (auto& button : button_devices) {
button.reset();
}
@@ -615,7 +618,7 @@ bool EmulatedController::IsConfiguring() const {
}
void EmulatedController::SaveCurrentConfig() {
- const auto player_index = NpadIdTypeToIndex(npad_id_type);
+ const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
auto& player = Settings::values.players.GetValue()[player_index];
player.connected = is_connected;
player.controller_type = MapNPadToSettingsType(npad_type);
@@ -1206,13 +1209,16 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
}
bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
+ if (!is_initalized) {
+ return false;
+ }
if (device_index >= output_devices.size()) {
return false;
}
if (!output_devices[device_index]) {
return false;
}
- const auto player_index = NpadIdTypeToIndex(npad_id_type);
+ const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f;
@@ -1238,9 +1244,13 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
}
bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
- const auto player_index = NpadIdTypeToIndex(npad_id_type);
+ const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
+ if (!is_initalized) {
+ return false;
+ }
+
if (!player.vibration_enabled) {
return false;
}
@@ -1260,6 +1270,10 @@ Common::Input::DriverResult EmulatedController::SetPollingMode(
EmulatedDeviceIndex device_index, Common::Input::PollingMode polling_mode) {
LOG_INFO(Service_HID, "Set polling mode {}, device_index={}", polling_mode, device_index);
+ if (!is_initalized) {
+ return Common::Input::DriverResult::InvalidHandle;
+ }
+
auto& left_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Left)];
auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
auto& nfc_output_device = output_devices[3];
@@ -1305,6 +1319,10 @@ bool EmulatedController::SetCameraFormat(
Core::IrSensor::ImageTransferProcessorFormat camera_format) {
LOG_INFO(Service_HID, "Set camera format {}", camera_format);
+ if (!is_initalized) {
+ return false;
+ }
+
auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
auto& camera_output_device = output_devices[2];
@@ -1328,6 +1346,11 @@ void EmulatedController::SetRingParam(Common::ParamPackage param) {
}
bool EmulatedController::HasNfc() const {
+
+ if (!is_initalized) {
+ return false;
+ }
+
const auto& nfc_output_device = output_devices[3];
switch (npad_type) {
@@ -1365,6 +1388,10 @@ bool EmulatedController::RemoveNfcHandle() {
}
bool EmulatedController::StartNfcPolling() {
+ if (!is_initalized) {
+ return false;
+ }
+
auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
auto& nfc_virtual_output_device = output_devices[3];
@@ -1376,6 +1403,10 @@ bool EmulatedController::StartNfcPolling() {
}
bool EmulatedController::StopNfcPolling() {
+ if (!is_initalized) {
+ return false;
+ }
+
auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
auto& nfc_virtual_output_device = output_devices[3];
@@ -1387,6 +1418,10 @@ bool EmulatedController::StopNfcPolling() {
}
bool EmulatedController::ReadAmiiboData(std::vector<u8>& data) {
+ if (!is_initalized) {
+ return false;
+ }
+
auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
auto& nfc_virtual_output_device = output_devices[3];
@@ -1399,6 +1434,10 @@ bool EmulatedController::ReadAmiiboData(std::vector<u8>& data) {
bool EmulatedController::ReadMifareData(const Common::Input::MifareRequest& request,
Common::Input::MifareRequest& out_data) {
+ if (!is_initalized) {
+ return false;
+ }
+
auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
auto& nfc_virtual_output_device = output_devices[3];
@@ -1411,6 +1450,10 @@ bool EmulatedController::ReadMifareData(const Common::Input::MifareRequest& requ
}
bool EmulatedController::WriteMifareData(const Common::Input::MifareRequest& request) {
+ if (!is_initalized) {
+ return false;
+ }
+
auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
auto& nfc_virtual_output_device = output_devices[3];
@@ -1422,6 +1465,10 @@ bool EmulatedController::WriteMifareData(const Common::Input::MifareRequest& req
}
bool EmulatedController::WriteNfc(const std::vector<u8>& data) {
+ if (!is_initalized) {
+ return false;
+ }
+
auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
auto& nfc_virtual_output_device = output_devices[3];
@@ -1433,6 +1480,10 @@ bool EmulatedController::WriteNfc(const std::vector<u8>& data) {
}
void EmulatedController::SetLedPattern() {
+ if (!is_initalized) {
+ return;
+ }
+
for (auto& device : output_devices) {
if (!device) {
continue;
@@ -1648,7 +1699,7 @@ void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
}
if (is_connected) {
LOG_WARNING(Service_HID, "Controller {} type changed while it's connected",
- NpadIdTypeToIndex(npad_id_type));
+ Service::HID::NpadIdTypeToIndex(npad_id_type));
}
npad_type = npad_type_;
}
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index ea18c2343..d6e20ab66 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -559,6 +559,7 @@ private:
NpadStyleTag supported_style_tag{NpadStyleSet::All};
bool is_connected{false};
bool is_configuring{false};
+ bool is_initalized{false};
bool system_buttons_enabled{true};
f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};
u32 turbo_button_state{0};
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 @@
#include "core/hid/emulated_controller.h"
#include "core/hid/emulated_devices.h"
#include "core/hid/hid_core.h"
+#include "core/hle/service/hid/hid_util.h"
namespace Core::HID {
@@ -98,11 +99,11 @@ const EmulatedDevices* HIDCore::GetEmulatedDevices() const {
}
EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) {
- return GetEmulatedController(IndexToNpadIdType(index));
+ return GetEmulatedController(Service::HID::IndexToNpadIdType(index));
}
const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) const {
- return GetEmulatedController(IndexToNpadIdType(index));
+ return GetEmulatedController(Service::HID::IndexToNpadIdType(index));
}
void 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 @@
#include "common/common_types.h"
#include "common/point.h"
#include "common/uuid.h"
+#include "common/vector_math.h"
namespace Core::HID {
@@ -598,6 +599,29 @@ struct SixAxisSensorIcInformation {
static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8,
"SixAxisSensorIcInformation is an invalid size");
+// This is nn::hid::SixAxisSensorAttribute
+struct SixAxisSensorAttribute {
+ union {
+ u32 raw{};
+ BitField<0, 1, u32> is_connected;
+ BitField<1, 1, u32> is_interpolated;
+ };
+};
+static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size");
+
+// This is nn::hid::SixAxisSensorState
+struct SixAxisSensorState {
+ s64 delta_time{};
+ s64 sampling_number{};
+ Common::Vec3f accel{};
+ Common::Vec3f gyro{};
+ Common::Vec3f rotation{};
+ std::array<Common::Vec3f, 3> orientation{};
+ SixAxisSensorAttribute attribute{};
+ INSERT_PADDING_BYTES(4); // Reserved
+};
+static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size");
+
// This is nn::hid::VibrationDeviceHandle
struct VibrationDeviceHandle {
NpadStyleIndex npad_type{NpadStyleIndex::None};
@@ -708,60 +732,4 @@ struct UniquePadId {
};
static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size");
-/// Converts a NpadIdType to an array index.
-constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
- switch (npad_id_type) {
- case NpadIdType::Player1:
- return 0;
- case NpadIdType::Player2:
- return 1;
- case NpadIdType::Player3:
- return 2;
- case NpadIdType::Player4:
- return 3;
- case NpadIdType::Player5:
- return 4;
- case NpadIdType::Player6:
- return 5;
- case NpadIdType::Player7:
- return 6;
- case NpadIdType::Player8:
- return 7;
- case NpadIdType::Handheld:
- return 8;
- case NpadIdType::Other:
- return 9;
- default:
- return 0;
- }
-}
-
-/// Converts an array index to a NpadIdType
-constexpr NpadIdType IndexToNpadIdType(size_t index) {
- switch (index) {
- case 0:
- return NpadIdType::Player1;
- case 1:
- return NpadIdType::Player2;
- case 2:
- return NpadIdType::Player3;
- case 3:
- return NpadIdType::Player4;
- case 4:
- return NpadIdType::Player5;
- case 5:
- return NpadIdType::Player6;
- case 6:
- return NpadIdType::Player7;
- case 7:
- return NpadIdType::Player8;
- case 8:
- return NpadIdType::Handheld;
- case 9:
- return NpadIdType::Other;
- default:
- return NpadIdType::Invalid;
- }
-}
-
} // 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)
: npad{system.ServiceManager()
.GetService<Service::HID::IHidServer>("hid")
->GetResourceManager()
- ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {
+ ->GetNpad()} {
ResetButtonStates();
}
InputInterpreter::~InputInterpreter() = default;
void InputInterpreter::PollInput() {
- const auto button_state = npad.GetAndResetPressState();
+ const auto button_state = npad->GetAndResetPressState();
previous_index = current_index;
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;
}
namespace Service::HID {
-class Controller_NPad;
+class NPad;
}
/**
@@ -101,7 +101,7 @@ public:
}
private:
- Service::HID::Controller_NPad& npad;
+ std::shared_ptr<Service::HID::NPad> npad;
/// Stores 9 consecutive button states polled from HID.
std::array<Core::HID::NpadButton, 9> button_states{};
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp
index b379dadeb..9d1960cb7 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.cpp
+++ b/src/core/hle/service/am/applets/applet_cabinet.cpp
@@ -122,7 +122,8 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)
Service::NFP::RegisterInfoPrivate register_info{};
std::memcpy(register_info.amiibo_name.data(), amiibo_name.data(),
std::min(amiibo_name.size(), register_info.amiibo_name.size() - 1));
-
+ register_info.mii_store_data.BuildRandom(Mii::Age::All, Mii::Gender::All, Mii::Race::All);
+ register_info.mii_store_data.SetNickname({u'y', u'u', u'z', u'u'});
nfp_device->SetRegisterInfoPrivate(register_info);
break;
}
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 @@
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/core_timing.h"
+#include "core/hid/emulated_console.h"
+#include "core/hid/hid_core.h"
+#include "core/hle/service/hid/controllers/console_six_axis.h"
+#include "core/memory.h"
+
+namespace Service::HID {
+constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
+
+ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
+ : ControllerBase{hid_core_} {
+ console = hid_core.GetEmulatedConsole();
+ static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
+ "ConsoleSharedMemory is bigger than the shared memory");
+ shared_memory = std::construct_at(
+ reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
+}
+
+ConsoleSixAxis::~ConsoleSixAxis() = default;
+
+void ConsoleSixAxis::OnInit() {}
+
+void ConsoleSixAxis::OnRelease() {}
+
+void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+ if (!IsControllerActivated()) {
+ return;
+ }
+
+ const auto motion_status = console->GetMotion();
+
+ shared_memory->sampling_number++;
+ shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
+ shared_memory->verticalization_error = motion_status.verticalization_error;
+ shared_memory->gyro_bias = motion_status.gyro_bias;
+}
+
+} // 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 @@
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/vector_math.h"
+#include "core/hle/service/hid/controllers/controller_base.h"
+
+namespace Core::HID {
+class EmulatedConsole;
+} // namespace Core::HID
+
+namespace Service::HID {
+class ConsoleSixAxis final : public ControllerBase {
+public:
+ explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ ~ConsoleSixAxis() override;
+
+ // Called when the controller is initialized
+ void OnInit() override;
+
+ // When the controller is released
+ void OnRelease() override;
+
+ // When the controller is requesting an update for the shared memory
+ void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
+
+private:
+ // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
+ struct ConsoleSharedMemory {
+ u64 sampling_number{};
+ bool is_seven_six_axis_sensor_at_rest{};
+ INSERT_PADDING_BYTES(3); // padding
+ f32 verticalization_error{};
+ Common::Vec3f gyro_bias{};
+ INSERT_PADDING_BYTES(4); // padding
+ };
+ static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
+
+ ConsoleSharedMemory* shared_memory = nullptr;
+ Core::HID::EmulatedConsole* console = nullptr;
+};
+} // 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 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
-Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
+DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
"DebugPadSharedMemory is bigger than the shared memory");
@@ -22,13 +22,13 @@ Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
}
-Controller_DebugPad::~Controller_DebugPad() = default;
+DebugPad::~DebugPad() = default;
-void Controller_DebugPad::OnInit() {}
+void DebugPad::OnInit() {}
-void Controller_DebugPad::OnRelease() {}
+void DebugPad::OnRelease() {}
-void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->debug_pad_lifo.buffer_count = 0;
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;
} // namespace Core::HID
namespace Service::HID {
-class Controller_DebugPad final : public ControllerBase {
+class DebugPad final : public ControllerBase {
public:
- explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
- ~Controller_DebugPad() override;
+ explicit DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ ~DebugPad() override;
// Called when the controller is initialized
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) {
return static_cast<f32>(num * num);
}
-Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
+Gesture::Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase(hid_core_) {
static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
"GestureSharedMemory is bigger than the shared memory");
@@ -31,17 +31,17 @@ Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_sh
reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
console = hid_core.GetEmulatedConsole();
}
-Controller_Gesture::~Controller_Gesture() = default;
+Gesture::~Gesture() = default;
-void Controller_Gesture::OnInit() {
+void Gesture::OnInit() {
shared_memory->gesture_lifo.buffer_count = 0;
shared_memory->gesture_lifo.buffer_tail = 0;
force_update = true;
}
-void Controller_Gesture::OnRelease() {}
+void Gesture::OnRelease() {}
-void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->gesture_lifo.buffer_count = 0;
shared_memory->gesture_lifo.buffer_tail = 0;
@@ -64,7 +64,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
UpdateGestureSharedMemory(gesture, time_difference);
}
-void Controller_Gesture::ReadTouchInput() {
+void Gesture::ReadTouchInput() {
if (!Settings::values.touchscreen.enabled) {
fingers = {};
return;
@@ -76,8 +76,7 @@ void Controller_Gesture::ReadTouchInput() {
}
}
-bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
- f32 time_difference) {
+bool Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
if (force_update) {
force_update = false;
@@ -100,8 +99,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
return false;
}
-void Controller_Gesture::UpdateGestureSharedMemory(GestureProperties& gesture,
- f32 time_difference) {
+void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference) {
GestureType type = GestureType::Idle;
GestureAttribute attributes{};
@@ -138,8 +136,8 @@ void Controller_Gesture::UpdateGestureSharedMemory(GestureProperties& gesture,
shared_memory->gesture_lifo.WriteNextEntry(next_state);
}
-void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
- GestureAttribute& attributes) {
+void Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
+ GestureAttribute& attributes) {
const auto& last_entry = GetLastGestureEntry();
gesture.detection_count++;
@@ -152,8 +150,8 @@ void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& typ
}
}
-void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
- f32 time_difference) {
+void Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
+ f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
// Promote to pan type if touch moved
@@ -186,9 +184,8 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Gestu
}
}
-void Controller_Gesture::EndGesture(GestureProperties& gesture,
- GestureProperties& last_gesture_props, GestureType& type,
- GestureAttribute& attributes, f32 time_difference) {
+void Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props,
+ GestureType& type, GestureAttribute& attributes, f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
if (last_gesture_props.active_points != 0) {
@@ -222,9 +219,8 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture,
}
}
-void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
- GestureProperties& last_gesture_props, GestureType& type,
- GestureAttribute& attributes) {
+void Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
+ GestureType& type, GestureAttribute& attributes) {
type = GestureType::Tap;
gesture = last_gesture_props;
force_update = true;
@@ -236,9 +232,8 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
}
}
-void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
- GestureProperties& last_gesture_props, GestureType& type,
- f32 time_difference) {
+void Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
+ GestureType& type, f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
next_state.delta = gesture.mid_point - last_entry.pos;
@@ -263,9 +258,8 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
}
}
-void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
- GestureProperties& last_gesture_props, GestureType& type,
- f32 time_difference) {
+void Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
+ GestureType& type, f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
next_state.vel_x =
static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference);
@@ -287,8 +281,8 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
force_update = true;
}
-void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
- GestureProperties& last_gesture_props, GestureType& type) {
+void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
+ GestureType& type) {
const auto& last_entry = GetLastGestureEntry();
type = GestureType::Swipe;
@@ -311,11 +305,11 @@ void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
next_state.direction = GestureDirection::Up;
}
-const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const {
+const Gesture::GestureState& Gesture::GetLastGestureEntry() const {
return shared_memory->gesture_lifo.ReadCurrentEntry().state;
}
-Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {
+Gesture::GestureProperties Gesture::GetGestureProperties() {
GestureProperties gesture;
std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
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 @@
#include "core/hle/service/hid/ring_lifo.h"
namespace Service::HID {
-class Controller_Gesture final : public ControllerBase {
+class Gesture final : public ControllerBase {
public:
- explicit Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
- ~Controller_Gesture() override;
+ explicit Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ ~Gesture() override;
// Called when the controller is initialized
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 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
-Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
+Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
"KeyboardSharedMemory is bigger than the shared memory");
@@ -21,13 +21,13 @@ Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_
emulated_devices = hid_core.GetEmulatedDevices();
}
-Controller_Keyboard::~Controller_Keyboard() = default;
+Keyboard::~Keyboard() = default;
-void Controller_Keyboard::OnInit() {}
+void Keyboard::OnInit() {}
-void Controller_Keyboard::OnRelease() {}
+void Keyboard::OnRelease() {}
-void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->keyboard_lifo.buffer_count = 0;
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;
} // namespace Core::HID
namespace Service::HID {
-class Controller_Keyboard final : public ControllerBase {
+class Keyboard final : public ControllerBase {
public:
- explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
- ~Controller_Keyboard() override;
+ explicit Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ ~Keyboard() override;
// Called when the controller is initialized
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 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
-Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
- : ControllerBase{hid_core_} {
+Mouse::Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size,
"MouseSharedMemory is bigger than the shared memory");
shared_memory = std::construct_at(
@@ -21,12 +20,12 @@ Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared
emulated_devices = hid_core.GetEmulatedDevices();
}
-Controller_Mouse::~Controller_Mouse() = default;
+Mouse::~Mouse() = default;
-void Controller_Mouse::OnInit() {}
-void Controller_Mouse::OnRelease() {}
+void Mouse::OnInit() {}
+void Mouse::OnRelease() {}
-void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->mouse_lifo.buffer_count = 0;
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;
} // namespace Core::HID
namespace Service::HID {
-class Controller_Mouse final : public ControllerBase {
+class Mouse final : public ControllerBase {
public:
- explicit Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
- ~Controller_Mouse() override;
+ explicit Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ ~Mouse() override;
// Called when the controller is initialized
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 @@
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/errors.h"
+#include "core/hle/service/hid/hid_util.h"
#include "core/hle/service/kernel_helpers.h"
namespace Service::HID {
@@ -29,60 +30,8 @@ constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
Core::HID::NpadIdType::Handheld,
};
-bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) {
- switch (npad_id) {
- case Core::HID::NpadIdType::Player1:
- case Core::HID::NpadIdType::Player2:
- case Core::HID::NpadIdType::Player3:
- case Core::HID::NpadIdType::Player4:
- case Core::HID::NpadIdType::Player5:
- case Core::HID::NpadIdType::Player6:
- case Core::HID::NpadIdType::Player7:
- case Core::HID::NpadIdType::Player8:
- case Core::HID::NpadIdType::Other:
- case Core::HID::NpadIdType::Handheld:
- return true;
- default:
- LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
- return false;
- }
-}
-
-Result Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
- const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
- const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
- const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
-
- if (!npad_type) {
- return VibrationInvalidStyleIndex;
- }
- if (!npad_id) {
- return VibrationInvalidNpadId;
- }
- if (!device_index) {
- return VibrationDeviceIndexOutOfRange;
- }
-
- return ResultSuccess;
-}
-
-Result Controller_NPad::VerifyValidSixAxisSensorHandle(
- const Core::HID::SixAxisSensorHandle& device_handle) {
- const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
- const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
-
- if (!npad_id) {
- return InvalidNpadId;
- }
- if (!device_index) {
- return NpadDeviceIndexOutOfRange;
- }
-
- return ResultSuccess;
-}
-
-Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
- KernelHelpers::ServiceContext& service_context_)
+NPad::NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
+ KernelHelpers::ServiceContext& service_context_)
: ControllerBase{hid_core_}, service_context{service_context_} {
static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
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
}
}
-Controller_NPad::~Controller_NPad() {
+NPad::~NPad() {
for (std::size_t i = 0; i < controller_data.size(); ++i) {
auto& controller = controller_data[i];
controller.device->DeleteCallback(controller.callback_key);
@@ -111,8 +60,7 @@ Controller_NPad::~Controller_NPad() {
OnRelease();
}
-void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
- std::size_t controller_idx) {
+void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) {
if (type == Core::HID::ControllerTriggerType::All) {
ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
@@ -150,7 +98,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
}
}
-void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
+void NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
auto& controller = GetControllerFromNpadIdType(npad_id);
if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) {
return;
@@ -350,7 +298,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
hid_core.SetLastActiveController(npad_id);
}
-void Controller_NPad::OnInit() {
+void NPad::OnInit() {
if (!IsControllerActivated()) {
return;
}
@@ -384,7 +332,7 @@ void Controller_NPad::OnInit() {
}
}
-void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) {
+void NPad::WriteEmptyEntry(NpadInternalState* npad) {
NPadGenericState dummy_pad_state{};
NpadGcTriggerState dummy_gc_state{};
dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
@@ -405,7 +353,7 @@ void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) {
npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
}
-void Controller_NPad::OnRelease() {
+void NPad::OnRelease() {
is_controller_initialized = false;
for (std::size_t i = 0; i < controller_data.size(); ++i) {
auto& controller = controller_data[i];
@@ -416,7 +364,7 @@ void Controller_NPad::OnRelease() {
}
}
-void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
+void NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
std::scoped_lock lock{mutex};
auto& controller = GetControllerFromNpadIdType(npad_id);
const auto controller_type = controller.device->GetNpadStyleIndex();
@@ -485,7 +433,7 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
}
}
-void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
return;
}
@@ -615,134 +563,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
}
}
-void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {
- if (!IsControllerActivated()) {
- return;
- }
-
- for (std::size_t i = 0; i < controller_data.size(); ++i) {
- auto& controller = controller_data[i];
-
- const auto& controller_type = controller.device->GetNpadStyleIndex();
-
- if (controller_type == Core::HID::NpadStyleIndex::None ||
- !controller.device->IsConnected()) {
- continue;
- }
-
- auto* npad = controller.shared_memory;
- const auto& motion_state = controller.device->GetMotions();
- auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
- auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
- auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
- auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
- auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
- auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
-
- // Clear previous state
- sixaxis_fullkey_state = {};
- sixaxis_handheld_state = {};
- sixaxis_dual_left_state = {};
- sixaxis_dual_right_state = {};
- sixaxis_left_lifo_state = {};
- sixaxis_right_lifo_state = {};
-
- if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
- controller.sixaxis_at_rest = true;
- for (std::size_t e = 0; e < motion_state.size(); ++e) {
- controller.sixaxis_at_rest =
- controller.sixaxis_at_rest && motion_state[e].is_at_rest;
- }
- }
-
- const auto set_motion_state = [&](SixAxisSensorState& state,
- const Core::HID::ControllerMotion& hid_state) {
- using namespace std::literals::chrono_literals;
- static constexpr SixAxisSensorState default_motion_state = {
- .delta_time = std::chrono::nanoseconds(5ms).count(),
- .accel = {0, 0, -1.0f},
- .orientation =
- {
- Common::Vec3f{1.0f, 0, 0},
- Common::Vec3f{0, 1.0f, 0},
- Common::Vec3f{0, 0, 1.0f},
- },
- .attribute = {1},
- };
- if (!controller.sixaxis_sensor_enabled) {
- state = default_motion_state;
- return;
- }
- if (!Settings::values.motion_enabled.GetValue()) {
- state = default_motion_state;
- return;
- }
- state.attribute.is_connected.Assign(1);
- state.delta_time = std::chrono::nanoseconds(5ms).count();
- state.accel = hid_state.accel;
- state.gyro = hid_state.gyro;
- state.rotation = hid_state.rotation;
- state.orientation = hid_state.orientation;
- };
-
- switch (controller_type) {
- case Core::HID::NpadStyleIndex::None:
- ASSERT(false);
- break;
- case Core::HID::NpadStyleIndex::ProController:
- set_motion_state(sixaxis_fullkey_state, motion_state[0]);
- break;
- case Core::HID::NpadStyleIndex::Handheld:
- set_motion_state(sixaxis_handheld_state, motion_state[0]);
- break;
- case Core::HID::NpadStyleIndex::JoyconDual:
- set_motion_state(sixaxis_dual_left_state, motion_state[0]);
- set_motion_state(sixaxis_dual_right_state, motion_state[1]);
- break;
- case Core::HID::NpadStyleIndex::JoyconLeft:
- set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
- break;
- case Core::HID::NpadStyleIndex::JoyconRight:
- set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
- break;
- case Core::HID::NpadStyleIndex::Pokeball:
- using namespace std::literals::chrono_literals;
- set_motion_state(sixaxis_fullkey_state, motion_state[0]);
- sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
- break;
- default:
- break;
- }
-
- sixaxis_fullkey_state.sampling_number =
- npad->sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
- sixaxis_handheld_state.sampling_number =
- npad->sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
- sixaxis_dual_left_state.sampling_number =
- npad->sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
- sixaxis_dual_right_state.sampling_number =
- npad->sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
- sixaxis_left_lifo_state.sampling_number =
- npad->sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
- sixaxis_right_lifo_state.sampling_number =
- npad->sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
-
- if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
- // This buffer only is updated on handheld on HW
- npad->sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
- } else {
- // Handheld doesn't update this buffer on HW
- npad->sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
- }
-
- npad->sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
- npad->sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
- npad->sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
- npad->sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
- }
-}
-
-void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
+void NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
hid_core.SetSupportedStyleTag(style_set);
if (is_controller_initialized) {
@@ -753,14 +574,14 @@ void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
is_controller_initialized = true;
}
-Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
+Core::HID::NpadStyleTag NPad::GetSupportedStyleSet() const {
if (!is_controller_initialized) {
return {Core::HID::NpadStyleSet::None};
}
return hid_core.GetSupportedStyleTag();
}
-Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
+Result NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
constexpr std::size_t max_number_npad_ids = 0xa;
const auto length = data.size();
ASSERT(length > 0 && (length % sizeof(u32)) == 0);
@@ -776,17 +597,17 @@ Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
return ResultSuccess;
}
-void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
+void NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
const auto copy_amount = supported_npad_id_types.size() * sizeof(u32);
ASSERT(max_length <= copy_amount);
std::memcpy(data, supported_npad_id_types.data(), copy_amount);
}
-std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
+std::size_t NPad::GetSupportedNpadIdTypesSize() const {
return supported_npad_id_types.size();
}
-void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
+void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
if (joy_hold_type != NpadJoyHoldType::Horizontal &&
joy_hold_type != NpadJoyHoldType::Vertical) {
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) {
hold_type = joy_hold_type;
}
-Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
+NPad::NpadJoyHoldType NPad::GetHoldType() const {
return hold_type;
}
-void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
+void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) {
ASSERT_MSG(false, "Activation mode should be always None, Single or Dual");
return;
@@ -809,21 +630,20 @@ void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode a
handheld_activation_mode = activation_mode;
}
-Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
+NPad::NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
return handheld_activation_mode;
}
-void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
+void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
communication_mode = communication_mode_;
}
-Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const {
+NPad::NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
return communication_mode;
}
-bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
- NpadJoyDeviceType npad_device_type,
- NpadJoyAssignmentMode assignment_mode) {
+bool NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
+ NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return false;
@@ -892,9 +712,8 @@ bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID:
return true;
}
-bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
- std::size_t device_index,
- const Core::HID::VibrationValue& vibration_value) {
+bool NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
+ const Core::HID::VibrationValue& vibration_value) {
auto& controller = GetControllerFromNpadIdType(npad_id);
if (!controller.device->IsConnected()) {
return false;
@@ -938,10 +757,9 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
return controller.device->SetVibration(device_index, vibration);
}
-void Controller_NPad::VibrateController(
- const Core::HID::VibrationDeviceHandle& vibration_device_handle,
- const Core::HID::VibrationValue& vibration_value) {
- if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
+void NPad::VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle,
+ const Core::HID::VibrationValue& vibration_value) {
+ if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
return;
}
@@ -985,7 +803,7 @@ void Controller_NPad::VibrateController(
}
}
-void Controller_NPad::VibrateControllers(
+void NPad::VibrateControllers(
std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
std::span<const Core::HID::VibrationValue> vibration_values) {
if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
@@ -1002,9 +820,9 @@ void Controller_NPad::VibrateControllers(
}
}
-Core::HID::VibrationValue Controller_NPad::GetLastVibration(
+Core::HID::VibrationValue NPad::GetLastVibration(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
- if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
+ if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
return {};
}
@@ -1013,9 +831,9 @@ Core::HID::VibrationValue Controller_NPad::GetLastVibration(
return controller.vibration[device_index].latest_vibration_value;
}
-void Controller_NPad::InitializeVibrationDevice(
+void NPad::InitializeVibrationDevice(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
- if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
+ if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
return;
}
@@ -1024,8 +842,8 @@ void Controller_NPad::InitializeVibrationDevice(
InitializeVibrationDeviceAtIndex(npad_index, device_index);
}
-void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
- std::size_t device_index) {
+void NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
+ std::size_t device_index) {
auto& controller = GetControllerFromNpadIdType(npad_id);
if (!Settings::values.vibration_enabled.GetValue()) {
controller.vibration[device_index].device_mounted = false;
@@ -1036,13 +854,13 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npa
controller.device->IsVibrationEnabled(device_index);
}
-void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
+void NPad::SetPermitVibrationSession(bool permit_vibration_session) {
permit_vibration_session_enabled = permit_vibration_session;
}
-bool Controller_NPad::IsVibrationDeviceMounted(
+bool NPad::IsVibrationDeviceMounted(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
- if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
+ if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
return false;
}
@@ -1051,7 +869,7 @@ bool Controller_NPad::IsVibrationDeviceMounted(
return controller.vibration[device_index].device_mounted;
}
-Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
+Kernel::KReadableEvent& NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
// Fallback to player 1
@@ -1063,18 +881,17 @@ Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::Npad
return controller.styleset_changed_event->GetReadableEvent();
}
-void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
+void NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
const auto& controller = GetControllerFromNpadIdType(npad_id);
controller.styleset_changed_event->Signal();
}
-void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller,
- Core::HID::NpadIdType npad_id) {
+void NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id) {
UpdateControllerAt(controller, npad_id, true);
}
-void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
- Core::HID::NpadIdType npad_id, bool connected) {
+void NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, Core::HID::NpadIdType npad_id,
+ bool connected) {
auto& controller = GetControllerFromNpadIdType(npad_id);
if (!connected) {
DisconnectNpad(npad_id);
@@ -1085,7 +902,7 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
InitNewlyAddedController(npad_id);
}
-Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
+Result NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return InvalidNpadId;
@@ -1134,54 +951,9 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
return ResultSuccess;
}
-Result Controller_NPad::SetGyroscopeZeroDriftMode(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::GyroscopeZeroDriftMode drift_mode) {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- auto& sixaxis = GetSixaxisState(sixaxis_handle);
- auto& controller = GetControllerFromHandle(sixaxis_handle);
- sixaxis.gyroscope_zero_drift_mode = drift_mode;
- controller.device->SetGyroscopeZeroDriftMode(drift_mode);
-
- return ResultSuccess;
-}
-
-Result Controller_NPad::GetGyroscopeZeroDriftMode(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- const auto& sixaxis = GetSixaxisState(sixaxis_handle);
- drift_mode = sixaxis.gyroscope_zero_drift_mode;
-
- return ResultSuccess;
-}
-
-Result Controller_NPad::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- bool& is_at_rest) const {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- const auto& controller = GetControllerFromHandle(sixaxis_handle);
- is_at_rest = controller.sixaxis_at_rest;
- return ResultSuccess;
-}
-
-Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
+Result NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
@@ -1192,65 +964,9 @@ Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
return ResultSuccess;
}
-Result Controller_NPad::EnableSixAxisSensorUnalteredPassthrough(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- auto& sixaxis = GetSixaxisState(sixaxis_handle);
- sixaxis.unaltered_passtrough = is_enabled;
- return ResultSuccess;
-}
-
-Result Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- const auto& sixaxis = GetSixaxisState(sixaxis_handle);
- is_enabled = sixaxis.unaltered_passtrough;
- return ResultSuccess;
-}
-
-Result Controller_NPad::LoadSixAxisSensorCalibrationParameter(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- // TODO: Request this data to the controller. On error return 0xd8ca
- const auto& sixaxis = GetSixaxisState(sixaxis_handle);
- calibration = sixaxis.calibration;
- return ResultSuccess;
-}
-
-Result Controller_NPad::GetSixAxisSensorIcInformation(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::SixAxisSensorIcInformation& ic_information) const {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- // TODO: Request this data to the controller. On error return 0xd8ca
- const auto& sixaxis = GetSixaxisState(sixaxis_handle);
- ic_information = sixaxis.ic_information;
- return ResultSuccess;
-}
-
-Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
+Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
@@ -1262,83 +978,32 @@ Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
return ResultSuccess;
}
-Result Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- bool sixaxis_status) {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- auto& controller = GetControllerFromHandle(sixaxis_handle);
- controller.sixaxis_sensor_enabled = sixaxis_status;
- return ResultSuccess;
+NPad::SixAxisLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
+ return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo;
}
-Result Controller_NPad::IsSixAxisSensorFusionEnabled(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- const auto& sixaxis = GetSixaxisState(sixaxis_handle);
- is_fusion_enabled = sixaxis.is_fusion_enabled;
-
- return ResultSuccess;
+NPad::SixAxisLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
+ return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo;
}
-Result Controller_NPad::SetSixAxisFusionEnabled(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
- auto& sixaxis = GetSixaxisState(sixaxis_handle);
- sixaxis.is_fusion_enabled = is_fusion_enabled;
-
- return ResultSuccess;
+NPad::SixAxisLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
+ return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo;
}
-Result Controller_NPad::SetSixAxisFusionParameters(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- const auto param1 = sixaxis_fusion_parameters.parameter1;
- if (param1 < 0.0f || param1 > 1.0f) {
- return InvalidSixAxisFusionRange;
- }
-
- auto& sixaxis = GetSixaxisState(sixaxis_handle);
- sixaxis.fusion = sixaxis_fusion_parameters;
-
- return ResultSuccess;
+NPad::SixAxisLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
+ return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo;
}
-Result Controller_NPad::GetSixAxisFusionParameters(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::SixAxisSensorFusionParameters& parameters) const {
- const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
- if (is_valid.IsError()) {
- LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
- return is_valid;
- }
-
- const auto& sixaxis = GetSixaxisState(sixaxis_handle);
- parameters = sixaxis.fusion;
+NPad::SixAxisLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
+ return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo;
+}
- return ResultSuccess;
+NPad::SixAxisLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
+ return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo;
}
-Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
- Core::HID::NpadIdType npad_id_2) {
+Result NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
+ Core::HID::NpadIdType npad_id_2) {
if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
npad_id_2);
@@ -1400,18 +1065,17 @@ Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
return ResultSuccess;
}
-void Controller_NPad::StartLRAssignmentMode() {
+void NPad::StartLRAssignmentMode() {
// Nothing internally is used for lr assignment mode. Since we have the ability to set the
// controller types from boot, it doesn't really matter about showing a selection screen
is_in_lr_assignment_mode = true;
}
-void Controller_NPad::StopLRAssignmentMode() {
+void NPad::StopLRAssignmentMode() {
is_in_lr_assignment_mode = false;
}
-Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
- Core::HID::NpadIdType npad_id_2) {
+Result NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2) {
if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
npad_id_2);
@@ -1442,8 +1106,7 @@ Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
return ResultSuccess;
}
-Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
- Core::HID::LedPattern& pattern) const {
+Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return InvalidNpadId;
@@ -1453,8 +1116,8 @@ Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
return ResultSuccess;
}
-Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
- bool& is_valid) const {
+Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
+ bool& is_valid) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return InvalidNpadId;
@@ -1464,8 +1127,8 @@ Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::
return ResultSuccess;
}
-Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
- bool is_protection_enabled, Core::HID::NpadIdType npad_id) {
+Result NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
+ Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return InvalidNpadId;
@@ -1475,11 +1138,11 @@ Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
return ResultSuccess;
}
-void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
+void NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
analog_stick_use_center_clamp = use_center_clamp;
}
-void Controller_NPad::ClearAllConnectedControllers() {
+void NPad::ClearAllConnectedControllers() {
for (auto& controller : controller_data) {
if (controller.device->IsConnected() &&
controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
@@ -1489,13 +1152,13 @@ void Controller_NPad::ClearAllConnectedControllers() {
}
}
-void Controller_NPad::DisconnectAllConnectedControllers() {
+void NPad::DisconnectAllConnectedControllers() {
for (auto& controller : controller_data) {
controller.device->Disconnect();
}
}
-void Controller_NPad::ConnectAllDisconnectedControllers() {
+void NPad::ConnectAllDisconnectedControllers() {
for (auto& controller : controller_data) {
if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
!controller.device->IsConnected()) {
@@ -1504,18 +1167,18 @@ void Controller_NPad::ConnectAllDisconnectedControllers() {
}
}
-void Controller_NPad::ClearAllControllers() {
+void NPad::ClearAllControllers() {
for (auto& controller : controller_data) {
controller.device->Disconnect();
controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
}
}
-Core::HID::NpadButton Controller_NPad::GetAndResetPressState() {
+Core::HID::NpadButton NPad::GetAndResetPressState() {
return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
}
-void Controller_NPad::ApplyNpadSystemCommonPolicy() {
+void NPad::ApplyNpadSystemCommonPolicy() {
Core::HID::NpadStyleTag styletag{};
styletag.fullkey.Assign(1);
styletag.handheld.Assign(1);
@@ -1540,7 +1203,7 @@ void Controller_NPad::ApplyNpadSystemCommonPolicy() {
supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld;
}
-bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
+bool NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
if (controller == Core::HID::NpadStyleIndex::Handheld) {
const bool support_handheld =
std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
@@ -1591,51 +1254,50 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
return false;
}
-Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
- const Core::HID::SixAxisSensorHandle& device_handle) {
+NPad::NpadControllerData& NPad::GetControllerFromHandle(
+ const Core::HID::VibrationDeviceHandle& device_handle) {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
-const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
- const Core::HID::SixAxisSensorHandle& device_handle) const {
+const NPad::NpadControllerData& NPad::GetControllerFromHandle(
+ const Core::HID::VibrationDeviceHandle& device_handle) const {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
-Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
- const Core::HID::VibrationDeviceHandle& device_handle) {
+NPad::NpadControllerData& NPad::GetControllerFromHandle(
+ const Core::HID::SixAxisSensorHandle& device_handle) {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
-const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
- const Core::HID::VibrationDeviceHandle& device_handle) const {
+const NPad::NpadControllerData& NPad::GetControllerFromHandle(
+ const Core::HID::SixAxisSensorHandle& device_handle) const {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
-Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
- Core::HID::NpadIdType npad_id) {
+NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
npad_id = Core::HID::NpadIdType::Player1;
}
- const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
+ const auto npad_index = NpadIdTypeToIndex(npad_id);
return controller_data[npad_index];
}
-const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
+const NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(
Core::HID::NpadIdType npad_id) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
npad_id = Core::HID::NpadIdType::Player1;
}
- const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
+ const auto npad_index = NpadIdTypeToIndex(npad_id);
return controller_data[npad_index];
}
-Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
+Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
@@ -1658,7 +1320,7 @@ Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
}
}
-const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
+const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
const auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
@@ -1681,65 +1343,13 @@ const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
}
}
-Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
- auto& controller = GetControllerFromHandle(sixaxis_handle);
- switch (sixaxis_handle.npad_type) {
- case Core::HID::NpadStyleIndex::ProController:
- case Core::HID::NpadStyleIndex::Pokeball:
- return controller.sixaxis_fullkey;
- case Core::HID::NpadStyleIndex::Handheld:
- return controller.sixaxis_handheld;
- case Core::HID::NpadStyleIndex::JoyconDual:
- if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
- return controller.sixaxis_dual_left;
- }
- return controller.sixaxis_dual_right;
- case Core::HID::NpadStyleIndex::JoyconLeft:
- return controller.sixaxis_left;
- case Core::HID::NpadStyleIndex::JoyconRight:
- return controller.sixaxis_right;
- default:
- return controller.sixaxis_unknown;
- }
-}
-
-const Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
- const auto& controller = GetControllerFromHandle(sixaxis_handle);
- switch (sixaxis_handle.npad_type) {
- case Core::HID::NpadStyleIndex::ProController:
- case Core::HID::NpadStyleIndex::Pokeball:
- return controller.sixaxis_fullkey;
- case Core::HID::NpadStyleIndex::Handheld:
- return controller.sixaxis_handheld;
- case Core::HID::NpadStyleIndex::JoyconDual:
- if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
- return controller.sixaxis_dual_left;
- }
- return controller.sixaxis_dual_right;
- case Core::HID::NpadStyleIndex::JoyconLeft:
- return controller.sixaxis_left;
- case Core::HID::NpadStyleIndex::JoyconRight:
- return controller.sixaxis_right;
- default:
- return controller.sixaxis_unknown;
- }
-}
-
-Controller_NPad::AppletDetailedUiType Controller_NPad::GetAppletDetailedUiType(
- Core::HID::NpadIdType npad_id) {
-
- auto controller = GetControllerFromNpadIdType(npad_id);
- auto shared_memory = controller.shared_memory;
- Service::HID::Controller_NPad::AppletFooterUiType applet_footer_type =
- shared_memory->applet_footer_type;
+NPad::AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
+ const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory;
- Controller_NPad::AppletDetailedUiType detailed_ui_type{
+ return {
.ui_variant = 0,
- .footer = applet_footer_type,
+ .footer = shared_memory->applet_footer_type,
};
- return detailed_ui_type;
}
} // 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 @@
#include "common/bit_field.h"
#include "common/common_types.h"
-#include "common/vector_math.h"
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/controllers/controller_base.h"
@@ -34,11 +33,11 @@ union Result;
namespace Service::HID {
-class Controller_NPad final : public ControllerBase {
+class NPad final : public ControllerBase {
public:
- explicit Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
- KernelHelpers::ServiceContext& service_context_);
- ~Controller_NPad() override;
+ explicit NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
+ KernelHelpers::ServiceContext& service_context_);
+ ~NPad() override;
// Called when the controller is initialized
void OnInit() override;
@@ -49,9 +48,6 @@ public:
// When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
- // When the controller is requesting a motion update for the shared memory
- void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) override;
-
// This is nn::hid::NpadJoyHoldType
enum class NpadJoyHoldType : u64 {
Vertical = 0,
@@ -133,6 +129,8 @@ public:
Revision3 = 3,
};
+ using SixAxisLifo = Lifo<Core::HID::SixAxisSensorState, hid_entry_count>;
+
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
@@ -185,37 +183,18 @@ public:
Result DisconnectNpad(Core::HID::NpadIdType npad_id);
- Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::GyroscopeZeroDriftMode drift_mode);
- Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::GyroscopeZeroDriftMode& drift_mode) const;
- Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- bool& is_at_rest) const;
Result IsFirmwareUpdateAvailableForSixAxisSensor(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const;
- Result EnableSixAxisSensorUnalteredPassthrough(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
- Result IsSixAxisSensorUnalteredPassthroughEnabled(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
- Result LoadSixAxisSensorCalibrationParameter(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
- Result GetSixAxisSensorIcInformation(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::SixAxisSensorIcInformation& ic_information) const;
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
const Core::HID::SixAxisSensorHandle& sixaxis_handle);
- Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- bool sixaxis_status);
- Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- bool& is_fusion_enabled) const;
- Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- bool is_fusion_enabled);
- Result SetSixAxisFusionParameters(
- const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
- Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
- Core::HID::SixAxisSensorFusionParameters& parameters) const;
+
+ SixAxisLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
+ SixAxisLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
+ SixAxisLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
+ SixAxisLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
+ SixAxisLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
+ SixAxisLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
+
Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
bool& is_enabled) const;
@@ -239,10 +218,6 @@ public:
void ApplyNpadSystemCommonPolicy();
- static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
- static Result IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
- static Result VerifyValidSixAxisSensorHandle(
- const Core::HID::SixAxisSensorHandle& device_handle);
AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
private:
@@ -302,29 +277,6 @@ private:
};
static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
- // This is nn::hid::SixAxisSensorAttribute
- struct SixAxisSensorAttribute {
- union {
- u32 raw{};
- BitField<0, 1, u32> is_connected;
- BitField<1, 1, u32> is_interpolated;
- };
- };
- static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size");
-
- // This is nn::hid::SixAxisSensorState
- struct SixAxisSensorState {
- s64 delta_time{};
- s64 sampling_number{};
- Common::Vec3f accel{};
- Common::Vec3f gyro{};
- Common::Vec3f rotation{};
- std::array<Common::Vec3f, 3> orientation{};
- SixAxisSensorAttribute attribute{};
- INSERT_PADDING_BYTES(4); // Reserved
- };
- static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size");
-
// This is nn::hid::server::NpadGcTriggerState
struct NpadGcTriggerState {
s64 sampling_number{};
@@ -444,12 +396,12 @@ private:
Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{};
Lifo<NPadGenericState, hid_entry_count> palma_lifo{};
Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{};
- Lifo<SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
- Lifo<SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
- Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
- Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
- Lifo<SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
- Lifo<SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
+ Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
+ Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
+ Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
+ Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
+ Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
+ Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
DeviceType device_type{};
INSERT_PADDING_BYTES(0x4); // Reserved
NPadSystemProperties system_properties{};
@@ -483,16 +435,6 @@ private:
std::chrono::steady_clock::time_point last_vibration_timepoint{};
};
- struct SixaxisParameters {
- bool is_fusion_enabled{true};
- bool unaltered_passtrough{false};
- Core::HID::SixAxisSensorFusionParameters fusion{};
- Core::HID::SixAxisSensorCalibrationParameter calibration{};
- Core::HID::SixAxisSensorIcInformation ic_information{};
- Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{
- Core::HID::GyroscopeZeroDriftMode::Standard};
- };
-
struct NpadControllerData {
Kernel::KEvent* styleset_changed_event{};
NpadInternalState* shared_memory = nullptr;
@@ -506,27 +448,10 @@ private:
bool is_dual_left_connected{true};
bool is_dual_right_connected{true};
- // Motion parameters
- bool sixaxis_at_rest{true};
- bool sixaxis_sensor_enabled{true};
- SixaxisParameters sixaxis_fullkey{};
- SixaxisParameters sixaxis_handheld{};
- SixaxisParameters sixaxis_dual_left{};
- SixaxisParameters sixaxis_dual_right{};
- SixaxisParameters sixaxis_left{};
- SixaxisParameters sixaxis_right{};
- SixaxisParameters sixaxis_unknown{};
-
// Current pad state
NPadGenericState npad_pad_state{};
NPadGenericState npad_libnx_state{};
NpadGcTriggerState npad_trigger_state{};
- SixAxisSensorState sixaxis_fullkey_state{};
- SixAxisSensorState sixaxis_handheld_state{};
- SixAxisSensorState sixaxis_dual_left_state{};
- SixAxisSensorState sixaxis_dual_right_state{};
- SixAxisSensorState sixaxis_left_lifo_state{};
- SixAxisSensorState sixaxis_right_lifo_state{};
int callback_key{};
};
@@ -537,13 +462,13 @@ private:
void WriteEmptyEntry(NpadInternalState* npad);
NpadControllerData& GetControllerFromHandle(
- const Core::HID::SixAxisSensorHandle& device_handle);
- const NpadControllerData& GetControllerFromHandle(
- const Core::HID::SixAxisSensorHandle& device_handle) const;
- NpadControllerData& GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle);
const NpadControllerData& GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle) const;
+ NpadControllerData& GetControllerFromHandle(
+ const Core::HID::SixAxisSensorHandle& device_handle);
+ const NpadControllerData& GetControllerFromHandle(
+ const Core::HID::SixAxisSensorHandle& device_handle) const;
NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
@@ -551,9 +476,6 @@ private:
const Core::HID::SixAxisSensorHandle& device_handle);
const Core::HID::SixAxisSensorProperties& GetSixaxisProperties(
const Core::HID::SixAxisSensorHandle& device_handle) const;
- SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
- const SixaxisParameters& GetSixaxisState(
- const Core::HID::SixAxisSensorHandle& device_handle) const;
std::atomic<u64> press_state{};
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 @@
namespace Service::HID {
-Controller_Palma::Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
- KernelHelpers::ServiceContext& service_context_)
+Palma::Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
+ KernelHelpers::ServiceContext& service_context_)
: ControllerBase{hid_core_}, service_context{service_context_} {
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
}
-Controller_Palma::~Controller_Palma() {
+Palma::~Palma() {
service_context.CloseEvent(operation_complete_event);
};
-void Controller_Palma::OnInit() {}
+void Palma::OnInit() {}
-void Controller_Palma::OnRelease() {}
+void Palma::OnRelease() {}
-void Controller_Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+void Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
return;
}
}
-Result Controller_Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id,
- PalmaConnectionHandle& handle) {
+Result Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id,
+ PalmaConnectionHandle& handle) {
active_handle.npad_id = npad_id;
handle = active_handle;
return ResultSuccess;
}
-Result Controller_Palma::InitializePalma(const PalmaConnectionHandle& handle) {
+Result Palma::InitializePalma(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -48,7 +48,7 @@ Result Controller_Palma::InitializePalma(const PalmaConnectionHandle& handle) {
return ResultSuccess;
}
-Kernel::KReadableEvent& Controller_Palma::AcquirePalmaOperationCompleteEvent(
+Kernel::KReadableEvent& Palma::AcquirePalmaOperationCompleteEvent(
const PalmaConnectionHandle& handle) const {
if (handle.npad_id != active_handle.npad_id) {
LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id);
@@ -56,9 +56,9 @@ Kernel::KReadableEvent& Controller_Palma::AcquirePalmaOperationCompleteEvent(
return operation_complete_event->GetReadableEvent();
}
-Result Controller_Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle,
- PalmaOperationType& operation_type,
- PalmaOperationData& data) const {
+Result Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle,
+ PalmaOperationType& operation_type,
+ PalmaOperationData& data) const {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -67,8 +67,7 @@ Result Controller_Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& hand
return ResultSuccess;
}
-Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle,
- u64 palma_activity) {
+Result Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -79,8 +78,7 @@ Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle,
return ResultSuccess;
}
-Result Controller_Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle,
- PalmaFrModeType fr_mode_) {
+Result Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -88,7 +86,7 @@ Result Controller_Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle,
return ResultSuccess;
}
-Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
+Result Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -99,25 +97,25 @@ Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
return ResultSuccess;
}
-Result Controller_Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) {
+Result Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
return ResultSuccess;
}
-Result Controller_Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) {
+Result Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
return ResultSuccess;
}
-void Controller_Palma::ReadPalmaApplicationSection() {}
+void Palma::ReadPalmaApplicationSection() {}
-void Controller_Palma::WritePalmaApplicationSection() {}
+void Palma::WritePalmaApplicationSection() {}
-Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) {
+Result Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -128,7 +126,7 @@ Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle
return ResultSuccess;
}
-Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) {
+Result Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -139,10 +137,9 @@ Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle&
return ResultSuccess;
}
-void Controller_Palma::WritePalmaActivityEntry() {}
+void Palma::WritePalmaActivityEntry() {}
-Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle,
- u64 unknown) {
+Result Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -153,8 +150,8 @@ Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandl
return ResultSuccess;
}
-Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave,
- Common::ProcessAddress t_mem, u64 size) {
+Result Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave,
+ Common::ProcessAddress t_mem, u64 size) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -165,8 +162,8 @@ Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle
return ResultSuccess;
}
-Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle,
- s32 database_id_version_) {
+Result Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle,
+ s32 database_id_version_) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -178,8 +175,7 @@ Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnec
return ResultSuccess;
}
-Result Controller_Palma::GetPalmaDataBaseIdentificationVersion(
- const PalmaConnectionHandle& handle) {
+Result Palma::GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -191,26 +187,26 @@ Result Controller_Palma::GetPalmaDataBaseIdentificationVersion(
return ResultSuccess;
}
-void Controller_Palma::SuspendPalmaFeature() {}
+void Palma::SuspendPalmaFeature() {}
-Result Controller_Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const {
+Result Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
return operation.result;
}
-void Controller_Palma::ReadPalmaPlayLog() {}
+void Palma::ReadPalmaPlayLog() {}
-void Controller_Palma::ResetPalmaPlayLog() {}
+void Palma::ResetPalmaPlayLog() {}
-void Controller_Palma::SetIsPalmaAllConnectable(bool is_all_connectable) {
+void Palma::SetIsPalmaAllConnectable(bool is_all_connectable) {
// If true controllers are able to be paired
is_connectable = is_all_connectable;
}
-void Controller_Palma::SetIsPalmaPairedConnectable() {}
+void Palma::SetIsPalmaPairedConnectable() {}
-Result Controller_Palma::PairPalma(const PalmaConnectionHandle& handle) {
+Result Palma::PairPalma(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -218,14 +214,14 @@ Result Controller_Palma::PairPalma(const PalmaConnectionHandle& handle) {
return ResultSuccess;
}
-void Controller_Palma::SetPalmaBoostMode(bool boost_mode) {}
+void Palma::SetPalmaBoostMode(bool boost_mode) {}
-void Controller_Palma::CancelWritePalmaWaveEntry() {}
+void Palma::CancelWritePalmaWaveEntry() {}
-void Controller_Palma::EnablePalmaBoostMode() {}
+void Palma::EnablePalmaBoostMode() {}
-void Controller_Palma::GetPalmaBluetoothAddress() {}
+void Palma::GetPalmaBluetoothAddress() {}
-void Controller_Palma::SetDisallowedPalmaConnection() {}
+void Palma::SetDisallowedPalmaConnection() {}
} // 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;
} // namespace Core::HID
namespace Service::HID {
-class Controller_Palma final : public ControllerBase {
+class Palma final : public ControllerBase {
public:
using PalmaOperationData = std::array<u8, 0x140>;
@@ -97,9 +97,9 @@ public:
static_assert(sizeof(PalmaConnectionHandle) == 0x8,
"PalmaConnectionHandle has incorrect size.");
- explicit Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
- KernelHelpers::ServiceContext& service_context_);
- ~Controller_Palma() override;
+ explicit Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
+ KernelHelpers::ServiceContext& service_context_);
+ ~Palma() override;
// Called when the controller is initialized
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 @@
-// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+#include <cstring>
+#include "common/common_types.h"
#include "core/core.h"
#include "core/core_timing.h"
+#include "core/frontend/emu_window.h"
#include "core/hid/emulated_console.h"
+#include "core/hid/emulated_devices.h"
#include "core/hid/hid_core.h"
-#include "core/hle/service/hid/controllers/console_sixaxis.h"
+#include "core/hle/service/hid/controllers/seven_six_axis.h"
#include "core/memory.h"
namespace Service::HID {
-constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
-
-Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_)
+SevenSixAxis::SevenSixAxis(Core::System& system_)
: ControllerBase{system_.HIDCore()}, system{system_} {
console = hid_core.GetEmulatedConsole();
- static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
- "ConsoleSharedMemory is bigger than the shared memory");
- shared_memory = std::construct_at(
- reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
}
-Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default;
-
-void Controller_ConsoleSixAxis::OnInit() {}
+SevenSixAxis::~SevenSixAxis() = default;
-void Controller_ConsoleSixAxis::OnRelease() {}
+void SevenSixAxis::OnInit() {}
+void SevenSixAxis::OnRelease() {}
-void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+void SevenSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated() || transfer_memory == 0) {
seven_sixaxis_lifo.buffer_count = 0;
seven_sixaxis_lifo.buffer_tail = 0;
@@ -53,22 +50,17 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
-motion_status.quaternion.xyz.z,
};
- shared_memory->sampling_number++;
- shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
- shared_memory->verticalization_error = motion_status.verticalization_error;
- shared_memory->gyro_bias = motion_status.gyro_bias;
-
- // Update seven six axis transfer memory
seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo,
sizeof(seven_sixaxis_lifo));
}
-void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
+void SevenSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
transfer_memory = t_mem;
}
-void Controller_ConsoleSixAxis::ResetTimestamp() {
+void SevenSixAxis::ResetTimestamp() {
last_saved_timestamp = last_global_timestamp;
}
+
} // 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 @@
-// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
-#include <array>
-
+#include "common/common_types.h"
#include "common/quaternion.h"
#include "common/typed_address.h"
#include "core/hle/service/hid/controllers/controller_base.h"
@@ -19,10 +18,10 @@ class EmulatedConsole;
} // namespace Core::HID
namespace Service::HID {
-class Controller_ConsoleSixAxis final : public ControllerBase {
+class SevenSixAxis final : public ControllerBase {
public:
- explicit Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_);
- ~Controller_ConsoleSixAxis() override;
+ explicit SevenSixAxis(Core::System& system_);
+ ~SevenSixAxis() override;
// Called when the controller is initialized
void OnInit() override;
@@ -51,28 +50,16 @@ private:
};
static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size");
- // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
- struct ConsoleSharedMemory {
- u64 sampling_number{};
- bool is_seven_six_axis_sensor_at_rest{};
- INSERT_PADDING_BYTES(3); // padding
- f32 verticalization_error{};
- Common::Vec3f gyro_bias{};
- INSERT_PADDING_BYTES(4); // padding
- };
- static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
-
Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{};
static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size");
+ u64 last_saved_timestamp{};
+ u64 last_global_timestamp{};
+
SevenSixAxisState next_seven_sixaxis_state{};
Common::ProcessAddress transfer_memory{};
- ConsoleSharedMemory* shared_memory = nullptr;
Core::HID::EmulatedConsole* console = nullptr;
- u64 last_saved_timestamp{};
- u64 last_global_timestamp{};
-
Core::System& system;
};
} // 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 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "common/common_types.h"
+#include "core/core_timing.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
+#include "core/hle/service/hid/controllers/npad.h"
+#include "core/hle/service/hid/controllers/six_axis.h"
+#include "core/hle/service/hid/errors.h"
+#include "core/hle/service/hid/hid_util.h"
+
+namespace Service::HID {
+
+SixAxis::SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_)
+ : ControllerBase{hid_core_}, npad{npad_} {
+ for (std::size_t i = 0; i < controller_data.size(); ++i) {
+ auto& controller = controller_data[i];
+ controller.device = hid_core.GetEmulatedControllerByIndex(i);
+ }
+}
+
+SixAxis::~SixAxis() = default;
+
+void SixAxis::OnInit() {}
+void SixAxis::OnRelease() {}
+
+void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+ if (!IsControllerActivated()) {
+ return;
+ }
+
+ for (std::size_t i = 0; i < controller_data.size(); ++i) {
+ auto& controller = controller_data[i];
+
+ const auto npad_id = IndexToNpadIdType(i);
+ const auto& controller_type = controller.device->GetNpadStyleIndex();
+
+ if (controller_type == Core::HID::NpadStyleIndex::None ||
+ !controller.device->IsConnected()) {
+ continue;
+ }
+
+ const auto& motion_state = controller.device->GetMotions();
+ auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
+ auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
+ auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
+ auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
+ auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
+ auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
+
+ auto& sixaxis_fullkey_lifo = npad->GetSixAxisFullkeyLifo(npad_id);
+ auto& sixaxis_handheld_lifo = npad->GetSixAxisHandheldLifo(npad_id);
+ auto& sixaxis_dual_left_lifo = npad->GetSixAxisDualLeftLifo(npad_id);
+ auto& sixaxis_dual_right_lifo = npad->GetSixAxisDualRightLifo(npad_id);
+ auto& sixaxis_left_lifo = npad->GetSixAxisLeftLifo(npad_id);
+ auto& sixaxis_right_lifo = npad->GetSixAxisRightLifo(npad_id);
+
+ // Clear previous state
+ sixaxis_fullkey_state = {};
+ sixaxis_handheld_state = {};
+ sixaxis_dual_left_state = {};
+ sixaxis_dual_right_state = {};
+ sixaxis_left_lifo_state = {};
+ sixaxis_right_lifo_state = {};
+
+ if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
+ controller.sixaxis_at_rest = true;
+ for (std::size_t e = 0; e < motion_state.size(); ++e) {
+ controller.sixaxis_at_rest =
+ controller.sixaxis_at_rest && motion_state[e].is_at_rest;
+ }
+ }
+
+ const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state,
+ const Core::HID::ControllerMotion& hid_state) {
+ using namespace std::literals::chrono_literals;
+ static constexpr Core::HID::SixAxisSensorState default_motion_state = {
+ .delta_time = std::chrono::nanoseconds(5ms).count(),
+ .accel = {0, 0, -1.0f},
+ .orientation =
+ {
+ Common::Vec3f{1.0f, 0, 0},
+ Common::Vec3f{0, 1.0f, 0},
+ Common::Vec3f{0, 0, 1.0f},
+ },
+ .attribute = {1},
+ };
+ if (!controller.sixaxis_sensor_enabled) {
+ state = default_motion_state;
+ return;
+ }
+ if (!Settings::values.motion_enabled.GetValue()) {
+ state = default_motion_state;
+ return;
+ }
+ state.attribute.is_connected.Assign(1);
+ state.delta_time = std::chrono::nanoseconds(5ms).count();
+ state.accel = hid_state.accel;
+ state.gyro = hid_state.gyro;
+ state.rotation = hid_state.rotation;
+ state.orientation = hid_state.orientation;
+ };
+
+ switch (controller_type) {
+ case Core::HID::NpadStyleIndex::None:
+ ASSERT(false);
+ break;
+ case Core::HID::NpadStyleIndex::ProController:
+ set_motion_state(sixaxis_fullkey_state, motion_state[0]);
+ break;
+ case Core::HID::NpadStyleIndex::Handheld:
+ set_motion_state(sixaxis_handheld_state, motion_state[0]);
+ break;
+ case Core::HID::NpadStyleIndex::JoyconDual:
+ set_motion_state(sixaxis_dual_left_state, motion_state[0]);
+ set_motion_state(sixaxis_dual_right_state, motion_state[1]);
+ break;
+ case Core::HID::NpadStyleIndex::JoyconLeft:
+ set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
+ break;
+ case Core::HID::NpadStyleIndex::JoyconRight:
+ set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
+ break;
+ case Core::HID::NpadStyleIndex::Pokeball:
+ using namespace std::literals::chrono_literals;
+ set_motion_state(sixaxis_fullkey_state, motion_state[0]);
+ sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
+ break;
+ default:
+ break;
+ }
+
+ sixaxis_fullkey_state.sampling_number =
+ sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_handheld_state.sampling_number =
+ sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_dual_left_state.sampling_number =
+ sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_dual_right_state.sampling_number =
+ sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_left_lifo_state.sampling_number =
+ sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_right_lifo_state.sampling_number =
+ sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
+
+ if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
+ // This buffer only is updated on handheld on HW
+ sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
+ } else {
+ // Handheld doesn't update this buffer on HW
+ sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
+ }
+
+ sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
+ sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
+ sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
+ sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
+ }
+}
+
+Result SixAxis::SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::GyroscopeZeroDriftMode drift_mode) {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ auto& controller = GetControllerFromHandle(sixaxis_handle);
+ sixaxis.gyroscope_zero_drift_mode = drift_mode;
+ controller.device->SetGyroscopeZeroDriftMode(drift_mode);
+
+ return ResultSuccess;
+}
+
+Result SixAxis::GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ const auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ drift_mode = sixaxis.gyroscope_zero_drift_mode;
+
+ return ResultSuccess;
+}
+
+Result SixAxis::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ bool& is_at_rest) const {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ const auto& controller = GetControllerFromHandle(sixaxis_handle);
+ is_at_rest = controller.sixaxis_at_rest;
+ return ResultSuccess;
+}
+
+Result SixAxis::LoadSixAxisSensorCalibrationParameter(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ // TODO: Request this data to the controller. On error return 0xd8ca
+ const auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ calibration = sixaxis.calibration;
+ return ResultSuccess;
+}
+
+Result SixAxis::GetSixAxisSensorIcInformation(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::SixAxisSensorIcInformation& ic_information) const {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ // TODO: Request this data to the controller. On error return 0xd8ca
+ const auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ ic_information = sixaxis.ic_information;
+ return ResultSuccess;
+}
+
+Result SixAxis::EnableSixAxisSensorUnalteredPassthrough(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ sixaxis.unaltered_passtrough = is_enabled;
+ return ResultSuccess;
+}
+
+Result SixAxis::IsSixAxisSensorUnalteredPassthroughEnabled(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ const auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ is_enabled = sixaxis.unaltered_passtrough;
+ return ResultSuccess;
+}
+
+Result SixAxis::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ bool sixaxis_status) {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ auto& controller = GetControllerFromHandle(sixaxis_handle);
+ controller.sixaxis_sensor_enabled = sixaxis_status;
+ return ResultSuccess;
+}
+
+Result SixAxis::IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ bool& is_fusion_enabled) const {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ const auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ is_fusion_enabled = sixaxis.is_fusion_enabled;
+
+ return ResultSuccess;
+}
+Result SixAxis::SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ bool is_fusion_enabled) {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ sixaxis.is_fusion_enabled = is_fusion_enabled;
+
+ return ResultSuccess;
+}
+
+Result SixAxis::SetSixAxisFusionParameters(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ const auto param1 = sixaxis_fusion_parameters.parameter1;
+ if (param1 < 0.0f || param1 > 1.0f) {
+ return InvalidSixAxisFusionRange;
+ }
+
+ auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ sixaxis.fusion = sixaxis_fusion_parameters;
+
+ return ResultSuccess;
+}
+
+Result SixAxis::GetSixAxisFusionParameters(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::SixAxisSensorFusionParameters& parameters) const {
+ const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
+ if (is_valid.IsError()) {
+ LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
+ return is_valid;
+ }
+
+ const auto& sixaxis = GetSixaxisState(sixaxis_handle);
+ parameters = sixaxis.fusion;
+
+ return ResultSuccess;
+}
+
+SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
+ auto& controller = GetControllerFromHandle(sixaxis_handle);
+ switch (sixaxis_handle.npad_type) {
+ case Core::HID::NpadStyleIndex::ProController:
+ case Core::HID::NpadStyleIndex::Pokeball:
+ return controller.sixaxis_fullkey;
+ case Core::HID::NpadStyleIndex::Handheld:
+ return controller.sixaxis_handheld;
+ case Core::HID::NpadStyleIndex::JoyconDual:
+ if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
+ return controller.sixaxis_dual_left;
+ }
+ return controller.sixaxis_dual_right;
+ case Core::HID::NpadStyleIndex::JoyconLeft:
+ return controller.sixaxis_left;
+ case Core::HID::NpadStyleIndex::JoyconRight:
+ return controller.sixaxis_right;
+ default:
+ return controller.sixaxis_unknown;
+ }
+}
+
+const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
+ const auto& controller = GetControllerFromHandle(sixaxis_handle);
+ switch (sixaxis_handle.npad_type) {
+ case Core::HID::NpadStyleIndex::ProController:
+ case Core::HID::NpadStyleIndex::Pokeball:
+ return controller.sixaxis_fullkey;
+ case Core::HID::NpadStyleIndex::Handheld:
+ return controller.sixaxis_handheld;
+ case Core::HID::NpadStyleIndex::JoyconDual:
+ if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
+ return controller.sixaxis_dual_left;
+ }
+ return controller.sixaxis_dual_right;
+ case Core::HID::NpadStyleIndex::JoyconLeft:
+ return controller.sixaxis_left;
+ case Core::HID::NpadStyleIndex::JoyconRight:
+ return controller.sixaxis_right;
+ default:
+ return controller.sixaxis_unknown;
+ }
+}
+
+SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle(
+ const Core::HID::SixAxisSensorHandle& device_handle) {
+ const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
+ return GetControllerFromNpadIdType(npad_id);
+}
+
+const SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle(
+ const Core::HID::SixAxisSensorHandle& device_handle) const {
+ const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
+ return GetControllerFromNpadIdType(npad_id);
+}
+
+SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) {
+ if (!IsNpadIdValid(npad_id)) {
+ LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
+ npad_id = Core::HID::NpadIdType::Player1;
+ }
+ const auto npad_index = NpadIdTypeToIndex(npad_id);
+ return controller_data[npad_index];
+}
+
+const SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(
+ Core::HID::NpadIdType npad_id) const {
+ if (!IsNpadIdValid(npad_id)) {
+ LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
+ npad_id = Core::HID::NpadIdType::Player1;
+ }
+ const auto npad_index = NpadIdTypeToIndex(npad_id);
+ return controller_data[npad_index];
+}
+
+} // 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 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "common/common_types.h"
+#include "core/hid/hid_types.h"
+#include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/ring_lifo.h"
+
+namespace Core::HID {
+class EmulatedController;
+} // namespace Core::HID
+
+namespace Service::HID {
+class NPad;
+
+class SixAxis final : public ControllerBase {
+public:
+ explicit SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_);
+ ~SixAxis() override;
+
+ // Called when the controller is initialized
+ void OnInit() override;
+
+ // When the controller is released
+ void OnRelease() override;
+
+ // When the controller is requesting an update for the shared memory
+ void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
+
+ Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::GyroscopeZeroDriftMode drift_mode);
+ Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::GyroscopeZeroDriftMode& drift_mode) const;
+ Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ bool& is_at_rest) const;
+ Result EnableSixAxisSensorUnalteredPassthrough(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
+ Result IsSixAxisSensorUnalteredPassthroughEnabled(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
+ Result LoadSixAxisSensorCalibrationParameter(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
+ Result GetSixAxisSensorIcInformation(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::SixAxisSensorIcInformation& ic_information) const;
+ Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ bool sixaxis_status);
+ Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ bool& is_fusion_enabled) const;
+ Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ bool is_fusion_enabled);
+ Result SetSixAxisFusionParameters(
+ const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
+ Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
+ Core::HID::SixAxisSensorFusionParameters& parameters) const;
+
+private:
+ static constexpr std::size_t NPAD_COUNT = 10;
+
+ struct SixaxisParameters {
+ bool is_fusion_enabled{true};
+ bool unaltered_passtrough{false};
+ Core::HID::SixAxisSensorFusionParameters fusion{};
+ Core::HID::SixAxisSensorCalibrationParameter calibration{};
+ Core::HID::SixAxisSensorIcInformation ic_information{};
+ Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{
+ Core::HID::GyroscopeZeroDriftMode::Standard};
+ };
+
+ struct NpadControllerData {
+ Core::HID::EmulatedController* device = nullptr;
+
+ // Motion parameters
+ bool sixaxis_at_rest{true};
+ bool sixaxis_sensor_enabled{true};
+ SixaxisParameters sixaxis_fullkey{};
+ SixaxisParameters sixaxis_handheld{};
+ SixaxisParameters sixaxis_dual_left{};
+ SixaxisParameters sixaxis_dual_right{};
+ SixaxisParameters sixaxis_left{};
+ SixaxisParameters sixaxis_right{};
+ SixaxisParameters sixaxis_unknown{};
+
+ // Current pad state
+ Core::HID::SixAxisSensorState sixaxis_fullkey_state{};
+ Core::HID::SixAxisSensorState sixaxis_handheld_state{};
+ Core::HID::SixAxisSensorState sixaxis_dual_left_state{};
+ Core::HID::SixAxisSensorState sixaxis_dual_right_state{};
+ Core::HID::SixAxisSensorState sixaxis_left_lifo_state{};
+ Core::HID::SixAxisSensorState sixaxis_right_lifo_state{};
+ int callback_key{};
+ };
+
+ SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
+ const SixaxisParameters& GetSixaxisState(
+ const Core::HID::SixAxisSensorHandle& device_handle) const;
+
+ NpadControllerData& GetControllerFromHandle(
+ const Core::HID::SixAxisSensorHandle& device_handle);
+ const NpadControllerData& GetControllerFromHandle(
+ const Core::HID::SixAxisSensorHandle& device_handle) const;
+ NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
+ const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
+
+ std::shared_ptr<NPad> npad;
+ std::array<NpadControllerData, NPAD_COUNT> controller_data{};
+};
+} // 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 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
-Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_,
- u8* raw_shared_memory_)
+TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
"TouchSharedMemory is bigger than the shared memory");
@@ -25,13 +24,13 @@ Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_,
console = hid_core.GetEmulatedConsole();
}
-Controller_Touchscreen::~Controller_Touchscreen() = default;
+TouchScreen::~TouchScreen() = default;
-void Controller_Touchscreen::OnInit() {}
+void TouchScreen::OnInit() {}
-void Controller_Touchscreen::OnRelease() {}
+void TouchScreen::OnRelease() {}
-void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
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;
} // namespace Core::HID
namespace Service::HID {
-class Controller_Touchscreen final : public ControllerBase {
+class TouchScreen final : public ControllerBase {
public:
- explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
- ~Controller_Touchscreen() override;
+ explicit TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ ~TouchScreen() override;
// Called when the controller is initialized
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 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
-Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
- : ControllerBase{hid_core_} {
+XPad::XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size,
"XpadSharedMemory is bigger than the shared memory");
shared_memory = std::construct_at(
reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
}
-Controller_XPad::~Controller_XPad() = default;
+XPad::~XPad() = default;
-void Controller_XPad::OnInit() {}
+void XPad::OnInit() {}
-void Controller_XPad::OnRelease() {}
+void XPad::OnRelease() {}
-void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
+void XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->basic_xpad_lifo.buffer_count = 0;
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 @@
#include "core/hle/service/hid/ring_lifo.h"
namespace Service::HID {
-class Controller_XPad final : public ControllerBase {
+class XPad final : public ControllerBase {
public:
- explicit Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
- ~Controller_XPad() override;
+ explicit XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ ~XPad() override;
// Called when the controller is initialized
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 @@
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid_firmware_settings.h"
#include "core/hle/service/hid/hid_server.h"
+#include "core/hle/service/hid/hid_util.h"
#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/memory.h"
-#include "core/hle/service/hid/controllers/console_sixaxis.h"
+#include "core/hle/service/hid/controllers/console_six_axis.h"
#include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/controllers/debug_pad.h"
#include "core/hle/service/hid/controllers/gesture.h"
@@ -24,9 +25,9 @@
#include "core/hle/service/hid/controllers/mouse.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/controllers/palma.h"
-#include "core/hle/service/hid/controllers/stubbed.h"
+#include "core/hle/service/hid/controllers/seven_six_axis.h"
+#include "core/hle/service/hid/controllers/six_axis.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
-#include "core/hle/service/hid/controllers/xpad.h"
namespace Service::HID {
@@ -50,8 +51,7 @@ private:
const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
if (resource_manager != nullptr) {
- resource_manager->GetController<Controller_NPad>(HidController::NPad)
- .InitializeVibrationDevice(vibration_device_handle);
+ resource_manager->GetNpad()->InitializeVibrationDevice(vibration_device_handle);
}
LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}",
@@ -235,15 +235,14 @@ void IHidServer::ActivateDebugPad(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
Result result = ResultSuccess;
- auto& debug_pad =
- GetResourceManager()->GetController<Controller_DebugPad>(HidController::DebugPad);
+ auto debug_pad = GetResourceManager()->GetDebugPad();
if (!firmware_settings->IsDeviceManaged()) {
- result = debug_pad.Activate();
+ result = debug_pad->Activate();
}
if (result.IsSuccess()) {
- result = debug_pad.Activate(applet_resource_user_id);
+ result = debug_pad->Activate(applet_resource_user_id);
}
IPC::ResponseBuilder rb{ctx, 2};
@@ -257,15 +256,14 @@ void IHidServer::ActivateTouchScreen(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
Result result = ResultSuccess;
- auto& touch_screen =
- GetResourceManager()->GetController<Controller_Touchscreen>(HidController::Touchscreen);
+ auto touch_screen = GetResourceManager()->GetTouchScreen();
if (!firmware_settings->IsDeviceManaged()) {
- result = touch_screen.Activate();
+ result = touch_screen->Activate();
}
if (result.IsSuccess()) {
- result = touch_screen.Activate(applet_resource_user_id);
+ result = touch_screen->Activate(applet_resource_user_id);
}
IPC::ResponseBuilder rb{ctx, 2};
@@ -279,14 +277,14 @@ void IHidServer::ActivateMouse(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
Result result = ResultSuccess;
- auto& mouse = GetResourceManager()->GetController<Controller_Mouse>(HidController::Mouse);
+ auto mouse = GetResourceManager()->GetMouse();
if (!firmware_settings->IsDeviceManaged()) {
- result = mouse.Activate();
+ result = mouse->Activate();
}
if (result.IsSuccess()) {
- result = mouse.Activate(applet_resource_user_id);
+ result = mouse->Activate(applet_resource_user_id);
}
IPC::ResponseBuilder rb{ctx, 2};
@@ -300,15 +298,14 @@ void IHidServer::ActivateKeyboard(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
Result result = ResultSuccess;
- auto& keyboard =
- GetResourceManager()->GetController<Controller_Keyboard>(HidController::Keyboard);
+ auto keyboard = GetResourceManager()->GetKeyboard();
if (!firmware_settings->IsDeviceManaged()) {
- result = keyboard.Activate();
+ result = keyboard->Activate();
}
if (result.IsSuccess()) {
- result = keyboard.Activate(applet_resource_user_id);
+ result = keyboard->Activate(applet_resource_user_id);
}
IPC::ResponseBuilder rb{ctx, 2};
@@ -502,8 +499,8 @@ void IHidServer::StartSixAxisSensor(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, true);
+ auto six_axis = GetResourceManager()->GetSixAxis();
+ const auto result = six_axis->SetSixAxisEnabled(parameters.sixaxis_handle, true);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -525,8 +522,8 @@ void IHidServer::StopSixAxisSensor(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, false);
+ auto six_axis = GetResourceManager()->GetSixAxis();
+ const auto result = six_axis->SetSixAxisEnabled(parameters.sixaxis_handle, false);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -549,9 +546,9 @@ void IHidServer::IsSixAxisSensorFusionEnabled(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
bool is_enabled{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto six_axis = GetResourceManager()->GetSixAxis();
const auto result =
- controller.IsSixAxisSensorFusionEnabled(parameters.sixaxis_handle, is_enabled);
+ six_axis->IsSixAxisSensorFusionEnabled(parameters.sixaxis_handle, is_enabled);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -575,9 +572,9 @@ void IHidServer::EnableSixAxisSensorFusion(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle,
- parameters.enable_sixaxis_sensor_fusion);
+ auto six_axis = GetResourceManager()->GetSixAxis();
+ const auto result = six_axis->SetSixAxisFusionEnabled(parameters.sixaxis_handle,
+ parameters.enable_sixaxis_sensor_fusion);
LOG_DEBUG(Service_HID,
"called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
@@ -602,9 +599,9 @@ void IHidServer::SetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto six_axis = GetResourceManager()->GetSixAxis();
const auto result =
- controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
+ six_axis->SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
@@ -629,10 +626,9 @@ void IHidServer::GetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
Core::HID::SixAxisSensorFusionParameters fusion_parameters{};
- const auto& controller =
- GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto six_axis = GetResourceManager()->GetSixAxis();
const auto result =
- controller.GetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
+ six_axis->GetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -660,10 +656,10 @@ void IHidServer::ResetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
.parameter1 = 0.03f,
.parameter2 = 0.4f,
};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto six_axis = GetResourceManager()->GetSixAxis();
const auto result1 =
- controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
- const auto result2 = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle, true);
+ six_axis->SetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
+ const auto result2 = six_axis->SetSixAxisFusionEnabled(parameters.sixaxis_handle, true);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -684,8 +680,8 @@ void IHidServer::SetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
const auto drift_mode{rp.PopEnum<Core::HID::GyroscopeZeroDriftMode>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
+ auto six_axis = GetResourceManager()->GetSixAxis();
+ const auto result = six_axis->SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, "
@@ -709,8 +705,8 @@ void IHidServer::GetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
+ auto six_axis = GetResourceManager()->GetSixAxis();
+ const auto result = six_axis->GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -734,8 +730,8 @@ void IHidServer::ResetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
const auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
+ auto six_axis = GetResourceManager()->GetSixAxis();
+ const auto result = six_axis->SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -758,8 +754,8 @@ void IHidServer::IsSixAxisSensorAtRest(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
bool is_at_rest{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- controller.IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest);
+ auto six_axis = GetResourceManager()->GetSixAxis();
+ six_axis->IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -783,9 +779,9 @@ void IHidServer::IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ct
const auto parameters{rp.PopRaw<Parameters>()};
bool is_firmware_available{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- controller.IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle,
- is_firmware_available);
+ auto controller = GetResourceManager()->GetNpad();
+ controller->IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle,
+ is_firmware_available);
LOG_WARNING(
Service_HID,
@@ -809,9 +805,9 @@ void IHidServer::EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx)
const auto parameters{rp.PopRaw<Parameters>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.EnableSixAxisSensorUnalteredPassthrough(
- parameters.sixaxis_handle, parameters.enabled);
+ auto six_axis = GetResourceManager()->GetSixAxis();
+ const auto result = six_axis->EnableSixAxisSensorUnalteredPassthrough(parameters.sixaxis_handle,
+ parameters.enabled);
LOG_DEBUG(Service_HID,
"(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, "
@@ -836,8 +832,8 @@ void IHidServer::IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& c
const auto parameters{rp.PopRaw<Parameters>()};
bool is_unaltered_sisxaxis_enabled{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled(
+ auto six_axis = GetResourceManager()->GetSixAxis();
+ const auto result = six_axis->IsSixAxisSensorUnalteredPassthroughEnabled(
parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled);
LOG_DEBUG(
@@ -863,9 +859,9 @@ void IHidServer::LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
Core::HID::SixAxisSensorCalibrationParameter calibration{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto six_axis = GetResourceManager()->GetSixAxis();
const auto result =
- controller.LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration);
+ six_axis->LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration);
LOG_WARNING(
Service_HID,
@@ -893,9 +889,9 @@ void IHidServer::GetSixAxisSensorIcInformation(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
Core::HID::SixAxisSensorIcInformation ic_information{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto six_axis = GetResourceManager()->GetSixAxis();
const auto result =
- controller.GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information);
+ six_axis->GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information);
LOG_WARNING(
Service_HID,
@@ -922,9 +918,9 @@ void IHidServer::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx)
const auto parameters{rp.PopRaw<Parameters>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto controller = GetResourceManager()->GetNpad();
const auto result =
- controller.ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle);
+ controller->ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle);
LOG_WARNING(
Service_HID,
@@ -951,15 +947,15 @@ void IHidServer::ActivateGesture(HLERequestContext& ctx) {
parameters.basic_gesture_id, parameters.applet_resource_user_id);
Result result = ResultSuccess;
- auto& gesture = GetResourceManager()->GetController<Controller_Gesture>(HidController::Gesture);
+ auto gesture = GetResourceManager()->GetGesture();
if (!firmware_settings->IsDeviceManaged()) {
- result = gesture.Activate();
+ result = gesture->Activate();
}
if (result.IsSuccess()) {
// TODO: Use gesture id here
- result = gesture.Activate(parameters.applet_resource_user_id);
+ result = gesture->Activate(parameters.applet_resource_user_id);
}
IPC::ResponseBuilder rb{ctx, 2};
@@ -977,9 +973,7 @@ void IHidServer::SetSupportedNpadStyleSet(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SetSupportedStyleSet({parameters.supported_styleset});
+ GetResourceManager()->GetNpad()->SetSupportedStyleSet({parameters.supported_styleset});
LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}",
parameters.supported_styleset, parameters.applet_resource_user_id);
@@ -996,19 +990,14 @@ void IHidServer::GetSupportedNpadStyleSet(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
- rb.PushEnum(GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .GetSupportedStyleSet()
- .raw);
+ rb.PushEnum(GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw);
}
void IHidServer::SetSupportedNpadIdType(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto result = GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SetSupportedNpadIdTypes(ctx.ReadBuffer());
+ const auto result = GetResourceManager()->GetNpad()->SetSupportedNpadIdTypes(ctx.ReadBuffer());
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
@@ -1022,10 +1011,10 @@ void IHidServer::ActivateNpad(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
- auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto npad = GetResourceManager()->GetNpad();
// TODO: npad->SetRevision(applet_resource_user_id, NpadRevision::Revision0);
- const Result result = npad.Activate(applet_resource_user_id);
+ const Result result = npad->Activate(applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -1059,15 +1048,12 @@ void IHidServer::AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx) {
parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown);
// Games expect this event to be signaled after calling this function
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SignalStyleSetChangedEvent(parameters.npad_id);
+ GetResourceManager()->GetNpad()->SignalStyleSetChangedEvent(parameters.npad_id);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
- rb.PushCopyObjects(GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .GetStyleSetChangedEvent(parameters.npad_id));
+ rb.PushCopyObjects(
+ GetResourceManager()->GetNpad()->GetStyleSetChangedEvent(parameters.npad_id));
}
void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
@@ -1081,8 +1067,8 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- controller.DisconnectNpad(parameters.npad_id);
+ auto controller = GetResourceManager()->GetNpad();
+ controller->DisconnectNpad(parameters.npad_id);
LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
parameters.applet_resource_user_id);
@@ -1096,8 +1082,8 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
Core::HID::LedPattern pattern{0, 0, 0, 0};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.GetLedPattern(npad_id, pattern);
+ auto controller = GetResourceManager()->GetNpad();
+ const auto result = controller->GetLedPattern(npad_id, pattern);
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
@@ -1109,7 +1095,7 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
- Controller_NPad::NpadRevision revision;
+ NPad::NpadRevision revision;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id;
};
@@ -1120,10 +1106,10 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision,
parameters.applet_resource_user_id);
- auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto npad = GetResourceManager()->GetNpad();
// TODO: npad->SetRevision(applet_resource_user_id, revision);
- const auto result = npad.Activate(parameters.applet_resource_user_id);
+ const auto result = npad->Activate(parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -1132,11 +1118,9 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto hold_type{rp.PopEnum<Controller_NPad::NpadJoyHoldType>()};
+ const auto hold_type{rp.PopEnum<NPad::NpadJoyHoldType>()};
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SetHoldType(hold_type);
+ GetResourceManager()->GetNpad()->SetHoldType(hold_type);
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}",
applet_resource_user_id, hold_type);
@@ -1153,8 +1137,7 @@ void IHidServer::GetNpadJoyHoldType(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
- rb.PushEnum(
- GetResourceManager()->GetController<Controller_NPad>(HidController::NPad).GetHoldType());
+ rb.PushEnum(GetResourceManager()->GetNpad()->GetHoldType());
}
void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) {
@@ -1169,10 +1152,9 @@ void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx)
const auto parameters{rp.PopRaw<Parameters>()};
Core::HID::NpadIdType new_npad_id{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- controller.SetNpadMode(new_npad_id, parameters.npad_id,
- Controller_NPad::NpadJoyDeviceType::Left,
- Controller_NPad::NpadJoyAssignmentMode::Single);
+ auto controller = GetResourceManager()->GetNpad();
+ controller->SetNpadMode(new_npad_id, parameters.npad_id, NPad::NpadJoyDeviceType::Left,
+ NPad::NpadJoyAssignmentMode::Single);
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
parameters.applet_resource_user_id);
@@ -1187,16 +1169,16 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id;
- Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
+ NPad::NpadJoyDeviceType npad_joy_device_type;
};
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()};
Core::HID::NpadIdType new_npad_id{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
- Controller_NPad::NpadJoyAssignmentMode::Single);
+ auto controller = GetResourceManager()->GetNpad();
+ controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
+ NPad::NpadJoyAssignmentMode::Single);
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
parameters.npad_id, parameters.applet_resource_user_id,
@@ -1218,9 +1200,8 @@ void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
Core::HID::NpadIdType new_npad_id{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- controller.SetNpadMode(new_npad_id, parameters.npad_id, {},
- Controller_NPad::NpadJoyAssignmentMode::Dual);
+ auto controller = GetResourceManager()->GetNpad();
+ controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NPad::NpadJoyAssignmentMode::Dual);
LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
parameters.applet_resource_user_id); // Spams a lot when controller applet is open
@@ -1235,8 +1216,8 @@ void IHidServer::MergeSingleJoyAsDualJoy(HLERequestContext& ctx) {
const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
+ auto controller = GetResourceManager()->GetNpad();
+ const auto result = controller->MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
npad_id_1, npad_id_2, applet_resource_user_id);
@@ -1249,9 +1230,7 @@ void IHidServer::StartLrAssignmentMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .StartLRAssignmentMode();
+ GetResourceManager()->GetNpad()->StartLRAssignmentMode();
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
@@ -1263,9 +1242,7 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .StopLRAssignmentMode();
+ GetResourceManager()->GetNpad()->StopLRAssignmentMode();
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
@@ -1276,11 +1253,9 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto activation_mode{rp.PopEnum<Controller_NPad::NpadHandheldActivationMode>()};
+ const auto activation_mode{rp.PopEnum<NPad::NpadHandheldActivationMode>()};
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SetNpadHandheldActivationMode(activation_mode);
+ GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode);
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}",
applet_resource_user_id, activation_mode);
@@ -1297,9 +1272,7 @@ void IHidServer::GetNpadHandheldActivationMode(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
- rb.PushEnum(GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .GetNpadHandheldActivationMode());
+ rb.PushEnum(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode());
}
void IHidServer::SwapNpadAssignment(HLERequestContext& ctx) {
@@ -1308,8 +1281,8 @@ void IHidServer::SwapNpadAssignment(HLERequestContext& ctx) {
const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SwapNpadAssignment(npad_id_1, npad_id_2);
+ auto controller = GetResourceManager()->GetNpad();
+ const auto result = controller->SwapNpadAssignment(npad_id_1, npad_id_2);
LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
npad_id_1, npad_id_2, applet_resource_user_id);
@@ -1330,9 +1303,9 @@ void IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext&
const auto parameters{rp.PopRaw<Parameters>()};
bool is_enabled = false;
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto controller = GetResourceManager()->GetNpad();
const auto result =
- controller.IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled);
+ controller->IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled);
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
parameters.npad_id, parameters.applet_resource_user_id);
@@ -1354,8 +1327,8 @@ void IHidServer::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ct
const auto parameters{rp.PopRaw<Parameters>()};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled(
+ auto controller = GetResourceManager()->GetNpad();
+ const auto result = controller->SetUnintendedHomeButtonInputProtectionEnabled(
parameters.is_enabled, parameters.npad_id);
LOG_DEBUG(Service_HID,
@@ -1372,17 +1345,17 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id;
- Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
+ NPad::NpadJoyDeviceType npad_joy_device_type;
};
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()};
Core::HID::NpadIdType new_npad_id{};
- auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ auto controller = GetResourceManager()->GetNpad();
const auto is_reassigned =
- controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
- Controller_NPad::NpadJoyAssignmentMode::Single);
+ controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
+ NPad::NpadJoyAssignmentMode::Single);
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
parameters.npad_id, parameters.applet_resource_user_id,
@@ -1405,9 +1378,8 @@ void IHidServer::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp);
+ GetResourceManager()->GetNpad()->SetAnalogStickUseCenterClamp(
+ parameters.analog_stick_use_center_clamp);
LOG_WARNING(Service_HID,
"(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}",
@@ -1451,8 +1423,7 @@ void IHidServer::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) {
void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
- const auto& controller =
- GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto controller = GetResourceManager()->GetNpad();
Core::HID::VibrationDeviceInfo vibration_device_info;
bool check_device_index = false;
@@ -1496,7 +1467,7 @@ void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}",
vibration_device_info.type, vibration_device_info.position);
- const auto result = controller.IsDeviceHandleValid(vibration_device_handle);
+ const auto result = IsVibrationHandleValid(vibration_device_handle);
if (result.IsError()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -1520,9 +1491,8 @@ void IHidServer::SendVibrationValue(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .VibrateController(parameters.vibration_device_handle, parameters.vibration_value);
+ GetResourceManager()->GetNpad()->VibrateController(parameters.vibration_device_handle,
+ parameters.vibration_value);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -1553,9 +1523,8 @@ void IHidServer::GetActualVibrationValue(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
- rb.PushRaw(GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .GetLastVibration(parameters.vibration_device_handle));
+ rb.PushRaw(
+ GetResourceManager()->GetNpad()->GetLastVibration(parameters.vibration_device_handle));
}
void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) {
@@ -1606,9 +1575,7 @@ void IHidServer::SendVibrationValues(HLERequestContext& ctx) {
auto vibration_values = std::span(
reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .VibrateControllers(vibration_device_handles, vibration_values);
+ GetResourceManager()->GetNpad()->VibrateControllers(vibration_device_handles, vibration_values);
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
@@ -1662,9 +1629,8 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) {
}
}();
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .VibrateController(parameters.vibration_device_handle, vibration_value);
+ GetResourceManager()->GetNpad()->VibrateController(parameters.vibration_device_handle,
+ vibration_value);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, "
@@ -1688,9 +1654,8 @@ void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
- const auto last_vibration = GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .GetLastVibration(parameters.vibration_device_handle);
+ const auto last_vibration =
+ GetResourceManager()->GetNpad()->GetLastVibration(parameters.vibration_device_handle);
const auto gc_erm_command = [last_vibration] {
if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
@@ -1725,9 +1690,7 @@ void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SetPermitVibrationSession(true);
+ GetResourceManager()->GetNpad()->SetPermitVibrationSession(true);
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
@@ -1736,9 +1699,7 @@ void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) {
}
void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) {
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SetPermitVibrationSession(false);
+ GetResourceManager()->GetNpad()->SetPermitVibrationSession(false);
LOG_DEBUG(Service_HID, "called");
@@ -1765,9 +1726,8 @@ void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
- rb.Push(GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .IsVibrationDeviceMounted(parameters.vibration_device_handle));
+ rb.Push(GetResourceManager()->GetNpad()->IsVibrationDeviceMounted(
+ parameters.vibration_device_handle));
}
void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {
@@ -1777,15 +1737,14 @@ void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {
LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
Result result = ResultSuccess;
- auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>(
- HidController::ConsoleSixAxisSensor);
+ auto console_sixaxis = GetResourceManager()->GetConsoleSixAxis();
if (!firmware_settings->IsDeviceManaged()) {
- result = console_sixaxis.Activate();
+ result = console_sixaxis->Activate();
}
if (result.IsSuccess()) {
- result = console_sixaxis.Activate(applet_resource_user_id);
+ result = console_sixaxis->Activate(applet_resource_user_id);
}
IPC::ResponseBuilder rb{ctx, 2};
@@ -1839,15 +1798,14 @@ void IHidServer::ActivateSevenSixAxisSensor(HLERequestContext& ctx) {
LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
Result result = ResultSuccess;
- auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>(
- HidController::ConsoleSixAxisSensor);
+ auto seven_sixaxis = GetResourceManager()->GetSevenSixAxis();
if (!firmware_settings->IsDeviceManaged()) {
- result = console_sixaxis.Activate();
+ result = seven_sixaxis->Activate();
}
if (result.IsSuccess()) {
- console_sixaxis.Activate(applet_resource_user_id);
+ seven_sixaxis->Activate(applet_resource_user_id);
}
IPC::ResponseBuilder rb{ctx, 2};
@@ -1911,13 +1869,10 @@ void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) {
ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size");
// Activate console six axis controller
- GetResourceManager()
- ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
- .Activate();
+ GetResourceManager()->GetConsoleSixAxis()->Activate();
+ GetResourceManager()->GetSevenSixAxis()->Activate();
- GetResourceManager()
- ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
- .SetTransferMemoryAddress(t_mem_1->GetSourceAddress());
+ GetResourceManager()->GetSevenSixAxis()->SetTransferMemoryAddress(t_mem_1->GetSourceAddress());
LOG_WARNING(Service_HID,
"called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, "
@@ -1943,9 +1898,7 @@ void IHidServer::ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- GetResourceManager()
- ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
- .ResetTimestamp();
+ GetResourceManager()->GetSevenSixAxis()->ResetTimestamp();
LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
@@ -1977,9 +1930,9 @@ void IHidServer::GetPalmaConnectionHandle(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
parameters.npad_id, parameters.applet_resource_user_id);
- Controller_Palma::PalmaConnectionHandle handle;
- auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.GetPalmaConnectionHandle(parameters.npad_id, handle);
+ Palma::PalmaConnectionHandle handle;
+ auto controller = GetResourceManager()->GetPalma();
+ const auto result = controller->GetPalmaConnectionHandle(parameters.npad_id, handle);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(result);
@@ -1988,12 +1941,12 @@ void IHidServer::GetPalmaConnectionHandle(HLERequestContext& ctx) {
void IHidServer::InitializePalma(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.InitializePalma(connection_handle);
+ auto controller = GetResourceManager()->GetPalma();
+ const auto result = controller->InitializePalma(connection_handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -2001,27 +1954,27 @@ void IHidServer::InitializePalma(HLERequestContext& ctx) {
void IHidServer::AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ auto controller = GetResourceManager()->GetPalma();
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
- rb.PushCopyObjects(controller.AcquirePalmaOperationCompleteEvent(connection_handle));
+ rb.PushCopyObjects(controller->AcquirePalmaOperationCompleteEvent(connection_handle));
}
void IHidServer::GetPalmaOperationInfo(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- Controller_Palma::PalmaOperationType operation_type;
- Controller_Palma::PalmaOperationData data;
- auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.GetPalmaOperationInfo(connection_handle, operation_type, data);
+ Palma::PalmaOperationType operation_type;
+ Palma::PalmaOperationData data;
+ auto controller = GetResourceManager()->GetPalma();
+ const auto result = controller->GetPalmaOperationInfo(connection_handle, operation_type, data);
if (result.IsError()) {
IPC::ResponseBuilder rb{ctx, 2};
@@ -2036,14 +1989,14 @@ void IHidServer::GetPalmaOperationInfo(HLERequestContext& ctx) {
void IHidServer::PlayPalmaActivity(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
const auto palma_activity{rp.Pop<u64>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, palma_activity={}",
connection_handle.npad_id, palma_activity);
- auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.PlayPalmaActivity(connection_handle, palma_activity);
+ auto controller = GetResourceManager()->GetPalma();
+ const auto result = controller->PlayPalmaActivity(connection_handle, palma_activity);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -2051,14 +2004,14 @@ void IHidServer::PlayPalmaActivity(HLERequestContext& ctx) {
void IHidServer::SetPalmaFrModeType(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
- const auto fr_mode{rp.PopEnum<Controller_Palma::PalmaFrModeType>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
+ const auto fr_mode{rp.PopEnum<Palma::PalmaFrModeType>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, fr_mode={}",
connection_handle.npad_id, fr_mode);
- auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.SetPalmaFrModeType(connection_handle, fr_mode);
+ auto controller = GetResourceManager()->GetPalma();
+ const auto result = controller->SetPalmaFrModeType(connection_handle, fr_mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -2066,12 +2019,12 @@ void IHidServer::SetPalmaFrModeType(HLERequestContext& ctx) {
void IHidServer::ReadPalmaStep(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.ReadPalmaStep(connection_handle);
+ auto controller = GetResourceManager()->GetPalma();
+ const auto result = controller->ReadPalmaStep(connection_handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -2082,7 +2035,7 @@ void IHidServer::EnablePalmaStep(HLERequestContext& ctx) {
struct Parameters {
bool is_enabled;
INSERT_PADDING_WORDS_NOINIT(1);
- Controller_Palma::PalmaConnectionHandle connection_handle;
+ Palma::PalmaConnectionHandle connection_handle;
};
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
@@ -2091,9 +2044,9 @@ void IHidServer::EnablePalmaStep(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, is_enabled={}",
parameters.connection_handle.npad_id, parameters.is_enabled);
- auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ auto controller = GetResourceManager()->GetPalma();
const auto result =
- controller.EnablePalmaStep(parameters.connection_handle, parameters.is_enabled);
+ controller->EnablePalmaStep(parameters.connection_handle, parameters.is_enabled);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -2101,12 +2054,12 @@ void IHidServer::EnablePalmaStep(HLERequestContext& ctx) {
void IHidServer::ResetPalmaStep(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.ResetPalmaStep(connection_handle);
+ auto controller = GetResourceManager()->GetPalma();
+ const auto result = controller->ResetPalmaStep(connection_handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -2128,13 +2081,11 @@ void IHidServer::WritePalmaApplicationSection(HLERequestContext& ctx) {
void IHidServer::ReadPalmaUniqueCode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .ReadPalmaUniqueCode(connection_handle);
+ GetResourceManager()->GetPalma()->ReadPalmaUniqueCode(connection_handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -2142,13 +2093,11 @@ void IHidServer::ReadPalmaUniqueCode(HLERequestContext& ctx) {
void IHidServer::SetPalmaUniqueCodeInvalid(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .SetPalmaUniqueCodeInvalid(connection_handle);
+ GetResourceManager()->GetPalma()->SetPalmaUniqueCodeInvalid(connection_handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -2163,7 +2112,7 @@ void IHidServer::WritePalmaActivityEntry(HLERequestContext& ctx) {
void IHidServer::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
const auto unknown{rp.Pop<u64>()};
[[maybe_unused]] const auto buffer = ctx.ReadBuffer();
@@ -2171,9 +2120,7 @@ void IHidServer::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}",
connection_handle.npad_id, unknown);
- GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .WritePalmaRgbLedPatternEntry(connection_handle, unknown);
+ GetResourceManager()->GetPalma()->WritePalmaRgbLedPatternEntry(connection_handle, unknown);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -2181,8 +2128,8 @@ void IHidServer::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
void IHidServer::WritePalmaWaveEntry(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
- const auto wave_set{rp.PopEnum<Controller_Palma::PalmaWaveSet>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
+ const auto wave_set{rp.PopEnum<Palma::PalmaWaveSet>()};
const auto unknown{rp.Pop<u64>()};
const auto t_mem_size{rp.Pop<u64>()};
const auto t_mem_handle{ctx.GetCopyHandle(0)};
@@ -2207,9 +2154,8 @@ void IHidServer::WritePalmaWaveEntry(HLERequestContext& ctx) {
"t_mem_handle=0x{:08X}, t_mem_size={}, size={}",
connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size);
- GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .WritePalmaWaveEntry(connection_handle, wave_set, t_mem->GetSourceAddress(), t_mem_size);
+ GetResourceManager()->GetPalma()->WritePalmaWaveEntry(connection_handle, wave_set,
+ t_mem->GetSourceAddress(), t_mem_size);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -2220,7 +2166,7 @@ void IHidServer::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
struct Parameters {
s32 database_id_version;
INSERT_PADDING_WORDS_NOINIT(1);
- Controller_Palma::PalmaConnectionHandle connection_handle;
+ Palma::PalmaConnectionHandle connection_handle;
};
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
@@ -2229,10 +2175,8 @@ void IHidServer::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, database_id_version={}",
parameters.connection_handle.npad_id, parameters.database_id_version);
- GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .SetPalmaDataBaseIdentificationVersion(parameters.connection_handle,
- parameters.database_id_version);
+ GetResourceManager()->GetPalma()->SetPalmaDataBaseIdentificationVersion(
+ parameters.connection_handle, parameters.database_id_version);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -2240,13 +2184,11 @@ void IHidServer::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
void IHidServer::GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .GetPalmaDataBaseIdentificationVersion(connection_handle);
+ GetResourceManager()->GetPalma()->GetPalmaDataBaseIdentificationVersion(connection_handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -2261,13 +2203,12 @@ void IHidServer::SuspendPalmaFeature(HLERequestContext& ctx) {
void IHidServer::GetPalmaOperationResult(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- const auto result = GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .GetPalmaOperationResult(connection_handle);
+ const auto result =
+ GetResourceManager()->GetPalma()->GetPalmaOperationResult(connection_handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -2302,9 +2243,7 @@ void IHidServer::SetIsPalmaAllConnectable(HLERequestContext& ctx) {
"(STUBBED) called, is_palma_all_connectable={},applet_resource_user_id={}",
parameters.is_palma_all_connectable, parameters.applet_resource_user_id);
- GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .SetIsPalmaAllConnectable(parameters.is_palma_all_connectable);
+ GetResourceManager()->GetPalma()->SetIsPalmaAllConnectable(parameters.is_palma_all_connectable);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -2319,13 +2258,11 @@ void IHidServer::SetIsPalmaPairedConnectable(HLERequestContext& ctx) {
void IHidServer::PairPalma(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
- GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .PairPalma(connection_handle);
+ GetResourceManager()->GetPalma()->PairPalma(connection_handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -2337,9 +2274,7 @@ void IHidServer::SetPalmaBoostMode(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called, palma_boost_mode={}", palma_boost_mode);
- GetResourceManager()
- ->GetController<Controller_Palma>(HidController::Palma)
- .SetPalmaBoostMode(palma_boost_mode);
+ GetResourceManager()->GetPalma()->SetPalmaBoostMode(palma_boost_mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -2376,11 +2311,9 @@ void IHidServer::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto communication_mode{rp.PopEnum<Controller_NPad::NpadCommunicationMode>()};
+ const auto communication_mode{rp.PopEnum<NPad::NpadCommunicationMode>()};
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SetNpadCommunicationMode(communication_mode);
+ GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode);
LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}",
applet_resource_user_id, communication_mode);
@@ -2396,9 +2329,7 @@ void IHidServer::GetNpadCommunicationMode(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
- rb.PushEnum(GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .GetNpadCommunicationMode());
+ rb.PushEnum(GetResourceManager()->GetNpad()->GetNpadCommunicationMode());
}
void 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
resource_manager{resource} {
// clang-format off
static const FunctionInfo functions[] = {
- {31, nullptr, "SendKeyboardLockKeyEvent"},
- {101, nullptr, "AcquireHomeButtonEventHandle"},
- {111, nullptr, "ActivateHomeButton"},
- {121, nullptr, "AcquireSleepButtonEventHandle"},
- {131, nullptr, "ActivateSleepButton"},
- {141, nullptr, "AcquireCaptureButtonEventHandle"},
- {151, nullptr, "ActivateCaptureButton"},
- {161, nullptr, "GetPlatformConfig"},
- {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
- {211, nullptr, "GetNpadsWithNfc"},
- {212, nullptr, "AcquireNfcActivateEventHandle"},
- {213, nullptr, "ActivateNfc"},
- {214, nullptr, "GetXcdHandleForNpadWithNfc"},
- {215, nullptr, "IsNfcActivated"},
- {230, nullptr, "AcquireIrSensorEventHandle"},
- {231, nullptr, "ActivateIrSensor"},
- {232, nullptr, "GetIrSensorState"},
- {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
- {301, nullptr, "ActivateNpadSystem"},
- {303, &IHidSystemServer::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
- {304, &IHidSystemServer::EnableAssigningSingleOnSlSrPress, "EnableAssigningSingleOnSlSrPress"},
- {305, &IHidSystemServer::DisableAssigningSingleOnSlSrPress, "DisableAssigningSingleOnSlSrPress"},
- {306, &IHidSystemServer::GetLastActiveNpad, "GetLastActiveNpad"},
- {307, nullptr, "GetNpadSystemExtStyle"},
- {308, &IHidSystemServer::ApplyNpadSystemCommonPolicyFull, "ApplyNpadSystemCommonPolicyFull"},
- {309, &IHidSystemServer::GetNpadFullKeyGripColor, "GetNpadFullKeyGripColor"},
- {310, &IHidSystemServer::GetMaskedSupportedNpadStyleSet, "GetMaskedSupportedNpadStyleSet"},
- {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
- {312, &IHidSystemServer::SetSupportedNpadStyleSetAll, "SetSupportedNpadStyleSetAll"},
- {313, nullptr, "GetNpadCaptureButtonAssignment"},
- {314, nullptr, "GetAppletFooterUiType"},
- {315, &IHidSystemServer::GetAppletDetailedUiType, "GetAppletDetailedUiType"},
- {316, &IHidSystemServer::GetNpadInterfaceType, "GetNpadInterfaceType"},
- {317, &IHidSystemServer::GetNpadLeftRightInterfaceType, "GetNpadLeftRightInterfaceType"},
- {318, &IHidSystemServer::HasBattery, "HasBattery"},
- {319, &IHidSystemServer::HasLeftRightBattery, "HasLeftRightBattery"},
- {321, &IHidSystemServer::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
- {322, &IHidSystemServer::GetIrSensorState, "GetIrSensorState"},
- {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
- {324, nullptr, "GetUniquePadButtonSet"},
- {325, nullptr, "GetUniquePadColor"},
- {326, nullptr, "GetUniquePadAppletDetailedUiType"},
- {327, nullptr, "GetAbstractedPadIdDataFromNpad"},
- {328, nullptr, "AttachAbstractedPadToNpad"},
- {329, nullptr, "DetachAbstractedPadAll"},
- {330, nullptr, "CheckAbstractedPadConnection"},
- {500, nullptr, "SetAppletResourceUserId"},
- {501, nullptr, "RegisterAppletResourceUserId"},
- {502, nullptr, "UnregisterAppletResourceUserId"},
- {503, nullptr, "EnableAppletToGetInput"},
- {504, nullptr, "SetAruidValidForVibration"},
- {505, nullptr, "EnableAppletToGetSixAxisSensor"},
- {506, nullptr, "EnableAppletToGetPadInput"},
- {507, nullptr, "EnableAppletToGetTouchScreen"},
- {510, nullptr, "SetVibrationMasterVolume"},
- {511, nullptr, "GetVibrationMasterVolume"},
- {512, nullptr, "BeginPermitVibrationSession"},
- {513, nullptr, "EndPermitVibrationSession"},
- {514, nullptr, "Unknown514"},
- {520, nullptr, "EnableHandheldHids"},
- {521, nullptr, "DisableHandheldHids"},
- {522, nullptr, "SetJoyConRailEnabled"},
- {523, nullptr, "IsJoyConRailEnabled"},
- {524, nullptr, "IsHandheldHidsEnabled"},
- {525, nullptr, "IsJoyConAttachedOnAllRail"},
- {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
- {541, nullptr, "GetPlayReportControllerUsages"},
- {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
- {543, nullptr, "GetRegisteredDevicesOld"},
- {544, &IHidSystemServer::AcquireConnectionTriggerTimeoutEvent, "AcquireConnectionTriggerTimeoutEvent"},
- {545, nullptr, "SendConnectionTrigger"},
- {546, &IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport, "AcquireDeviceRegisteredEventForControllerSupport"},
- {547, nullptr, "GetAllowedBluetoothLinksCount"},
- {548, &IHidSystemServer::GetRegisteredDevices, "GetRegisteredDevices"},
- {549, nullptr, "GetConnectableRegisteredDevices"},
- {700, nullptr, "ActivateUniquePad"},
- {702, &IHidSystemServer::AcquireUniquePadConnectionEventHandle, "AcquireUniquePadConnectionEventHandle"},
- {703, &IHidSystemServer::GetUniquePadIds, "GetUniquePadIds"},
- {751, &IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
- {800, nullptr, "ListSixAxisSensorHandles"},
- {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
- {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
- {803, nullptr, "StartSixAxisSensorUserCalibration"},
- {804, nullptr, "CancelSixAxisSensorUserCalibration"},
- {805, nullptr, "GetUniquePadBluetoothAddress"},
- {806, nullptr, "DisconnectUniquePad"},
- {807, nullptr, "GetUniquePadType"},
- {808, nullptr, "GetUniquePadInterface"},
- {809, nullptr, "GetUniquePadSerialNumber"},
- {810, nullptr, "GetUniquePadControllerNumber"},
- {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
- {812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
- {821, nullptr, "StartAnalogStickManualCalibration"},
- {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
- {823, nullptr, "CancelAnalogStickManualCalibration"},
- {824, nullptr, "ResetAnalogStickManualCalibration"},
- {825, nullptr, "GetAnalogStickState"},
- {826, nullptr, "GetAnalogStickManualCalibrationStage"},
- {827, nullptr, "IsAnalogStickButtonPressed"},
- {828, nullptr, "IsAnalogStickInReleasePosition"},
- {829, nullptr, "IsAnalogStickInCircumference"},
- {830, nullptr, "SetNotificationLedPattern"},
- {831, nullptr, "SetNotificationLedPatternWithTimeout"},
- {832, nullptr, "PrepareHidsForNotificationWake"},
- {850, &IHidSystemServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
- {851, nullptr, "EnableUsbFullKeyController"},
- {852, nullptr, "IsUsbConnected"},
- {870, &IHidSystemServer::IsHandheldButtonPressedOnConsoleMode, "IsHandheldButtonPressedOnConsoleMode"},
- {900, nullptr, "ActivateInputDetector"},
- {901, nullptr, "NotifyInputDetector"},
- {1000, &IHidSystemServer::InitializeFirmwareUpdate, "InitializeFirmwareUpdate"},
- {1001, nullptr, "GetFirmwareVersion"},
- {1002, nullptr, "GetAvailableFirmwareVersion"},
- {1003, nullptr, "IsFirmwareUpdateAvailable"},
- {1004, nullptr, "CheckFirmwareUpdateRequired"},
- {1005, nullptr, "StartFirmwareUpdate"},
- {1006, nullptr, "AbortFirmwareUpdate"},
- {1007, nullptr, "GetFirmwareUpdateState"},
- {1008, nullptr, "ActivateAudioControl"},
- {1009, nullptr, "AcquireAudioControlEventHandle"},
- {1010, nullptr, "GetAudioControlStates"},
- {1011, nullptr, "DeactivateAudioControl"},
- {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
- {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
- {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
- {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
- {1100, nullptr, "GetHidbusSystemServiceObject"},
- {1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"},
- {1130, nullptr, "InitializeUsbFirmwareUpdate"},
- {1131, nullptr, "FinalizeUsbFirmwareUpdate"},
- {1132, nullptr, "CheckUsbFirmwareUpdateRequired"},
- {1133, nullptr, "StartUsbFirmwareUpdate"},
- {1134, nullptr, "GetUsbFirmwareUpdateState"},
- {1135, &IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory, "InitializeUsbFirmwareUpdateWithoutMemory"},
- {1150, nullptr, "SetTouchScreenMagnification"},
- {1151, nullptr, "GetTouchScreenFirmwareVersion"},
- {1152, nullptr, "SetTouchScreenDefaultConfiguration"},
- {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
- {1154, nullptr, "IsFirmwareAvailableForNotification"},
- {1155, nullptr, "SetForceHandheldStyleVibration"},
- {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
- {1157, nullptr, "CancelConnectionTrigger"},
- {1200, nullptr, "IsButtonConfigSupported"},
- {1201, nullptr, "IsButtonConfigEmbeddedSupported"},
- {1202, nullptr, "DeleteButtonConfig"},
- {1203, nullptr, "DeleteButtonConfigEmbedded"},
- {1204, nullptr, "SetButtonConfigEnabled"},
- {1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
- {1206, nullptr, "IsButtonConfigEnabled"},
- {1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
- {1208, nullptr, "SetButtonConfigEmbedded"},
- {1209, nullptr, "SetButtonConfigFull"},
- {1210, nullptr, "SetButtonConfigLeft"},
- {1211, nullptr, "SetButtonConfigRight"},
- {1212, nullptr, "GetButtonConfigEmbedded"},
- {1213, nullptr, "GetButtonConfigFull"},
- {1214, nullptr, "GetButtonConfigLeft"},
- {1215, nullptr, "GetButtonConfigRight"},
- {1250, nullptr, "IsCustomButtonConfigSupported"},
- {1251, nullptr, "IsDefaultButtonConfigEmbedded"},
- {1252, nullptr, "IsDefaultButtonConfigFull"},
- {1253, nullptr, "IsDefaultButtonConfigLeft"},
- {1254, nullptr, "IsDefaultButtonConfigRight"},
- {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
- {1256, nullptr, "IsButtonConfigStorageFullEmpty"},
- {1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
- {1258, nullptr, "IsButtonConfigStorageRightEmpty"},
- {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
- {1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
- {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
- {1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
- {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
- {1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
- {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
- {1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
- {1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
- {1268, nullptr, "DeleteButtonConfigStorageFull"},
- {1269, nullptr, "DeleteButtonConfigStorageLeft"},
- {1270, nullptr, "DeleteButtonConfigStorageRight"},
- {1271, nullptr, "IsUsingCustomButtonConfig"},
- {1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
- {1273, nullptr, "SetAllCustomButtonConfigEnabled"},
- {1274, nullptr, "SetDefaultButtonConfig"},
- {1275, nullptr, "SetAllDefaultButtonConfig"},
- {1276, nullptr, "SetHidButtonConfigEmbedded"},
- {1277, nullptr, "SetHidButtonConfigFull"},
- {1278, nullptr, "SetHidButtonConfigLeft"},
- {1279, nullptr, "SetHidButtonConfigRight"},
- {1280, nullptr, "GetHidButtonConfigEmbedded"},
- {1281, nullptr, "GetHidButtonConfigFull"},
- {1282, nullptr, "GetHidButtonConfigLeft"},
- {1283, nullptr, "GetHidButtonConfigRight"},
- {1284, nullptr, "GetButtonConfigStorageEmbedded"},
- {1285, nullptr, "GetButtonConfigStorageFull"},
- {1286, nullptr, "GetButtonConfigStorageLeft"},
- {1287, nullptr, "GetButtonConfigStorageRight"},
- {1288, nullptr, "SetButtonConfigStorageEmbedded"},
- {1289, nullptr, "SetButtonConfigStorageFull"},
- {1290, nullptr, "DeleteButtonConfigStorageRight"},
- {1291, nullptr, "DeleteButtonConfigStorageRight"},
+ {31, nullptr, "SendKeyboardLockKeyEvent"},
+ {101, nullptr, "AcquireHomeButtonEventHandle"},
+ {111, nullptr, "ActivateHomeButton"},
+ {121, nullptr, "AcquireSleepButtonEventHandle"},
+ {131, nullptr, "ActivateSleepButton"},
+ {141, nullptr, "AcquireCaptureButtonEventHandle"},
+ {151, nullptr, "ActivateCaptureButton"},
+ {161, nullptr, "GetPlatformConfig"},
+ {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
+ {211, nullptr, "GetNpadsWithNfc"},
+ {212, nullptr, "AcquireNfcActivateEventHandle"},
+ {213, nullptr, "ActivateNfc"},
+ {214, nullptr, "GetXcdHandleForNpadWithNfc"},
+ {215, nullptr, "IsNfcActivated"},
+ {230, nullptr, "AcquireIrSensorEventHandle"},
+ {231, nullptr, "ActivateIrSensor"},
+ {232, nullptr, "GetIrSensorState"},
+ {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
+ {301, nullptr, "ActivateNpadSystem"},
+ {303, &IHidSystemServer::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
+ {304, &IHidSystemServer::EnableAssigningSingleOnSlSrPress, "EnableAssigningSingleOnSlSrPress"},
+ {305, &IHidSystemServer::DisableAssigningSingleOnSlSrPress, "DisableAssigningSingleOnSlSrPress"},
+ {306, &IHidSystemServer::GetLastActiveNpad, "GetLastActiveNpad"},
+ {307, nullptr, "GetNpadSystemExtStyle"},
+ {308, &IHidSystemServer::ApplyNpadSystemCommonPolicyFull, "ApplyNpadSystemCommonPolicyFull"},
+ {309, &IHidSystemServer::GetNpadFullKeyGripColor, "GetNpadFullKeyGripColor"},
+ {310, &IHidSystemServer::GetMaskedSupportedNpadStyleSet, "GetMaskedSupportedNpadStyleSet"},
+ {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
+ {312, &IHidSystemServer::SetSupportedNpadStyleSetAll, "SetSupportedNpadStyleSetAll"},
+ {313, nullptr, "GetNpadCaptureButtonAssignment"},
+ {314, nullptr, "GetAppletFooterUiType"},
+ {315, &IHidSystemServer::GetAppletDetailedUiType, "GetAppletDetailedUiType"},
+ {316, &IHidSystemServer::GetNpadInterfaceType, "GetNpadInterfaceType"},
+ {317, &IHidSystemServer::GetNpadLeftRightInterfaceType, "GetNpadLeftRightInterfaceType"},
+ {318, &IHidSystemServer::HasBattery, "HasBattery"},
+ {319, &IHidSystemServer::HasLeftRightBattery, "HasLeftRightBattery"},
+ {321, &IHidSystemServer::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
+ {322, &IHidSystemServer::GetIrSensorState, "GetIrSensorState"},
+ {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
+ {324, nullptr, "GetUniquePadButtonSet"},
+ {325, nullptr, "GetUniquePadColor"},
+ {326, nullptr, "GetUniquePadAppletDetailedUiType"},
+ {327, nullptr, "GetAbstractedPadIdDataFromNpad"},
+ {328, nullptr, "AttachAbstractedPadToNpad"},
+ {329, nullptr, "DetachAbstractedPadAll"},
+ {330, nullptr, "CheckAbstractedPadConnection"},
+ {500, nullptr, "SetAppletResourceUserId"},
+ {501, nullptr, "RegisterAppletResourceUserId"},
+ {502, nullptr, "UnregisterAppletResourceUserId"},
+ {503, nullptr, "EnableAppletToGetInput"},
+ {504, nullptr, "SetAruidValidForVibration"},
+ {505, nullptr, "EnableAppletToGetSixAxisSensor"},
+ {506, nullptr, "EnableAppletToGetPadInput"},
+ {507, nullptr, "EnableAppletToGetTouchScreen"},
+ {510, nullptr, "SetVibrationMasterVolume"},
+ {511, nullptr, "GetVibrationMasterVolume"},
+ {512, nullptr, "BeginPermitVibrationSession"},
+ {513, nullptr, "EndPermitVibrationSession"},
+ {514, nullptr, "Unknown514"},
+ {520, nullptr, "EnableHandheldHids"},
+ {521, nullptr, "DisableHandheldHids"},
+ {522, nullptr, "SetJoyConRailEnabled"},
+ {523, nullptr, "IsJoyConRailEnabled"},
+ {524, nullptr, "IsHandheldHidsEnabled"},
+ {525, nullptr, "IsJoyConAttachedOnAllRail"},
+ {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
+ {541, nullptr, "GetPlayReportControllerUsages"},
+ {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
+ {543, nullptr, "GetRegisteredDevicesOld"},
+ {544, &IHidSystemServer::AcquireConnectionTriggerTimeoutEvent, "AcquireConnectionTriggerTimeoutEvent"},
+ {545, nullptr, "SendConnectionTrigger"},
+ {546, &IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport, "AcquireDeviceRegisteredEventForControllerSupport"},
+ {547, nullptr, "GetAllowedBluetoothLinksCount"},
+ {548, &IHidSystemServer::GetRegisteredDevices, "GetRegisteredDevices"},
+ {549, nullptr, "GetConnectableRegisteredDevices"},
+ {700, nullptr, "ActivateUniquePad"},
+ {702, &IHidSystemServer::AcquireUniquePadConnectionEventHandle, "AcquireUniquePadConnectionEventHandle"},
+ {703, &IHidSystemServer::GetUniquePadIds, "GetUniquePadIds"},
+ {751, &IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
+ {800, nullptr, "ListSixAxisSensorHandles"},
+ {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
+ {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
+ {803, nullptr, "StartSixAxisSensorUserCalibration"},
+ {804, nullptr, "CancelSixAxisSensorUserCalibration"},
+ {805, nullptr, "GetUniquePadBluetoothAddress"},
+ {806, nullptr, "DisconnectUniquePad"},
+ {807, nullptr, "GetUniquePadType"},
+ {808, nullptr, "GetUniquePadInterface"},
+ {809, nullptr, "GetUniquePadSerialNumber"},
+ {810, nullptr, "GetUniquePadControllerNumber"},
+ {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
+ {812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
+ {821, nullptr, "StartAnalogStickManualCalibration"},
+ {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
+ {823, nullptr, "CancelAnalogStickManualCalibration"},
+ {824, nullptr, "ResetAnalogStickManualCalibration"},
+ {825, nullptr, "GetAnalogStickState"},
+ {826, nullptr, "GetAnalogStickManualCalibrationStage"},
+ {827, nullptr, "IsAnalogStickButtonPressed"},
+ {828, nullptr, "IsAnalogStickInReleasePosition"},
+ {829, nullptr, "IsAnalogStickInCircumference"},
+ {830, nullptr, "SetNotificationLedPattern"},
+ {831, nullptr, "SetNotificationLedPatternWithTimeout"},
+ {832, nullptr, "PrepareHidsForNotificationWake"},
+ {850, &IHidSystemServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
+ {851, nullptr, "EnableUsbFullKeyController"},
+ {852, nullptr, "IsUsbConnected"},
+ {870, &IHidSystemServer::IsHandheldButtonPressedOnConsoleMode, "IsHandheldButtonPressedOnConsoleMode"},
+ {900, nullptr, "ActivateInputDetector"},
+ {901, nullptr, "NotifyInputDetector"},
+ {1000, &IHidSystemServer::InitializeFirmwareUpdate, "InitializeFirmwareUpdate"},
+ {1001, nullptr, "GetFirmwareVersion"},
+ {1002, nullptr, "GetAvailableFirmwareVersion"},
+ {1003, nullptr, "IsFirmwareUpdateAvailable"},
+ {1004, nullptr, "CheckFirmwareUpdateRequired"},
+ {1005, nullptr, "StartFirmwareUpdate"},
+ {1006, nullptr, "AbortFirmwareUpdate"},
+ {1007, nullptr, "GetFirmwareUpdateState"},
+ {1008, nullptr, "ActivateAudioControl"},
+ {1009, nullptr, "AcquireAudioControlEventHandle"},
+ {1010, nullptr, "GetAudioControlStates"},
+ {1011, nullptr, "DeactivateAudioControl"},
+ {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
+ {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
+ {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
+ {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
+ {1100, nullptr, "GetHidbusSystemServiceObject"},
+ {1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"},
+ {1130, nullptr, "InitializeUsbFirmwareUpdate"},
+ {1131, nullptr, "FinalizeUsbFirmwareUpdate"},
+ {1132, nullptr, "CheckUsbFirmwareUpdateRequired"},
+ {1133, nullptr, "StartUsbFirmwareUpdate"},
+ {1134, nullptr, "GetUsbFirmwareUpdateState"},
+ {1135, &IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory, "InitializeUsbFirmwareUpdateWithoutMemory"},
+ {1150, nullptr, "SetTouchScreenMagnification"},
+ {1151, nullptr, "GetTouchScreenFirmwareVersion"},
+ {1152, nullptr, "SetTouchScreenDefaultConfiguration"},
+ {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
+ {1154, nullptr, "IsFirmwareAvailableForNotification"},
+ {1155, nullptr, "SetForceHandheldStyleVibration"},
+ {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
+ {1157, nullptr, "CancelConnectionTrigger"},
+ {1200, nullptr, "IsButtonConfigSupported"},
+ {1201, nullptr, "IsButtonConfigEmbeddedSupported"},
+ {1202, nullptr, "DeleteButtonConfig"},
+ {1203, nullptr, "DeleteButtonConfigEmbedded"},
+ {1204, nullptr, "SetButtonConfigEnabled"},
+ {1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
+ {1206, nullptr, "IsButtonConfigEnabled"},
+ {1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
+ {1208, nullptr, "SetButtonConfigEmbedded"},
+ {1209, nullptr, "SetButtonConfigFull"},
+ {1210, nullptr, "SetButtonConfigLeft"},
+ {1211, nullptr, "SetButtonConfigRight"},
+ {1212, nullptr, "GetButtonConfigEmbedded"},
+ {1213, nullptr, "GetButtonConfigFull"},
+ {1214, nullptr, "GetButtonConfigLeft"},
+ {1215, nullptr, "GetButtonConfigRight"},
+ {1250, nullptr, "IsCustomButtonConfigSupported"},
+ {1251, nullptr, "IsDefaultButtonConfigEmbedded"},
+ {1252, nullptr, "IsDefaultButtonConfigFull"},
+ {1253, nullptr, "IsDefaultButtonConfigLeft"},
+ {1254, nullptr, "IsDefaultButtonConfigRight"},
+ {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
+ {1256, nullptr, "IsButtonConfigStorageFullEmpty"},
+ {1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
+ {1258, nullptr, "IsButtonConfigStorageRightEmpty"},
+ {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
+ {1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
+ {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
+ {1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
+ {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
+ {1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
+ {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
+ {1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
+ {1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
+ {1268, nullptr, "DeleteButtonConfigStorageFull"},
+ {1269, nullptr, "DeleteButtonConfigStorageLeft"},
+ {1270, nullptr, "DeleteButtonConfigStorageRight"},
+ {1271, nullptr, "IsUsingCustomButtonConfig"},
+ {1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
+ {1273, nullptr, "SetAllCustomButtonConfigEnabled"},
+ {1274, nullptr, "SetDefaultButtonConfig"},
+ {1275, nullptr, "SetAllDefaultButtonConfig"},
+ {1276, nullptr, "SetHidButtonConfigEmbedded"},
+ {1277, nullptr, "SetHidButtonConfigFull"},
+ {1278, nullptr, "SetHidButtonConfigLeft"},
+ {1279, nullptr, "SetHidButtonConfigRight"},
+ {1280, nullptr, "GetHidButtonConfigEmbedded"},
+ {1281, nullptr, "GetHidButtonConfigFull"},
+ {1282, nullptr, "GetHidButtonConfigLeft"},
+ {1283, nullptr, "GetHidButtonConfigRight"},
+ {1284, nullptr, "GetButtonConfigStorageEmbedded"},
+ {1285, nullptr, "GetButtonConfigStorageFull"},
+ {1286, nullptr, "GetButtonConfigStorageLeft"},
+ {1287, nullptr, "GetButtonConfigStorageRight"},
+ {1288, nullptr, "SetButtonConfigStorageEmbedded"},
+ {1289, nullptr, "SetButtonConfigStorageFull"},
+ {1290, nullptr, "DeleteButtonConfigStorageRight"},
+ {1291, nullptr, "DeleteButtonConfigStorageRight"},
};
// clang-format on
@@ -240,9 +240,7 @@ IHidSystemServer::~IHidSystemServer() {
void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "called");
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .ApplyNpadSystemCommonPolicy();
+ GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -273,9 +271,7 @@ void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) {
void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "called");
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .ApplyNpadSystemCommonPolicy();
+ GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -304,10 +300,7 @@ void IHidSystemServer::GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx) {
LOG_INFO(Service_HID, "(STUBBED) called");
Core::HID::NpadStyleSet supported_styleset =
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .GetSupportedStyleSet()
- .raw;
+ GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
@@ -320,10 +313,7 @@ void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) {
LOG_INFO(Service_HID, "(STUBBED) called");
Core::HID::NpadStyleSet supported_styleset =
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .GetSupportedStyleSet()
- .raw;
+ GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
@@ -337,10 +327,8 @@ void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called, npad_id_type={}",
npad_id_type); // Spams a lot when controller applet is running
- const Service::HID::Controller_NPad::AppletDetailedUiType detailed_ui_type =
- GetResourceManager()
- ->GetController<Controller_NPad>(HidController::NPad)
- .GetAppletDetailedUiType(npad_id_type);
+ const NPad::AppletDetailedUiType detailed_ui_type =
+ GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type);
IPC::ResponseBuilder rb{ctx, 3};
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 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hid/hid_types.h"
+#include "core/hle/service/hid/errors.h"
+
+namespace Service::HID {
+
+constexpr bool IsNpadIdValid(const Core::HID::NpadIdType npad_id) {
+ switch (npad_id) {
+ case Core::HID::NpadIdType::Player1:
+ case Core::HID::NpadIdType::Player2:
+ case Core::HID::NpadIdType::Player3:
+ case Core::HID::NpadIdType::Player4:
+ case Core::HID::NpadIdType::Player5:
+ case Core::HID::NpadIdType::Player6:
+ case Core::HID::NpadIdType::Player7:
+ case Core::HID::NpadIdType::Player8:
+ case Core::HID::NpadIdType::Other:
+ case Core::HID::NpadIdType::Handheld:
+ return true;
+ default:
+ return false;
+ }
+}
+
+constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& handle) {
+ const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id));
+ const bool device_index = handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
+
+ if (!npad_id) {
+ return InvalidNpadId;
+ }
+ if (!device_index) {
+ return NpadDeviceIndexOutOfRange;
+ }
+
+ return ResultSuccess;
+}
+
+constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) {
+ switch (handle.npad_type) {
+ case Core::HID::NpadStyleIndex::ProController:
+ case Core::HID::NpadStyleIndex::Handheld:
+ case Core::HID::NpadStyleIndex::JoyconDual:
+ case Core::HID::NpadStyleIndex::JoyconLeft:
+ case Core::HID::NpadStyleIndex::JoyconRight:
+ case Core::HID::NpadStyleIndex::GameCube:
+ case Core::HID::NpadStyleIndex::N64:
+ case Core::HID::NpadStyleIndex::SystemExt:
+ case Core::HID::NpadStyleIndex::System:
+ // These support vibration
+ break;
+ default:
+ return VibrationInvalidStyleIndex;
+ }
+
+ if (!IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id))) {
+ return VibrationInvalidNpadId;
+ }
+
+ if (handle.device_index >= Core::HID::DeviceIndex::MaxDeviceIndex) {
+ return VibrationDeviceIndexOutOfRange;
+ }
+
+ return ResultSuccess;
+}
+
+/// Converts a Core::HID::NpadIdType to an array index.
+constexpr size_t NpadIdTypeToIndex(Core::HID::NpadIdType npad_id_type) {
+ switch (npad_id_type) {
+ case Core::HID::NpadIdType::Player1:
+ return 0;
+ case Core::HID::NpadIdType::Player2:
+ return 1;
+ case Core::HID::NpadIdType::Player3:
+ return 2;
+ case Core::HID::NpadIdType::Player4:
+ return 3;
+ case Core::HID::NpadIdType::Player5:
+ return 4;
+ case Core::HID::NpadIdType::Player6:
+ return 5;
+ case Core::HID::NpadIdType::Player7:
+ return 6;
+ case Core::HID::NpadIdType::Player8:
+ return 7;
+ case Core::HID::NpadIdType::Handheld:
+ return 8;
+ case Core::HID::NpadIdType::Other:
+ return 9;
+ default:
+ return 8;
+ }
+}
+
+/// Converts an array index to a Core::HID::NpadIdType
+constexpr Core::HID::NpadIdType IndexToNpadIdType(size_t index) {
+ switch (index) {
+ case 0:
+ return Core::HID::NpadIdType::Player1;
+ case 1:
+ return Core::HID::NpadIdType::Player2;
+ case 2:
+ return Core::HID::NpadIdType::Player3;
+ case 3:
+ return Core::HID::NpadIdType::Player4;
+ case 4:
+ return Core::HID::NpadIdType::Player5;
+ case 5:
+ return Core::HID::NpadIdType::Player6;
+ case 6:
+ return Core::HID::NpadIdType::Player7;
+ case 7:
+ return Core::HID::NpadIdType::Player8;
+ case 8:
+ return Core::HID::NpadIdType::Handheld;
+ case 9:
+ return Core::HID::NpadIdType::Other;
+ default:
+ return Core::HID::NpadIdType::Invalid;
+ }
+}
+
+constexpr Core::HID::NpadStyleSet GetStylesetByIndex(std::size_t index) {
+ switch (index) {
+ case 0:
+ return Core::HID::NpadStyleSet::Fullkey;
+ case 1:
+ return Core::HID::NpadStyleSet::Handheld;
+ case 2:
+ return Core::HID::NpadStyleSet::JoyDual;
+ case 3:
+ return Core::HID::NpadStyleSet::JoyLeft;
+ case 4:
+ return Core::HID::NpadStyleSet::JoyRight;
+ case 5:
+ return Core::HID::NpadStyleSet::Palma;
+ default:
+ return Core::HID::NpadStyleSet::None;
+ }
+}
+
+} // 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 @@
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/hid/errors.h"
+#include "core/hle/service/hid/hid_util.h"
#include "core/hle/service/hid/irs.h"
#include "core/hle/service/hid/irsensor/clustering_processor.h"
#include "core/hle/service/hid/irsensor/image_transfer_processor.h"
@@ -320,7 +321,7 @@ void IRS::GetNpadIrCameraHandle(HLERequestContext& ctx) {
}
Core::IrSensor::IrCameraHandle camera_handle{
- .npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)),
+ .npad_id = static_cast<u8>(HID::NpadIdTypeToIndex(npad_id)),
.npad_type = Core::HID::NpadStyleIndex::None,
};
@@ -545,7 +546,7 @@ void IRS::ActivateIrsensorWithFunctionLevel(HLERequestContext& ctx) {
Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const {
if (camera_handle.npad_id >
- static_cast<u8>(NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) {
+ static_cast<u8>(HID::NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) {
return InvalidIrCameraHandle;
}
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 @@
#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/hid/controllers/console_sixaxis.h"
-#include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/controllers/console_six_axis.h"
#include "core/hle/service/hid/controllers/debug_pad.h"
#include "core/hle/service/hid/controllers/gesture.h"
#include "core/hle/service/hid/controllers/keyboard.h"
#include "core/hle/service/hid/controllers/mouse.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/controllers/palma.h"
+#include "core/hle/service/hid/controllers/seven_six_axis.h"
+#include "core/hle/service/hid/controllers/six_axis.h"
#include "core/hle/service/hid/controllers/stubbed.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
#include "core/hle/service/hid/controllers/xpad.h"
@@ -42,76 +43,132 @@ void ResourceManager::Initialize() {
}
u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
- MakeController<Controller_DebugPad>(HidController::DebugPad, shared_memory);
- MakeController<Controller_Touchscreen>(HidController::Touchscreen, shared_memory);
- MakeController<Controller_Mouse>(HidController::Mouse, shared_memory);
- MakeController<Controller_Keyboard>(HidController::Keyboard, shared_memory);
- MakeController<Controller_XPad>(HidController::XPad, shared_memory);
- MakeController<Controller_Stubbed>(HidController::HomeButton, shared_memory);
- MakeController<Controller_Stubbed>(HidController::SleepButton, shared_memory);
- MakeController<Controller_Stubbed>(HidController::CaptureButton, shared_memory);
- MakeController<Controller_Stubbed>(HidController::InputDetector, shared_memory);
- MakeController<Controller_Stubbed>(HidController::UniquePad, shared_memory);
- MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory);
- MakeController<Controller_Gesture>(HidController::Gesture, shared_memory);
- MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory);
- MakeController<Controller_Stubbed>(HidController::DebugMouse, shared_memory);
- MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory);
+ debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory);
+ mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory);
+ debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory);
+ keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory);
+ unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory);
+ npad = std::make_shared<NPad>(system.HIDCore(), shared_memory, service_context);
+ gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory);
+ touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory);
+ xpad = std::make_shared<XPad>(system.HIDCore(), shared_memory);
+
+ palma = std::make_shared<Palma>(system.HIDCore(), shared_memory, service_context);
+
+ home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory);
+ sleep_button = std::make_shared<SleepButton>(system.HIDCore(), shared_memory);
+ capture_button = std::make_shared<CaptureButton>(system.HIDCore(), shared_memory);
+
+ six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
+ console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory);
+ seven_six_axis = std::make_shared<SevenSixAxis>(system);
+
+ home_button->SetCommonHeaderOffset(0x4C00);
+ sleep_button->SetCommonHeaderOffset(0x4E00);
+ capture_button->SetCommonHeaderOffset(0x5000);
+ unique_pad->SetCommonHeaderOffset(0x5A00);
+ debug_mouse->SetCommonHeaderOffset(0x3DC00);
// Homebrew doesn't try to activate some controllers, so we activate them by default
- GetController<Controller_NPad>(HidController::NPad).Activate();
- GetController<Controller_Touchscreen>(HidController::Touchscreen).Activate();
-
- GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
- GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
- GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
- GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
- GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
- GetController<Controller_Stubbed>(HidController::DebugMouse).SetCommonHeaderOffset(0x3DC00);
+ npad->Activate();
+ six_axis->Activate();
+ touch_screen->Activate();
system.HIDCore().ReloadInputDevices();
is_initialized = true;
}
+std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const {
+ return capture_button;
+}
+
+std::shared_ptr<ConsoleSixAxis> ResourceManager::GetConsoleSixAxis() const {
+ return console_six_axis;
+}
+
+std::shared_ptr<DebugMouse> ResourceManager::GetDebugMouse() const {
+ return debug_mouse;
+}
+
+std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
+ return debug_pad;
+}
+
+std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
+ return gesture;
+}
+
+std::shared_ptr<HomeButton> ResourceManager::GetHomeButton() const {
+ return home_button;
+}
+
+std::shared_ptr<Keyboard> ResourceManager::GetKeyboard() const {
+ return keyboard;
+}
+
+std::shared_ptr<Mouse> ResourceManager::GetMouse() const {
+ return mouse;
+}
+
+std::shared_ptr<NPad> ResourceManager::GetNpad() const {
+ return npad;
+}
+
+std::shared_ptr<Palma> ResourceManager::GetPalma() const {
+ return palma;
+}
+
+std::shared_ptr<SevenSixAxis> ResourceManager::GetSevenSixAxis() const {
+ return seven_six_axis;
+}
+
+std::shared_ptr<SixAxis> ResourceManager::GetSixAxis() const {
+ return six_axis;
+}
+
+std::shared_ptr<SleepButton> ResourceManager::GetSleepButton() const {
+ return sleep_button;
+}
+
+std::shared_ptr<TouchScreen> ResourceManager::GetTouchScreen() const {
+ return touch_screen;
+}
+
+std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const {
+ return unique_pad;
+}
void ResourceManager::UpdateControllers(std::uintptr_t user_data,
std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
-
- for (const auto& controller : controllers) {
- // Keyboard has it's own update event
- if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
- continue;
- }
- // Mouse has it's own update event
- if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
- continue;
- }
- // Npad has it's own update event
- if (controller == controllers[static_cast<size_t>(HidController::NPad)]) {
- continue;
- }
- controller->OnUpdate(core_timing);
- }
+ debug_pad->OnUpdate(core_timing);
+ unique_pad->OnUpdate(core_timing);
+ gesture->OnUpdate(core_timing);
+ touch_screen->OnUpdate(core_timing);
+ palma->OnUpdate(core_timing);
+ home_button->OnUpdate(core_timing);
+ sleep_button->OnUpdate(core_timing);
+ capture_button->OnUpdate(core_timing);
+ xpad->OnUpdate(core_timing);
}
void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
-
- controllers[static_cast<size_t>(HidController::NPad)]->OnUpdate(core_timing);
+ npad->OnUpdate(core_timing);
}
void ResourceManager::UpdateMouseKeyboard(std::uintptr_t user_data,
std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
-
- controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(core_timing);
- controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(core_timing);
+ mouse->OnUpdate(core_timing);
+ debug_mouse->OnUpdate(core_timing);
+ keyboard->OnUpdate(core_timing);
}
void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
-
- controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(core_timing);
+ six_axis->OnUpdate(core_timing);
+ seven_six_axis->OnUpdate(core_timing);
+ console_six_axis->OnUpdate(core_timing);
}
IAppletResource::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 @@
#pragma once
-#include <chrono>
-
-#include "core/core.h"
-#include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
@@ -14,74 +10,85 @@ namespace Core::Timing {
struct EventType;
}
-namespace Core::HID {
-class HIDCore;
-}
-
namespace Service::HID {
+class Controller_Stubbed;
+class ConsoleSixAxis;
+class DebugPad;
+class Gesture;
+class Keyboard;
+class Mouse;
+class NPad;
+class Palma;
+class SevenSixAxis;
+class SixAxis;
+class TouchScreen;
+class XPad;
+
+using CaptureButton = Controller_Stubbed;
+using DebugMouse = Controller_Stubbed;
+using HomeButton = Controller_Stubbed;
+using SleepButton = Controller_Stubbed;
+using UniquePad = Controller_Stubbed;
-enum class HidController : std::size_t {
- DebugPad,
- Touchscreen,
- Mouse,
- Keyboard,
- XPad,
- HomeButton,
- SleepButton,
- CaptureButton,
- InputDetector,
- UniquePad,
- NPad,
- Gesture,
- ConsoleSixAxisSensor,
- DebugMouse,
- Palma,
-
- MaxControllers,
-};
class ResourceManager {
+
public:
explicit ResourceManager(Core::System& system_);
~ResourceManager();
- template <typename T>
- T& GetController(HidController controller) {
- return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
- }
-
- template <typename T>
- const T& GetController(HidController controller) const {
- return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
- }
-
void Initialize();
+ std::shared_ptr<CaptureButton> GetCaptureButton() const;
+ std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const;
+ std::shared_ptr<DebugMouse> GetDebugMouse() const;
+ std::shared_ptr<DebugPad> GetDebugPad() const;
+ std::shared_ptr<Gesture> GetGesture() const;
+ std::shared_ptr<HomeButton> GetHomeButton() const;
+ std::shared_ptr<Keyboard> GetKeyboard() const;
+ std::shared_ptr<Mouse> GetMouse() const;
+ std::shared_ptr<NPad> GetNpad() const;
+ std::shared_ptr<Palma> GetPalma() const;
+ std::shared_ptr<SevenSixAxis> GetSevenSixAxis() const;
+ std::shared_ptr<SixAxis> GetSixAxis() const;
+ std::shared_ptr<SleepButton> GetSleepButton() const;
+ std::shared_ptr<TouchScreen> GetTouchScreen() const;
+ std::shared_ptr<UniquePad> GetUniquePad() const;
+
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
private:
- template <typename T>
- void MakeController(HidController controller, u8* shared_memory) {
- if constexpr (std::is_constructible_v<T, Core::System&, u8*>) {
- controllers[static_cast<std::size_t>(controller)] =
- std::make_unique<T>(system, shared_memory);
- } else {
- controllers[static_cast<std::size_t>(controller)] =
- std::make_unique<T>(system.HIDCore(), shared_memory);
- }
- }
-
- template <typename T>
- void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
- controllers[static_cast<std::size_t>(controller)] =
- std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
- }
-
bool is_initialized{false};
- std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
- controllers{};
+
+ std::shared_ptr<CaptureButton> capture_button = nullptr;
+ std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr;
+ std::shared_ptr<DebugMouse> debug_mouse = nullptr;
+ std::shared_ptr<DebugPad> debug_pad = nullptr;
+ std::shared_ptr<Gesture> gesture = nullptr;
+ std::shared_ptr<HomeButton> home_button = nullptr;
+ std::shared_ptr<Keyboard> keyboard = nullptr;
+ std::shared_ptr<Mouse> mouse = nullptr;
+ std::shared_ptr<NPad> npad = nullptr;
+ std::shared_ptr<Palma> palma = nullptr;
+ std::shared_ptr<SevenSixAxis> seven_six_axis = nullptr;
+ std::shared_ptr<SixAxis> six_axis = nullptr;
+ std::shared_ptr<SleepButton> sleep_button = nullptr;
+ std::shared_ptr<TouchScreen> touch_screen = nullptr;
+ std::shared_ptr<UniquePad> unique_pad = nullptr;
+ std::shared_ptr<XPad> xpad = nullptr;
+
+ // TODO: Create these resources
+ // std::shared_ptr<AudioControl> audio_control = nullptr;
+ // std::shared_ptr<ButtonConfig> button_config = nullptr;
+ // std::shared_ptr<Config> config = nullptr;
+ // std::shared_ptr<Connection> connection = nullptr;
+ // std::shared_ptr<CustomConfig> custom_config = nullptr;
+ // std::shared_ptr<Digitizer> digitizer = nullptr;
+ // std::shared_ptr<Hdls> hdls = nullptr;
+ // std::shared_ptr<PlayReport> play_report = nullptr;
+ // std::shared_ptr<Rail> rail = nullptr;
Core::System& system;
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 @@
#include "core/core.h"
#include "core/hid/hid_types.h"
#include "core/hle/kernel/k_event.h"
+#include "core/hle/service/hid/hid_util.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/nfc/common/device.h"
#include "core/hle/service/nfc/common/device_manager.h"
@@ -24,7 +25,7 @@ DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContex
for (u32 device_index = 0; device_index < devices.size(); device_index++) {
devices[device_index] =
- std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
+ std::make_shared<NfcDevice>(HID::IndexToNpadIdType(device_index), system,
service_context, availability_change_event);
}
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp
index 19c667b42..f5edfdc8b 100644
--- a/src/core/hle/service/set/set_sys.cpp
+++ b/src/core/hle/service/set/set_sys.cpp
@@ -19,19 +19,8 @@
namespace Service::Set {
-namespace {
-constexpr u64 SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET = 0x05;
-
-enum class GetFirmwareVersionType {
- Version1,
- Version2,
-};
-
-void GetFirmwareVersionImpl(Core::System& system, HLERequestContext& ctx,
- GetFirmwareVersionType type) {
- ASSERT_MSG(ctx.GetWriteBufferSize() == 0x100,
- "FirmwareVersion output buffer must be 0x100 bytes in size!");
-
+Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system,
+ GetFirmwareVersionType type) {
constexpr u64 FirmwareVersionSystemDataId = 0x0100000000000809;
auto& fsc = system.GetFileSystemController();
@@ -52,39 +41,34 @@ void GetFirmwareVersionImpl(Core::System& system, HLERequestContext& ctx,
FileSys::SystemArchive::SynthesizeSystemArchive(FirmwareVersionSystemDataId));
}
- const auto early_exit_failure = [&ctx](std::string_view desc, Result code) {
+ const auto early_exit_failure = [](std::string_view desc, Result code) {
LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).",
desc);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(code);
+ return code;
};
const auto ver_file = romfs->GetFile("file");
if (ver_file == nullptr) {
- early_exit_failure("The system version archive didn't contain the file 'file'.",
- FileSys::ERROR_INVALID_ARGUMENT);
- return;
+ return early_exit_failure("The system version archive didn't contain the file 'file'.",
+ FileSys::ERROR_INVALID_ARGUMENT);
}
auto data = ver_file->ReadAllBytes();
- if (data.size() != 0x100) {
- early_exit_failure("The system version file 'file' was not the correct size.",
- FileSys::ERROR_OUT_OF_BOUNDS);
- return;
+ if (data.size() != sizeof(FirmwareVersionFormat)) {
+ return early_exit_failure("The system version file 'file' was not the correct size.",
+ FileSys::ERROR_OUT_OF_BOUNDS);
}
+ std::memcpy(&out_firmware, data.data(), sizeof(FirmwareVersionFormat));
+
// If the command is GetFirmwareVersion (as opposed to GetFirmwareVersion2), hardware will
// zero out the REVISION_MINOR field.
if (type == GetFirmwareVersionType::Version1) {
- data[SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET] = 0;
+ out_firmware.revision_minor = 0;
}
- ctx.WriteBuffer(data);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ return ResultSuccess;
}
-} // Anonymous namespace
void SET_SYS::SetLanguageCode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -98,12 +82,32 @@ void SET_SYS::SetLanguageCode(HLERequestContext& ctx) {
void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
- GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version1);
+
+ FirmwareVersionFormat firmware_data{};
+ const auto result =
+ GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version1);
+
+ if (result.IsSuccess()) {
+ ctx.WriteBuffer(firmware_data);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
}
void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
- GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version2);
+
+ FirmwareVersionFormat firmware_data{};
+ const auto result =
+ GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version2);
+
+ if (result.IsSuccess()) {
+ ctx.WriteBuffer(firmware_data);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
}
void SET_SYS::GetAccountSettings(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h
index 93023c6dd..5f770fd32 100644
--- a/src/core/hle/service/set/set_sys.h
+++ b/src/core/hle/service/set/set_sys.h
@@ -4,6 +4,7 @@
#pragma once
#include "common/uuid.h"
+#include "core/hle/result.h"
#include "core/hle/service/service.h"
#include "core/hle/service/time/clock_types.h"
@@ -12,6 +13,29 @@ class System;
}
namespace Service::Set {
+enum class LanguageCode : u64;
+enum class GetFirmwareVersionType {
+ Version1,
+ Version2,
+};
+
+struct FirmwareVersionFormat {
+ u8 major;
+ u8 minor;
+ u8 micro;
+ INSERT_PADDING_BYTES(1);
+ u8 revision_major;
+ u8 revision_minor;
+ INSERT_PADDING_BYTES(2);
+ std::array<char, 0x20> platform;
+ std::array<u8, 0x40> version_hash;
+ std::array<char, 0x18> display_version;
+ std::array<char, 0x80> display_title;
+};
+static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size");
+
+Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system,
+ GetFirmwareVersionType type);
class SET_SYS final : public ServiceFramework<SET_SYS> {
public:
diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h
index 9fc01ea90..7149fffeb 100644
--- a/src/core/hle/service/time/clock_types.h
+++ b/src/core/hle/service/time/clock_types.h
@@ -11,6 +11,11 @@
#include "core/hle/service/time/errors.h"
#include "core/hle/service/time/time_zone_types.h"
+// Defined by WinBase.h on Windows
+#ifdef GetCurrentTime
+#undef GetCurrentTime
+#endif
+
namespace Service::Time::Clock {
enum class TimeType : u8 {
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() {
return 0;
}
- const auto press_state =
- applet_resource
- ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)
- .GetAndResetPressState();
+ const auto press_state = applet_resource->GetNpad()->GetAndResetPressState();
return static_cast<u64>(press_state & HID::NpadButton::All);
}
diff --git a/src/frontend_common/CMakeLists.txt b/src/frontend_common/CMakeLists.txt
new file mode 100644
index 000000000..22e9337c4
--- /dev/null
+++ b/src/frontend_common/CMakeLists.txt
@@ -0,0 +1,10 @@
+# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+add_library(frontend_common STATIC
+ config.cpp
+ config.h
+)
+
+create_target_directory_groups(frontend_common)
+target_link_libraries(frontend_common PUBLIC core SimpleIni::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 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <algorithm>
+#include <array>
+#include "common/fs/fs.h"
+#include "common/fs/path_util.h"
+#include "common/settings.h"
+#include "common/settings_common.h"
+#include "common/settings_enums.h"
+#include "config.h"
+#include "core/core.h"
+#include "core/hle/service/acc/profile_manager.h"
+#include "core/hle/service/hid/controllers/npad.h"
+#include "network/network.h"
+
+#include <boost/algorithm/string/replace.hpp>
+
+#include "common/string_util.h"
+
+namespace FS = Common::FS;
+
+Config::Config(const ConfigType config_type)
+ : type(config_type), global{config_type == ConfigType::GlobalConfig} {}
+
+void Config::Initialize(const std::string& config_name) {
+ const std::filesystem::path fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir);
+ const auto config_file = fmt::format("{}.ini", config_name);
+
+ switch (type) {
+ case ConfigType::GlobalConfig:
+ config_loc = FS::PathToUTF8String(fs_config_loc / config_file);
+ void(FS::CreateParentDir(config_loc));
+ SetUpIni();
+ Reload();
+ break;
+ case ConfigType::PerGameConfig:
+ config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file));
+ void(FS::CreateParentDir(config_loc));
+ SetUpIni();
+ Reload();
+ break;
+ case ConfigType::InputProfile:
+ config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file);
+ void(FS::CreateParentDir(config_loc));
+ SetUpIni();
+ break;
+ }
+}
+
+void Config::Initialize(const std::optional<std::string> config_path) {
+ const std::filesystem::path default_sdl_config_path =
+ FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini";
+ config_loc = config_path.value_or(FS::PathToUTF8String(default_sdl_config_path));
+ void(FS::CreateParentDir(config_loc));
+ SetUpIni();
+ Reload();
+}
+
+void Config::WriteToIni() const {
+ FILE* fp = nullptr;
+#ifdef _WIN32
+ fp = _wfopen(Common::UTF8ToUTF16W(config_loc).data(), L"wb");
+#else
+ fp = fopen(config_loc.c_str(), "wb");
+#endif
+
+ if (fp == nullptr) {
+ LOG_ERROR(Frontend, "Config file could not be saved!");
+ return;
+ }
+
+ CSimpleIniA::FileWriter writer(fp);
+ const SI_Error rc = config->Save(writer, false);
+ if (rc < 0) {
+ LOG_ERROR(Frontend, "Config file could not be saved!");
+ }
+ fclose(fp);
+}
+
+void Config::SetUpIni() {
+ config = std::make_unique<CSimpleIniA>();
+ config->SetUnicode(true);
+ config->SetSpaces(false);
+
+ FILE* fp = nullptr;
+#ifdef _WIN32
+ _wfopen_s(&fp, Common::UTF8ToUTF16W(config_loc).data(), L"rb, ccs=UTF-8");
+ if (fp == nullptr) {
+ fp = _wfopen(Common::UTF8ToUTF16W(config_loc).data(), L"wb, ccs=UTF-8");
+ }
+#else
+ fp = fopen(config_loc.c_str(), "rb");
+ if (fp == nullptr) {
+ fp = fopen(config_loc.c_str(), "wb");
+ }
+#endif
+
+ if (fp == nullptr) {
+ LOG_ERROR(Frontend, "Config file could not be loaded!");
+ return;
+ }
+
+ if (SI_Error rc = config->LoadFile(fp); rc < 0) {
+ LOG_ERROR(Frontend, "Config file could not be loaded!");
+ }
+ fclose(fp);
+}
+
+bool Config::IsCustomConfig() const {
+ return type == ConfigType::PerGameConfig;
+}
+
+void Config::ReadPlayerValues(const std::size_t player_index) {
+ std::string player_prefix;
+ if (type != ConfigType::InputProfile) {
+ player_prefix.append("player_").append(ToString(player_index)).append("_");
+ }
+
+ auto& player = Settings::values.players.GetValue()[player_index];
+ if (IsCustomConfig()) {
+ const auto profile_name =
+ ReadStringSetting(std::string(player_prefix).append("profile_name"));
+ if (profile_name.empty()) {
+ // Use the global input config
+ player = Settings::values.players.GetValue(true)[player_index];
+ return;
+ }
+ player.profile_name = profile_name;
+ }
+
+ if (player_prefix.empty() && Settings::IsConfiguringGlobal()) {
+ const auto controller = static_cast<Settings::ControllerType>(
+ ReadIntegerSetting(std::string(player_prefix).append("type"),
+ static_cast<u8>(Settings::ControllerType::ProController)));
+
+ if (controller == Settings::ControllerType::LeftJoycon ||
+ controller == Settings::ControllerType::RightJoycon) {
+ player.controller_type = controller;
+ }
+ } else {
+ std::string connected_key = player_prefix;
+ player.connected = ReadBooleanSetting(connected_key.append("connected"),
+ std::make_optional(player_index == 0));
+
+ player.controller_type = static_cast<Settings::ControllerType>(
+ ReadIntegerSetting(std::string(player_prefix).append("type"),
+ static_cast<u8>(Settings::ControllerType::ProController)));
+
+ player.vibration_enabled = ReadBooleanSetting(
+ std::string(player_prefix).append("vibration_enabled"), std::make_optional(true));
+
+ player.vibration_strength = static_cast<int>(
+ ReadIntegerSetting(std::string(player_prefix).append("vibration_strength"), 100));
+
+ player.body_color_left = static_cast<u32>(ReadIntegerSetting(
+ std::string(player_prefix).append("body_color_left"), Settings::JOYCON_BODY_NEON_BLUE));
+ player.body_color_right = static_cast<u32>(ReadIntegerSetting(
+ std::string(player_prefix).append("body_color_right"), Settings::JOYCON_BODY_NEON_RED));
+ player.button_color_left = static_cast<u32>(
+ ReadIntegerSetting(std::string(player_prefix).append("button_color_left"),
+ Settings::JOYCON_BUTTONS_NEON_BLUE));
+ player.button_color_right = static_cast<u32>(
+ ReadIntegerSetting(std::string(player_prefix).append("button_color_right"),
+ Settings::JOYCON_BUTTONS_NEON_RED));
+ }
+}
+
+void Config::ReadTouchscreenValues() {
+ Settings::values.touchscreen.enabled =
+ ReadBooleanSetting(std::string("touchscreen_enabled"), std::make_optional(true));
+ Settings::values.touchscreen.rotation_angle =
+ static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_angle"), 0));
+ Settings::values.touchscreen.diameter_x =
+ static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_x"), 15));
+ Settings::values.touchscreen.diameter_y =
+ static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_y"), 15));
+}
+
+void Config::ReadAudioValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Audio));
+
+ ReadCategory(Settings::Category::Audio);
+ ReadCategory(Settings::Category::UiAudio);
+
+ EndGroup();
+}
+
+void Config::ReadControlValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
+
+ ReadCategory(Settings::Category::Controls);
+
+ Settings::values.players.SetGlobal(!IsCustomConfig());
+ for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
+ ReadPlayerValues(p);
+ }
+
+ // Disable docked mode if handheld is selected
+ const auto controller_type = Settings::values.players.GetValue()[0].controller_type;
+ if (controller_type == Settings::ControllerType::Handheld) {
+ Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig());
+ Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
+ }
+
+ if (IsCustomConfig()) {
+ EndGroup();
+ return;
+ }
+ ReadTouchscreenValues();
+ ReadMotionTouchValues();
+
+ EndGroup();
+}
+
+void Config::ReadMotionTouchValues() {
+ int num_touch_from_button_maps = BeginArray(std::string("touch_from_button_maps"));
+
+ if (num_touch_from_button_maps > 0) {
+ for (int i = 0; i < num_touch_from_button_maps; ++i) {
+ SetArrayIndex(i);
+
+ Settings::TouchFromButtonMap map;
+ map.name = ReadStringSetting(std::string("name"), std::string("default"));
+
+ const int num_touch_maps = BeginArray(std::string("entries"));
+ map.buttons.reserve(num_touch_maps);
+ for (int j = 0; j < num_touch_maps; j++) {
+ SetArrayIndex(j);
+ std::string touch_mapping = ReadStringSetting(std::string("bind"));
+ map.buttons.emplace_back(std::move(touch_mapping));
+ }
+ EndArray(); // entries
+ Settings::values.touch_from_button_maps.emplace_back(std::move(map));
+ }
+ } else {
+ Settings::values.touch_from_button_maps.emplace_back(
+ Settings::TouchFromButtonMap{"default", {}});
+ num_touch_from_button_maps = 1;
+ }
+ EndArray(); // touch_from_button_maps
+
+ Settings::values.touch_from_button_map_index = std::clamp(
+ Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
+}
+
+void Config::ReadCoreValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Core));
+
+ ReadCategory(Settings::Category::Core);
+
+ EndGroup();
+}
+
+void Config::ReadDataStorageValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
+
+ FS::SetYuzuPath(FS::YuzuPath::NANDDir, ReadStringSetting(std::string("nand_directory")));
+ FS::SetYuzuPath(FS::YuzuPath::SDMCDir, ReadStringSetting(std::string("sdmc_directory")));
+ FS::SetYuzuPath(FS::YuzuPath::LoadDir, ReadStringSetting(std::string("load_directory")));
+ FS::SetYuzuPath(FS::YuzuPath::DumpDir, ReadStringSetting(std::string("dump_directory")));
+ FS::SetYuzuPath(FS::YuzuPath::TASDir, ReadStringSetting(std::string("tas_directory")));
+
+ ReadCategory(Settings::Category::DataStorage);
+
+ EndGroup();
+}
+
+void Config::ReadDebuggingValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
+
+ // Intentionally not using the QT default setting as this is intended to be changed in the ini
+ Settings::values.record_frame_times =
+ ReadBooleanSetting(std::string("record_frame_times"), std::make_optional(false));
+
+ ReadCategory(Settings::Category::Debugging);
+ ReadCategory(Settings::Category::DebuggingGraphics);
+
+ EndGroup();
+}
+
+void Config::ReadServiceValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
+
+ ReadCategory(Settings::Category::Services);
+
+ EndGroup();
+}
+
+void Config::ReadDisabledAddOnValues() {
+ // Custom config section
+ BeginGroup(std::string("DisabledAddOns"));
+
+ const int size = BeginArray(std::string(""));
+ for (int i = 0; i < size; ++i) {
+ SetArrayIndex(i);
+ const auto title_id = ReadUnsignedIntegerSetting(std::string("title_id"), 0);
+ std::vector<std::string> out;
+ const int d_size = BeginArray("disabled");
+ for (int j = 0; j < d_size; ++j) {
+ SetArrayIndex(j);
+ out.push_back(ReadStringSetting(std::string("d"), std::string("")));
+ }
+ EndArray(); // d
+ Settings::values.disabled_addons.insert_or_assign(title_id, out);
+ }
+ EndArray(); // Base disabled addons array - Has no base key
+
+ EndGroup();
+}
+
+void Config::ReadMiscellaneousValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous));
+
+ ReadCategory(Settings::Category::Miscellaneous);
+
+ EndGroup();
+}
+
+void Config::ReadCpuValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Cpu));
+
+ ReadCategory(Settings::Category::Cpu);
+ ReadCategory(Settings::Category::CpuDebug);
+ ReadCategory(Settings::Category::CpuUnsafe);
+
+ EndGroup();
+}
+
+void Config::ReadRendererValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Renderer));
+
+ ReadCategory(Settings::Category::Renderer);
+ ReadCategory(Settings::Category::RendererAdvanced);
+ ReadCategory(Settings::Category::RendererDebug);
+
+ EndGroup();
+}
+
+void Config::ReadScreenshotValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots));
+
+ ReadCategory(Settings::Category::Screenshots);
+ FS::SetYuzuPath(FS::YuzuPath::ScreenshotsDir,
+ ReadStringSetting(std::string("screenshot_path")));
+
+ EndGroup();
+}
+
+void Config::ReadSystemValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::System));
+
+ ReadCategory(Settings::Category::System);
+ ReadCategory(Settings::Category::SystemAudio);
+
+ EndGroup();
+}
+
+void Config::ReadWebServiceValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::WebService));
+
+ ReadCategory(Settings::Category::WebService);
+
+ EndGroup();
+}
+
+void Config::ReadNetworkValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
+
+ ReadCategory(Settings::Category::Network);
+
+ EndGroup();
+}
+
+void Config::ReadValues() {
+ if (global) {
+ ReadDataStorageValues();
+ ReadDebuggingValues();
+ ReadDisabledAddOnValues();
+ ReadNetworkValues();
+ ReadServiceValues();
+ ReadWebServiceValues();
+ ReadMiscellaneousValues();
+ }
+ ReadControlValues();
+ ReadCoreValues();
+ ReadCpuValues();
+ ReadRendererValues();
+ ReadAudioValues();
+ ReadSystemValues();
+}
+
+void Config::SavePlayerValues(const std::size_t player_index) {
+ std::string player_prefix;
+ if (type != ConfigType::InputProfile) {
+ player_prefix = std::string("player_").append(ToString(player_index)).append("_");
+ }
+
+ const auto& player = Settings::values.players.GetValue()[player_index];
+ if (IsCustomConfig()) {
+ if (player.profile_name.empty()) {
+ // No custom profile selected
+ return;
+ }
+ WriteSetting(std::string(player_prefix).append("profile_name"), player.profile_name,
+ std::make_optional(std::string("")));
+ }
+
+ WriteSetting(std::string(player_prefix).append("type"), static_cast<u8>(player.controller_type),
+ std::make_optional(static_cast<u8>(Settings::ControllerType::ProController)));
+
+ if (!player_prefix.empty() || !Settings::IsConfiguringGlobal()) {
+ WriteSetting(std::string(player_prefix).append("connected"), player.connected,
+ std::make_optional(player_index == 0));
+ WriteSetting(std::string(player_prefix).append("vibration_enabled"),
+ player.vibration_enabled, std::make_optional(true));
+ WriteSetting(std::string(player_prefix).append("vibration_strength"),
+ player.vibration_strength, std::make_optional(100));
+ WriteSetting(std::string(player_prefix).append("body_color_left"), player.body_color_left,
+ std::make_optional(Settings::JOYCON_BODY_NEON_BLUE));
+ WriteSetting(std::string(player_prefix).append("body_color_right"), player.body_color_right,
+ std::make_optional(Settings::JOYCON_BODY_NEON_RED));
+ WriteSetting(std::string(player_prefix).append("button_color_left"),
+ player.button_color_left,
+ std::make_optional(Settings::JOYCON_BUTTONS_NEON_BLUE));
+ WriteSetting(std::string(player_prefix).append("button_color_right"),
+ player.button_color_right,
+ std::make_optional(Settings::JOYCON_BUTTONS_NEON_RED));
+ }
+}
+
+void Config::SaveTouchscreenValues() {
+ const auto& touchscreen = Settings::values.touchscreen;
+
+ WriteSetting(std::string("touchscreen_enabled"), touchscreen.enabled, std::make_optional(true));
+
+ WriteSetting(std::string("touchscreen_angle"), touchscreen.rotation_angle,
+ std::make_optional(static_cast<u32>(0)));
+ WriteSetting(std::string("touchscreen_diameter_x"), touchscreen.diameter_x,
+ std::make_optional(static_cast<u32>(15)));
+ WriteSetting(std::string("touchscreen_diameter_y"), touchscreen.diameter_y,
+ std::make_optional(static_cast<u32>(15)));
+}
+
+void Config::SaveMotionTouchValues() {
+ BeginArray(std::string("touch_from_button_maps"));
+ for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
+ SetArrayIndex(static_cast<int>(p));
+ WriteSetting(std::string("name"), Settings::values.touch_from_button_maps[p].name,
+ std::make_optional(std::string("default")));
+
+ BeginArray(std::string("entries"));
+ for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size();
+ ++q) {
+ SetArrayIndex(static_cast<int>(q));
+ WriteSetting(std::string("bind"),
+ Settings::values.touch_from_button_maps[p].buttons[q]);
+ }
+ EndArray(); // entries
+ }
+ EndArray(); // touch_from_button_maps
+}
+
+void Config::SaveValues() {
+ if (global) {
+ SaveDataStorageValues();
+ SaveDebuggingValues();
+ SaveDisabledAddOnValues();
+ SaveNetworkValues();
+ SaveWebServiceValues();
+ SaveMiscellaneousValues();
+ }
+ SaveControlValues();
+ SaveCoreValues();
+ SaveCpuValues();
+ SaveRendererValues();
+ SaveAudioValues();
+ SaveSystemValues();
+
+ WriteToIni();
+}
+
+void Config::SaveAudioValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Audio));
+
+ WriteCategory(Settings::Category::Audio);
+ WriteCategory(Settings::Category::UiAudio);
+
+ EndGroup();
+}
+
+void Config::SaveControlValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
+
+ WriteCategory(Settings::Category::Controls);
+
+ Settings::values.players.SetGlobal(!IsCustomConfig());
+ for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
+ SavePlayerValues(p);
+ }
+ if (IsCustomConfig()) {
+ EndGroup();
+ return;
+ }
+ SaveTouchscreenValues();
+ SaveMotionTouchValues();
+
+ EndGroup();
+}
+
+void Config::SaveCoreValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Core));
+
+ WriteCategory(Settings::Category::Core);
+
+ EndGroup();
+}
+
+void Config::SaveDataStorageValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
+
+ WriteSetting(std::string("nand_directory"), FS::GetYuzuPathString(FS::YuzuPath::NANDDir),
+ std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
+ WriteSetting(std::string("sdmc_directory"), FS::GetYuzuPathString(FS::YuzuPath::SDMCDir),
+ std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
+ WriteSetting(std::string("load_directory"), FS::GetYuzuPathString(FS::YuzuPath::LoadDir),
+ std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
+ WriteSetting(std::string("dump_directory"), FS::GetYuzuPathString(FS::YuzuPath::DumpDir),
+ std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
+ WriteSetting(std::string("tas_directory"), FS::GetYuzuPathString(FS::YuzuPath::TASDir),
+ std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::TASDir)));
+
+ WriteCategory(Settings::Category::DataStorage);
+
+ EndGroup();
+}
+
+void Config::SaveDebuggingValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
+
+ // Intentionally not using the QT default setting as this is intended to be changed in the ini
+ WriteSetting(std::string("record_frame_times"), Settings::values.record_frame_times);
+
+ WriteCategory(Settings::Category::Debugging);
+ WriteCategory(Settings::Category::DebuggingGraphics);
+
+ EndGroup();
+}
+
+void Config::SaveNetworkValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
+
+ WriteCategory(Settings::Category::Network);
+
+ EndGroup();
+}
+
+void Config::SaveDisabledAddOnValues() {
+ // Custom config section
+ BeginGroup(std::string("DisabledAddOns"));
+
+ int i = 0;
+ BeginArray(std::string(""));
+ for (const auto& elem : Settings::values.disabled_addons) {
+ SetArrayIndex(i);
+ WriteSetting(std::string("title_id"), elem.first, std::make_optional(static_cast<u64>(0)));
+ BeginArray(std::string("disabled"));
+ for (std::size_t j = 0; j < elem.second.size(); ++j) {
+ SetArrayIndex(static_cast<int>(j));
+ WriteSetting(std::string("d"), elem.second[j], std::make_optional(std::string("")));
+ }
+ EndArray(); // disabled
+ ++i;
+ }
+ EndArray(); // Base disabled addons array - Has no base key
+
+ EndGroup();
+}
+
+void Config::SaveMiscellaneousValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous));
+
+ WriteCategory(Settings::Category::Miscellaneous);
+
+ EndGroup();
+}
+
+void Config::SaveCpuValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Cpu));
+
+ WriteCategory(Settings::Category::Cpu);
+ WriteCategory(Settings::Category::CpuDebug);
+ WriteCategory(Settings::Category::CpuUnsafe);
+
+ EndGroup();
+}
+
+void Config::SaveRendererValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Renderer));
+
+ WriteCategory(Settings::Category::Renderer);
+ WriteCategory(Settings::Category::RendererAdvanced);
+ WriteCategory(Settings::Category::RendererDebug);
+
+ EndGroup();
+}
+
+void Config::SaveScreenshotValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots));
+
+ WriteSetting(std::string("screenshot_path"),
+ FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir));
+ WriteCategory(Settings::Category::Screenshots);
+
+ EndGroup();
+}
+
+void Config::SaveSystemValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::System));
+
+ WriteCategory(Settings::Category::System);
+ WriteCategory(Settings::Category::SystemAudio);
+
+ EndGroup();
+}
+
+void Config::SaveWebServiceValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::WebService));
+
+ WriteCategory(Settings::Category::WebService);
+
+ EndGroup();
+}
+
+bool Config::ReadBooleanSetting(const std::string& key, const std::optional<bool> default_value) {
+ std::string full_key = GetFullKey(key, false);
+ if (!default_value.has_value()) {
+ return config->GetBoolValue(GetSection().c_str(), full_key.c_str(), false);
+ }
+
+ if (config->GetBoolValue(GetSection().c_str(),
+ std::string(full_key).append("\\default").c_str(), false)) {
+ return static_cast<bool>(default_value.value());
+ } else {
+ return config->GetBoolValue(GetSection().c_str(), full_key.c_str(),
+ static_cast<bool>(default_value.value()));
+ }
+}
+
+s64 Config::ReadIntegerSetting(const std::string& key, const std::optional<s64> default_value) {
+ std::string full_key = GetFullKey(key, false);
+ if (!default_value.has_value()) {
+ try {
+ return std::stoll(
+ std::string(config->GetValue(GetSection().c_str(), full_key.c_str(), "0")));
+ } catch (...) {
+ return 0;
+ }
+ }
+
+ s64 result = 0;
+ if (config->GetBoolValue(GetSection().c_str(),
+ std::string(full_key).append("\\default").c_str(), true)) {
+ result = default_value.value();
+ } else {
+ try {
+ result = std::stoll(std::string(config->GetValue(
+ GetSection().c_str(), full_key.c_str(), ToString(default_value.value()).c_str())));
+ } catch (...) {
+ result = default_value.value();
+ }
+ }
+ return result;
+}
+
+u64 Config::ReadUnsignedIntegerSetting(const std::string& key,
+ const std::optional<u64> default_value) {
+ std::string full_key = GetFullKey(key, false);
+ if (!default_value.has_value()) {
+ try {
+ return std::stoull(
+ std::string(config->GetValue(GetSection().c_str(), full_key.c_str(), "0")));
+ } catch (...) {
+ return 0;
+ }
+ }
+
+ u64 result = 0;
+ if (config->GetBoolValue(GetSection().c_str(),
+ std::string(full_key).append("\\default").c_str(), true)) {
+ result = default_value.value();
+ } else {
+ try {
+ result = std::stoull(std::string(config->GetValue(
+ GetSection().c_str(), full_key.c_str(), ToString(default_value.value()).c_str())));
+ } catch (...) {
+ result = default_value.value();
+ }
+ }
+ return result;
+}
+
+double Config::ReadDoubleSetting(const std::string& key,
+ const std::optional<double> default_value) {
+ std::string full_key = GetFullKey(key, false);
+ if (!default_value.has_value()) {
+ return config->GetDoubleValue(GetSection().c_str(), full_key.c_str(), 0);
+ }
+
+ double result;
+ if (config->GetBoolValue(GetSection().c_str(),
+ std::string(full_key).append("\\default").c_str(), true)) {
+ result = default_value.value();
+ } else {
+ result =
+ config->GetDoubleValue(GetSection().c_str(), full_key.c_str(), default_value.value());
+ }
+ return result;
+}
+
+std::string Config::ReadStringSetting(const std::string& key,
+ const std::optional<std::string> default_value) {
+ std::string result;
+ std::string full_key = GetFullKey(key, false);
+ if (!default_value.has_value()) {
+ result = config->GetValue(GetSection().c_str(), full_key.c_str(), "");
+ boost::replace_all(result, "\"", "");
+ return result;
+ }
+
+ if (config->GetBoolValue(GetSection().c_str(),
+ std::string(full_key).append("\\default").c_str(), true)) {
+ result = default_value.value();
+ } else {
+ result =
+ config->GetValue(GetSection().c_str(), full_key.c_str(), default_value.value().c_str());
+ }
+ boost::replace_all(result, "\"", "");
+ boost::replace_all(result, "//", "/");
+ return result;
+}
+
+bool Config::Exists(const std::string& section, const std::string& key) const {
+ const std::string value = config->GetValue(section.c_str(), key.c_str(), "");
+ return !value.empty();
+}
+
+template <typename Type>
+void Config::WriteSetting(const std::string& key, const Type& value,
+ const std::optional<Type>& default_value,
+ const std::optional<bool>& use_global) {
+ std::string full_key = GetFullKey(key, false);
+
+ std::string saved_value;
+ std::string string_default;
+ if constexpr (std::is_same_v<Type, std::string>) {
+ saved_value.append(AdjustOutputString(value));
+ if (default_value.has_value()) {
+ string_default.append(AdjustOutputString(default_value.value()));
+ }
+ } else {
+ saved_value.append(AdjustOutputString(ToString(value)));
+ if (default_value.has_value()) {
+ string_default.append(ToString(default_value.value()));
+ }
+ }
+
+ if (default_value.has_value() && use_global.has_value()) {
+ if (!global) {
+ WriteSettingInternal(std::string(full_key).append("\\global"),
+ ToString(use_global.value()));
+ }
+ if (global || use_global.value() == false) {
+ WriteSettingInternal(std::string(full_key).append("\\default"),
+ ToString(string_default == saved_value));
+ WriteSettingInternal(full_key, saved_value);
+ }
+ } else if (default_value.has_value() && !use_global.has_value()) {
+ WriteSettingInternal(std::string(full_key).append("\\default"),
+ ToString(string_default == saved_value));
+ WriteSettingInternal(full_key, saved_value);
+ } else {
+ WriteSettingInternal(full_key, saved_value);
+ }
+}
+
+void Config::WriteSettingInternal(const std::string& key, const std::string& value) {
+ config->SetValue(GetSection().c_str(), key.c_str(), value.c_str());
+}
+
+void Config::Reload() {
+ ReadValues();
+ // To apply default value changes
+ SaveValues();
+}
+
+void Config::Save() {
+ SaveValues();
+}
+
+void Config::ClearControlPlayerValues() const {
+ // If key is an empty string, all keys in the current group() are removed.
+ const char* section = Settings::TranslateCategory(Settings::Category::Controls);
+ CSimpleIniA::TNamesDepend keys;
+ config->GetAllKeys(section, keys);
+ for (const auto& key : keys) {
+ if (std::string(config->GetValue(section, key.pItem)).empty()) {
+ config->Delete(section, key.pItem);
+ }
+ }
+}
+
+const std::string& Config::GetConfigFilePath() const {
+ return config_loc;
+}
+
+void Config::ReadCategory(const Settings::Category category) {
+ const auto& settings = FindRelevantList(category);
+ std::ranges::for_each(settings, [&](const auto& setting) { ReadSettingGeneric(setting); });
+}
+
+void Config::WriteCategory(const Settings::Category category) {
+ const auto& settings = FindRelevantList(category);
+ std::ranges::for_each(settings, [&](const auto& setting) { WriteSettingGeneric(setting); });
+}
+
+void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) {
+ if (!setting->Save() || (!setting->Switchable() && !global)) {
+ return;
+ }
+
+ const std::string key = AdjustKey(setting->GetLabel());
+ const std::string default_value(setting->DefaultToString());
+
+ bool use_global = true;
+ if (setting->Switchable() && !global) {
+ use_global =
+ ReadBooleanSetting(std::string(key).append("\\use_global"), std::make_optional(true));
+ setting->SetGlobal(use_global);
+ }
+
+ if (global || !use_global) {
+ const bool is_default =
+ ReadBooleanSetting(std::string(key).append("\\default"), std::make_optional(true));
+ if (!is_default) {
+ const std::string setting_string = ReadStringSetting(key, default_value);
+ setting->LoadString(setting_string);
+ } else {
+ // Empty string resets the Setting to default
+ setting->LoadString("");
+ }
+ }
+}
+
+void Config::WriteSettingGeneric(const Settings::BasicSetting* const setting) {
+ if (!setting->Save()) {
+ return;
+ }
+
+ std::string key = AdjustKey(setting->GetLabel());
+ if (setting->Switchable()) {
+ if (!global) {
+ WriteSetting(std::string(key).append("\\use_global"), setting->UsingGlobal());
+ }
+ if (global || !setting->UsingGlobal()) {
+ WriteSetting(std::string(key).append("\\default"),
+ setting->ToString() == setting->DefaultToString());
+ WriteSetting(key, setting->ToString());
+ }
+ } else if (global) {
+ WriteSetting(std::string(key).append("\\default"),
+ setting->ToString() == setting->DefaultToString());
+ WriteSetting(key, setting->ToString());
+ }
+}
+
+void Config::BeginGroup(const std::string& group) {
+ // You can't begin a group while reading/writing from a config array
+ ASSERT(array_stack.empty());
+
+ key_stack.push_back(AdjustKey(group));
+}
+
+void Config::EndGroup() {
+ // You can't end a group if you haven't started one yet
+ ASSERT(!key_stack.empty());
+
+ // You can't end a group when reading/writing from a config array
+ ASSERT(array_stack.empty());
+
+ key_stack.pop_back();
+}
+
+std::string Config::GetSection() {
+ if (key_stack.empty()) {
+ return std::string{""};
+ }
+
+ return key_stack.front();
+}
+
+std::string Config::GetGroup() const {
+ if (key_stack.size() <= 1) {
+ return std::string{""};
+ }
+
+ std::string key;
+ for (size_t i = 1; i < key_stack.size(); ++i) {
+ key.append(key_stack[i]).append("\\");
+ }
+ return key;
+}
+
+std::string Config::AdjustKey(const std::string& key) {
+ std::string adjusted_key(key);
+ boost::replace_all(adjusted_key, "/", "\\");
+ boost::replace_all(adjusted_key, " ", "%20");
+ return adjusted_key;
+}
+
+std::string Config::AdjustOutputString(const std::string& string) {
+ std::string adjusted_string(string);
+ boost::replace_all(adjusted_string, "\\", "/");
+
+ // Windows requires that two forward slashes are used at the start of a path for unmapped
+ // network drives so we have to watch for that here
+ if (string.substr(0, 2) == "//") {
+ boost::replace_all(adjusted_string, "//", "/");
+ adjusted_string.insert(0, "/");
+ } else {
+ boost::replace_all(adjusted_string, "//", "/");
+ }
+
+ // Needed for backwards compatibility with QSettings deserialization
+ for (const auto& special_character : special_characters) {
+ if (adjusted_string.find(special_character) != std::string::npos) {
+ adjusted_string.insert(0, "\"");
+ adjusted_string.append("\"");
+ break;
+ }
+ }
+ return adjusted_string;
+}
+
+std::string Config::GetFullKey(const std::string& key, bool skipArrayIndex) {
+ if (array_stack.empty()) {
+ return std::string(GetGroup()).append(AdjustKey(key));
+ }
+
+ std::string array_key;
+ for (size_t i = 0; i < array_stack.size(); ++i) {
+ if (!array_stack[i].name.empty()) {
+ array_key.append(array_stack[i].name).append("\\");
+ }
+
+ if (!skipArrayIndex || (array_stack.size() - 1 != i && array_stack.size() > 1)) {
+ array_key.append(ToString(array_stack[i].index)).append("\\");
+ }
+ }
+ std::string final_key = std::string(GetGroup()).append(array_key).append(AdjustKey(key));
+ return final_key;
+}
+
+int Config::BeginArray(const std::string& array) {
+ array_stack.push_back(ConfigArray{AdjustKey(array), 0, 0});
+ const int size = config->GetLongValue(GetSection().c_str(),
+ GetFullKey(std::string("size"), true).c_str(), 0);
+ array_stack.back().size = size;
+ return size;
+}
+
+void Config::EndArray() {
+ // You can't end a config array before starting one
+ ASSERT(!array_stack.empty());
+
+ // Set the array size to 0 if the array is ended without changing the index
+ int size = 0;
+ if (array_stack.back().index != 0) {
+ size = array_stack.back().size;
+ }
+
+ // Write out the size to config
+ if (key_stack.size() == 1 && array_stack.back().name.empty()) {
+ // Edge-case where the first array created doesn't have a name
+ config->SetValue(GetSection().c_str(), std::string("size").c_str(), ToString(size).c_str());
+ } else {
+ const auto key = GetFullKey(std::string("size"), true);
+ config->SetValue(GetSection().c_str(), key.c_str(), ToString(size).c_str());
+ }
+
+ array_stack.pop_back();
+}
+
+void Config::SetArrayIndex(const int index) {
+ // You can't set the array index if you haven't started one yet
+ ASSERT(!array_stack.empty());
+
+ const int array_index = index + 1;
+
+ // You can't exceed the known max size of the array by more than 1
+ ASSERT(array_stack.front().size + 1 >= array_index);
+
+ // Change the config array size to the current index since you may want
+ // to reduce the number of elements that you read back from the config
+ // in the future.
+ array_stack.back().size = array_index;
+ array_stack.back().index = array_index;
+}
diff --git a/src/frontend_common/config.h b/src/frontend_common/config.h
new file mode 100644
index 000000000..b3812af17
--- /dev/null
+++ b/src/frontend_common/config.h
@@ -0,0 +1,211 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include "common/settings.h"
+
+#define SI_NO_CONVERSION
+#include <SimpleIni.h>
+#include <boost/algorithm/string/replace.hpp>
+
+// Workaround for conflicting definition in libloaderapi.h caused by SimpleIni
+#undef LoadString
+#undef CreateFile
+#undef DeleteFile
+#undef CopyFile
+#undef CreateDirectory
+#undef MoveFile
+
+namespace Core {
+class System;
+}
+
+class Config {
+public:
+ enum class ConfigType {
+ GlobalConfig,
+ PerGameConfig,
+ InputProfile,
+ };
+
+ virtual ~Config() = default;
+
+ void ClearControlPlayerValues() const;
+
+ [[nodiscard]] const std::string& GetConfigFilePath() const;
+
+ [[nodiscard]] bool Exists(const std::string& section, const std::string& key) const;
+
+protected:
+ explicit Config(ConfigType config_type = ConfigType::GlobalConfig);
+
+ void Initialize(const std::string& config_name = "config");
+ void Initialize(std::optional<std::string> config_path);
+
+ void WriteToIni() const;
+
+ void SetUpIni();
+ [[nodiscard]] bool IsCustomConfig() const;
+
+ void Reload();
+ void Save();
+
+ /**
+ * Derived config classes must implement this so they can reload all platform-specific
+ * values and global ones.
+ */
+ virtual void ReloadAllValues() = 0;
+
+ /**
+ * Derived config classes must implement this so they can save all platform-specific
+ * and global values.
+ */
+ virtual void SaveAllValues() = 0;
+
+ void ReadValues();
+ void ReadPlayerValues(std::size_t player_index);
+
+ void ReadTouchscreenValues();
+ void ReadMotionTouchValues();
+
+ // Read functions bases off the respective config section names.
+ void ReadAudioValues();
+ void ReadControlValues();
+ void ReadCoreValues();
+ void ReadDataStorageValues();
+ void ReadDebuggingValues();
+ void ReadServiceValues();
+ void ReadDisabledAddOnValues();
+ void ReadMiscellaneousValues();
+ void ReadCpuValues();
+ void ReadRendererValues();
+ void ReadScreenshotValues();
+ void ReadSystemValues();
+ void ReadWebServiceValues();
+ void ReadNetworkValues();
+
+ // Read platform specific sections
+ virtual void ReadHidbusValues() = 0;
+ virtual void ReadDebugControlValues() = 0;
+ virtual void ReadPathValues() = 0;
+ virtual void ReadShortcutValues() = 0;
+ virtual void ReadUIValues() = 0;
+ virtual void ReadUIGamelistValues() = 0;
+ virtual void ReadUILayoutValues() = 0;
+ virtual void ReadMultiplayerValues() = 0;
+
+ void SaveValues();
+ void SavePlayerValues(std::size_t player_index);
+ void SaveTouchscreenValues();
+ void SaveMotionTouchValues();
+
+ // Save functions based off the respective config section names.
+ void SaveAudioValues();
+ void SaveControlValues();
+ void SaveCoreValues();
+ void SaveDataStorageValues();
+ void SaveDebuggingValues();
+ void SaveNetworkValues();
+ void SaveDisabledAddOnValues();
+ void SaveMiscellaneousValues();
+ void SaveCpuValues();
+ void SaveRendererValues();
+ void SaveScreenshotValues();
+ void SaveSystemValues();
+ void SaveWebServiceValues();
+
+ // Save platform specific sections
+ virtual void SaveHidbusValues() = 0;
+ virtual void SaveDebugControlValues() = 0;
+ virtual void SavePathValues() = 0;
+ virtual void SaveShortcutValues() = 0;
+ virtual void SaveUIValues() = 0;
+ virtual void SaveUIGamelistValues() = 0;
+ virtual void SaveUILayoutValues() = 0;
+ virtual void SaveMultiplayerValues() = 0;
+
+ virtual std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) = 0;
+
+ /**
+ * Reads a setting from the qt_config.
+ *
+ * @param key The setting's identifier
+ * @param default_value The value to use when the setting is not already present in the config
+ */
+ bool ReadBooleanSetting(const std::string& key,
+ std::optional<bool> default_value = std::nullopt);
+ s64 ReadIntegerSetting(const std::string& key, std::optional<s64> default_value = std::nullopt);
+ u64 ReadUnsignedIntegerSetting(const std::string& key,
+ std::optional<u64> default_value = std::nullopt);
+ double ReadDoubleSetting(const std::string& key,
+ std::optional<double> default_value = std::nullopt);
+ std::string ReadStringSetting(const std::string& key,
+ std::optional<std::string> default_value = std::nullopt);
+
+ /**
+ * Writes a setting to the qt_config.
+ *
+ * @param key The setting's idetentifier
+ * @param value Value of the setting
+ * @param default_value Default of the setting if not present in config
+ * @param use_global Specifies if the custom or global config should be in use, for custom
+ * configs
+ */
+ template <typename Type = int>
+ void WriteSetting(const std::string& key, const Type& value,
+ const std::optional<Type>& default_value = std::nullopt,
+ const std::optional<bool>& use_global = std::nullopt);
+ void WriteSettingInternal(const std::string& key, const std::string& value);
+
+ void ReadCategory(Settings::Category category);
+ void WriteCategory(Settings::Category category);
+ void ReadSettingGeneric(Settings::BasicSetting* setting);
+ void WriteSettingGeneric(const Settings::BasicSetting* setting);
+
+ template <typename T>
+ [[nodiscard]] std::string ToString(const T& value_) {
+ if constexpr (std::is_same_v<T, std::string>) {
+ return value_;
+ } else if constexpr (std::is_same_v<T, std::optional<u32>>) {
+ return value_.has_value() ? std::to_string(*value_) : "none";
+ } else if constexpr (std::is_same_v<T, bool>) {
+ return value_ ? "true" : "false";
+ } else if constexpr (std::is_same_v<T, u64>) {
+ return std::to_string(static_cast<u64>(value_));
+ } else {
+ return std::to_string(static_cast<s64>(value_));
+ }
+ }
+
+ void BeginGroup(const std::string& group);
+ void EndGroup();
+ std::string GetSection();
+ [[nodiscard]] std::string GetGroup() const;
+ static std::string AdjustKey(const std::string& key);
+ static std::string AdjustOutputString(const std::string& string);
+ std::string GetFullKey(const std::string& key, bool skipArrayIndex);
+ int BeginArray(const std::string& array);
+ void EndArray();
+ void SetArrayIndex(int index);
+
+ const ConfigType type;
+ std::unique_ptr<CSimpleIniA> config;
+ std::string config_loc;
+ const bool global;
+
+private:
+ inline static std::array<char, 19> special_characters = {'!', '#', '$', '%', '^', '&', '*',
+ '|', ';', '\'', '\"', ',', '<', '.',
+ '>', '?', '`', '~', '='};
+
+ struct ConfigArray {
+ std::string name;
+ int size;
+ int index;
+ };
+ std::vector<ConfigArray> array_stack;
+ std::vector<std::string> key_stack;
+};
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index b65b9f2a2..c22c7631c 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -15,6 +15,7 @@ add_library(video_core STATIC
buffer_cache/buffer_cache.cpp
buffer_cache/buffer_cache.h
buffer_cache/memory_tracker_base.h
+ buffer_cache/usage_tracker.h
buffer_cache/word_manager.h
cache_types.h
cdma_pusher.cpp
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index f5b10411b..90dbd352f 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -67,6 +67,7 @@ void BufferCache<P>::TickFrame() {
if (!channel_state) {
return;
}
+ runtime.TickFrame(slot_buffers);
// Calculate hits and shots and move hit bits to the right
const u32 hits = std::reduce(channel_state->uniform_cache_hits.begin(),
@@ -230,7 +231,10 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am
for (const IntervalType& add_interval : tmp_intervals) {
common_ranges.add(add_interval);
}
- runtime.CopyBuffer(dest_buffer, src_buffer, copies);
+ const auto& copy = copies[0];
+ src_buffer.MarkUsage(copy.src_offset, copy.size);
+ dest_buffer.MarkUsage(copy.dst_offset, copy.size);
+ runtime.CopyBuffer(dest_buffer, src_buffer, copies, true);
if (has_new_downloads) {
memory_tracker.MarkRegionAsGpuModified(*cpu_dest_address, amount);
}
@@ -258,9 +262,10 @@ bool BufferCache<P>::DMAClear(GPUVAddr dst_address, u64 amount, u32 value) {
common_ranges.subtract(subtract_interval);
const BufferId buffer = FindBuffer(*cpu_dst_address, static_cast<u32>(size));
- auto& dest_buffer = slot_buffers[buffer];
+ Buffer& dest_buffer = slot_buffers[buffer];
const u32 offset = dest_buffer.Offset(*cpu_dst_address);
runtime.ClearBuffer(dest_buffer, offset, size, value);
+ dest_buffer.MarkUsage(offset, size);
return true;
}
@@ -603,6 +608,7 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
VAddr orig_cpu_addr = static_cast<VAddr>(second_copy.src_offset);
const IntervalType base_interval{orig_cpu_addr, orig_cpu_addr + copy.size};
async_downloads += std::make_pair(base_interval, 1);
+ buffer.MarkUsage(copy.src_offset, copy.size);
runtime.CopyBuffer(download_staging.buffer, buffer, copies, false);
normalized_copies.push_back(second_copy);
}
@@ -621,8 +627,9 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
// Have in mind the staging buffer offset for the copy
copy.dst_offset += download_staging.offset;
const std::array copies{copy};
- runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies,
- false);
+ Buffer& buffer = slot_buffers[buffer_id];
+ buffer.MarkUsage(copy.src_offset, copy.size);
+ runtime.CopyBuffer(download_staging.buffer, buffer, copies, false);
}
runtime.PostCopyBarrier();
runtime.Finish();
@@ -742,7 +749,7 @@ void BufferCache<P>::BindHostIndexBuffer() {
{BufferCopy{.src_offset = upload_staging.offset, .dst_offset = 0, .size = size}}};
std::memcpy(upload_staging.mapped_span.data(),
draw_state.inline_index_draw_indexes.data(), size);
- runtime.CopyBuffer(buffer, upload_staging.buffer, copies);
+ runtime.CopyBuffer(buffer, upload_staging.buffer, copies, true);
} else {
buffer.ImmediateUpload(0, draw_state.inline_index_draw_indexes);
}
@@ -754,6 +761,7 @@ void BufferCache<P>::BindHostIndexBuffer() {
offset + draw_state.index_buffer.first * draw_state.index_buffer.FormatSizeInBytes();
runtime.BindIndexBuffer(buffer, new_offset, size);
} else {
+ buffer.MarkUsage(offset, size);
runtime.BindIndexBuffer(draw_state.topology, draw_state.index_buffer.format,
draw_state.index_buffer.first, draw_state.index_buffer.count,
buffer, offset, size);
@@ -790,6 +798,7 @@ void BufferCache<P>::BindHostVertexBuffers() {
const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
const u32 offset = buffer.Offset(binding.cpu_addr);
+ buffer.MarkUsage(offset, binding.size);
host_bindings.buffers.push_back(&buffer);
host_bindings.offsets.push_back(offset);
@@ -895,6 +904,7 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size;
}
+ buffer.MarkUsage(offset, size);
if constexpr (NEEDS_BIND_UNIFORM_INDEX) {
runtime.BindUniformBuffer(stage, binding_index, buffer, offset, size);
} else {
@@ -913,6 +923,7 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
SynchronizeBuffer(buffer, binding.cpu_addr, size);
const u32 offset = buffer.Offset(binding.cpu_addr);
+ buffer.MarkUsage(offset, size);
const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0;
if (is_written) {
@@ -943,6 +954,7 @@ void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) {
const u32 offset = buffer.Offset(binding.cpu_addr);
const PixelFormat format = binding.format;
+ buffer.MarkUsage(offset, size);
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
if (((channel_state->image_texture_buffers[stage] >> index) & 1) != 0) {
runtime.BindImageBuffer(buffer, offset, size, format);
@@ -975,9 +987,10 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
const u32 offset = buffer.Offset(binding.cpu_addr);
+ buffer.MarkUsage(offset, size);
host_bindings.buffers.push_back(&buffer);
host_bindings.offsets.push_back(offset);
- host_bindings.sizes.push_back(binding.size);
+ host_bindings.sizes.push_back(size);
}
if (host_bindings.buffers.size() > 0) {
runtime.BindTransformFeedbackBuffers(host_bindings);
@@ -1001,6 +1014,7 @@ void BufferCache<P>::BindHostComputeUniformBuffers() {
SynchronizeBuffer(buffer, binding.cpu_addr, size);
const u32 offset = buffer.Offset(binding.cpu_addr);
+ buffer.MarkUsage(offset, size);
if constexpr (NEEDS_BIND_UNIFORM_INDEX) {
runtime.BindComputeUniformBuffer(binding_index, buffer, offset, size);
++binding_index;
@@ -1021,6 +1035,7 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
SynchronizeBuffer(buffer, binding.cpu_addr, size);
const u32 offset = buffer.Offset(binding.cpu_addr);
+ buffer.MarkUsage(offset, size);
const bool is_written =
((channel_state->written_compute_storage_buffers >> index) & 1) != 0;
@@ -1053,6 +1068,7 @@ void BufferCache<P>::BindHostComputeTextureBuffers() {
const u32 offset = buffer.Offset(binding.cpu_addr);
const PixelFormat format = binding.format;
+ buffer.MarkUsage(offset, size);
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
if (((channel_state->image_compute_texture_buffers >> index) & 1) != 0) {
runtime.BindImageBuffer(buffer, offset, size, format);
@@ -1172,10 +1188,11 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end)) {
size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size));
}
+ const BufferId buffer_id = FindBuffer(*cpu_addr, size);
channel_state->vertex_buffers[index] = Binding{
.cpu_addr = *cpu_addr,
.size = size,
- .buffer_id = FindBuffer(*cpu_addr, size),
+ .buffer_id = buffer_id,
};
}
@@ -1401,7 +1418,8 @@ void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id,
.dst_offset = dst_base_offset,
.size = overlap.SizeBytes(),
});
- runtime.CopyBuffer(new_buffer, overlap, copies);
+ new_buffer.MarkUsage(copies[0].dst_offset, copies[0].size);
+ runtime.CopyBuffer(new_buffer, overlap, copies, true);
DeleteBuffer(overlap_id, true);
}
@@ -1414,7 +1432,9 @@ BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) {
const u32 size = static_cast<u32>(overlap.end - overlap.begin);
const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, overlap.begin, size);
auto& new_buffer = slot_buffers[new_buffer_id];
- runtime.ClearBuffer(new_buffer, 0, new_buffer.SizeBytes(), 0);
+ const size_t size_bytes = new_buffer.SizeBytes();
+ runtime.ClearBuffer(new_buffer, 0, size_bytes, 0);
+ new_buffer.MarkUsage(0, size_bytes);
for (const BufferId overlap_id : overlap.ids) {
JoinOverlap(new_buffer_id, overlap_id, !overlap.has_stream_leap);
}
@@ -1467,11 +1487,6 @@ void BufferCache<P>::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept {
template <class P>
bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, VAddr cpu_addr, u32 size) {
- return SynchronizeBufferImpl(buffer, cpu_addr, size);
-}
-
-template <class P>
-bool BufferCache<P>::SynchronizeBufferImpl(Buffer& buffer, VAddr cpu_addr, u32 size) {
boost::container::small_vector<BufferCopy, 4> copies;
u64 total_size_bytes = 0;
u64 largest_copy = 0;
@@ -1494,51 +1509,6 @@ bool BufferCache<P>::SynchronizeBufferImpl(Buffer& buffer, VAddr cpu_addr, u32 s
}
template <class P>
-bool BufferCache<P>::SynchronizeBufferNoModified(Buffer& buffer, VAddr cpu_addr, u32 size) {
- boost::container::small_vector<BufferCopy, 4> copies;
- u64 total_size_bytes = 0;
- u64 largest_copy = 0;
- IntervalSet found_sets{};
- auto make_copies = [&] {
- for (auto& interval : found_sets) {
- const std::size_t sub_size = interval.upper() - interval.lower();
- const VAddr cpu_addr_ = interval.lower();
- copies.push_back(BufferCopy{
- .src_offset = total_size_bytes,
- .dst_offset = cpu_addr_ - buffer.CpuAddr(),
- .size = sub_size,
- });
- total_size_bytes += sub_size;
- largest_copy = std::max<u64>(largest_copy, sub_size);
- }
- const std::span<BufferCopy> copies_span(copies.data(), copies.size());
- UploadMemory(buffer, total_size_bytes, largest_copy, copies_span);
- };
- memory_tracker.ForEachUploadRange(cpu_addr, size, [&](u64 cpu_addr_out, u64 range_size) {
- const VAddr base_adr = cpu_addr_out;
- const VAddr end_adr = base_adr + range_size;
- const IntervalType add_interval{base_adr, end_adr};
- found_sets.add(add_interval);
- });
- if (found_sets.empty()) {
- return true;
- }
- const IntervalType search_interval{cpu_addr, cpu_addr + size};
- auto it = common_ranges.lower_bound(search_interval);
- auto it_end = common_ranges.upper_bound(search_interval);
- if (it == common_ranges.end()) {
- make_copies();
- return false;
- }
- while (it != it_end) {
- found_sets.subtract(*it);
- it++;
- }
- make_copies();
- return false;
-}
-
-template <class P>
void BufferCache<P>::UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy,
std::span<BufferCopy> copies) {
if constexpr (USE_MEMORY_MAPS_FOR_UPLOADS) {
@@ -1586,7 +1556,8 @@ void BufferCache<P>::MappedUploadMemory([[maybe_unused]] Buffer& buffer,
// Apply the staging offset
copy.src_offset += upload_staging.offset;
}
- runtime.CopyBuffer(buffer, upload_staging.buffer, copies);
+ const bool can_reorder = runtime.CanReorderUpload(buffer, copies);
+ runtime.CopyBuffer(buffer, upload_staging.buffer, copies, true, can_reorder);
}
}
@@ -1628,7 +1599,8 @@ void BufferCache<P>::InlineMemoryImplementation(VAddr dest_address, size_t copy_
}};
u8* const src_pointer = upload_staging.mapped_span.data();
std::memcpy(src_pointer, inlined_buffer.data(), copy_size);
- runtime.CopyBuffer(buffer, upload_staging.buffer, copies);
+ const bool can_reorder = runtime.CanReorderUpload(buffer, copies);
+ runtime.CopyBuffer(buffer, upload_staging.buffer, copies, true, can_reorder);
} else {
buffer.ImmediateUpload(buffer.Offset(dest_address), inlined_buffer.first(copy_size));
}
@@ -1681,8 +1653,9 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 si
for (BufferCopy& copy : copies) {
// Modify copies to have the staging offset in mind
copy.dst_offset += download_staging.offset;
+ buffer.MarkUsage(copy.src_offset, copy.size);
}
- runtime.CopyBuffer(download_staging.buffer, buffer, copies_span);
+ runtime.CopyBuffer(download_staging.buffer, buffer, copies_span, true);
runtime.Finish();
for (const BufferCopy& copy : copies) {
const VAddr copy_cpu_addr = buffer.CpuAddr() + copy.src_offset;
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h
index eed267361..d6d696d8c 100644
--- a/src/video_core/buffer_cache/buffer_cache_base.h
+++ b/src/video_core/buffer_cache/buffer_cache_base.h
@@ -529,10 +529,6 @@ private:
bool SynchronizeBuffer(Buffer& buffer, VAddr cpu_addr, u32 size);
- bool SynchronizeBufferImpl(Buffer& buffer, VAddr cpu_addr, u32 size);
-
- bool SynchronizeBufferNoModified(Buffer& buffer, VAddr cpu_addr, u32 size);
-
void UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy,
std::span<BufferCopy> copies);
diff --git a/src/video_core/buffer_cache/usage_tracker.h b/src/video_core/buffer_cache/usage_tracker.h
new file mode 100644
index 000000000..ab05fe415
--- /dev/null
+++ b/src/video_core/buffer_cache/usage_tracker.h
@@ -0,0 +1,79 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "common/alignment.h"
+#include "common/common_types.h"
+
+namespace VideoCommon {
+
+class UsageTracker {
+ static constexpr size_t BYTES_PER_BIT_SHIFT = 6;
+ static constexpr size_t PAGE_SHIFT = 6 + BYTES_PER_BIT_SHIFT;
+ static constexpr size_t PAGE_BYTES = 1 << PAGE_SHIFT;
+
+public:
+ explicit UsageTracker(size_t size) {
+ const size_t num_pages = (size >> PAGE_SHIFT) + 1;
+ pages.resize(num_pages, 0ULL);
+ }
+
+ void Reset() noexcept {
+ std::ranges::fill(pages, 0ULL);
+ }
+
+ void Track(u64 offset, u64 size) noexcept {
+ const size_t page = offset >> PAGE_SHIFT;
+ const size_t page_end = (offset + size) >> PAGE_SHIFT;
+ TrackPage(page, offset, size);
+ if (page == page_end) {
+ return;
+ }
+ for (size_t i = page + 1; i < page_end; i++) {
+ pages[i] = ~u64{0};
+ }
+ const size_t offset_end = offset + size;
+ const size_t offset_end_page_aligned = Common::AlignDown(offset_end, PAGE_BYTES);
+ TrackPage(page_end, offset_end_page_aligned, offset_end - offset_end_page_aligned);
+ }
+
+ [[nodiscard]] bool IsUsed(u64 offset, u64 size) const noexcept {
+ const size_t page = offset >> PAGE_SHIFT;
+ const size_t page_end = (offset + size) >> PAGE_SHIFT;
+ if (IsPageUsed(page, offset, size)) {
+ return true;
+ }
+ for (size_t i = page + 1; i < page_end; i++) {
+ if (pages[i] != 0) {
+ return true;
+ }
+ }
+ const size_t offset_end = offset + size;
+ const size_t offset_end_page_aligned = Common::AlignDown(offset_end, PAGE_BYTES);
+ return IsPageUsed(page_end, offset_end_page_aligned, offset_end - offset_end_page_aligned);
+ }
+
+private:
+ void TrackPage(u64 page, u64 offset, u64 size) noexcept {
+ const size_t offset_in_page = offset % PAGE_BYTES;
+ const size_t first_bit = offset_in_page >> BYTES_PER_BIT_SHIFT;
+ const size_t num_bits = std::min(size, PAGE_BYTES) >> BYTES_PER_BIT_SHIFT;
+ const size_t mask = ~u64{0} >> (64 - num_bits);
+ pages[page] |= (~u64{0} & mask) << first_bit;
+ }
+
+ bool IsPageUsed(u64 page, u64 offset, u64 size) const noexcept {
+ const size_t offset_in_page = offset % PAGE_BYTES;
+ const size_t first_bit = offset_in_page >> BYTES_PER_BIT_SHIFT;
+ const size_t num_bits = std::min(size, PAGE_BYTES) >> BYTES_PER_BIT_SHIFT;
+ const size_t mask = ~u64{0} >> (64 - num_bits);
+ const size_t mask2 = (~u64{0} & mask) << first_bit;
+ return (pages[page] & mask2) != 0;
+ }
+
+private:
+ std::vector<u64> pages;
+};
+
+} // namespace VideoCommon
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
return;
}
if (False(query_base->flags & QueryFlagBits::IsFinalValueSynced)) [[unlikely]] {
- UNREACHABLE();
+ ASSERT(false);
return;
}
query_base->value += streamer->GetAmmendValue();
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index 38d553d3c..dfd696de6 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -178,13 +178,14 @@ void BufferCacheRuntime::CopyBuffer(GLuint dst_buffer, Buffer& src_buffer,
}
void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, GLuint src_buffer,
- std::span<const VideoCommon::BufferCopy> copies, bool barrier) {
+ std::span<const VideoCommon::BufferCopy> copies, bool barrier,
+ bool) {
CopyBuffer(dst_buffer.Handle(), src_buffer, copies, barrier);
}
void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer,
- std::span<const VideoCommon::BufferCopy> copies) {
- CopyBuffer(dst_buffer.Handle(), src_buffer.Handle(), copies);
+ std::span<const VideoCommon::BufferCopy> copies, bool) {
+ CopyBuffer(dst_buffer.Handle(), src_buffer.Handle(), copies, true);
}
void BufferCacheRuntime::PreCopyBarrier() {
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index 41b746f3b..feccf06f9 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -30,6 +30,8 @@ public:
void MakeResident(GLenum access) noexcept;
+ void MarkUsage(u64 offset, u64 size) {}
+
[[nodiscard]] GLuint View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format);
[[nodiscard]] GLuint64EXT HostGpuAddr() const noexcept {
@@ -66,22 +68,29 @@ public:
[[nodiscard]] StagingBufferMap DownloadStagingBuffer(size_t size);
+ bool CanReorderUpload(const Buffer&, std::span<const VideoCommon::BufferCopy>) {
+ return false;
+ }
+
void CopyBuffer(GLuint dst_buffer, GLuint src_buffer,
- std::span<const VideoCommon::BufferCopy> copies, bool barrier = true);
+ std::span<const VideoCommon::BufferCopy> copies, bool barrier);
void CopyBuffer(GLuint dst_buffer, Buffer& src_buffer,
- std::span<const VideoCommon::BufferCopy> copies, bool barrier = true);
+ std::span<const VideoCommon::BufferCopy> copies, bool barrier);
void CopyBuffer(Buffer& dst_buffer, GLuint src_buffer,
- std::span<const VideoCommon::BufferCopy> copies, bool barrier = true);
+ std::span<const VideoCommon::BufferCopy> copies, bool barrier,
+ bool can_reorder_upload = false);
void CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer,
- std::span<const VideoCommon::BufferCopy> copies);
+ std::span<const VideoCommon::BufferCopy> copies, bool);
void PreCopyBarrier();
void PostCopyBarrier();
void Finish();
+ void TickFrame(VideoCommon::SlotVector<Buffer>&) noexcept {}
+
void ClearBuffer(Buffer& dest_buffer, u32 offset, size_t size, u32 value);
void BindIndexBuffer(Buffer& buffer, u32 offset, u32 size);
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index d8148e89a..7691cc2ba 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -79,13 +79,13 @@ vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allo
} // Anonymous namespace
Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params)
- : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(null_params) {}
+ : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(null_params), tracker{4096} {}
Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
VAddr cpu_addr_, u64 size_bytes_)
: VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_),
- device{&runtime.device}, buffer{
- CreateBuffer(*device, runtime.memory_allocator, SizeBytes())} {
+ device{&runtime.device}, buffer{CreateBuffer(*device, runtime.memory_allocator, SizeBytes())},
+ tracker{SizeBytes()} {
if (runtime.device.HasDebuggingToolAttached()) {
buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str());
}
@@ -355,12 +355,31 @@ bool BufferCacheRuntime::CanReportMemoryUsage() const {
return device.CanReportMemoryUsage();
}
+void BufferCacheRuntime::TickFrame(VideoCommon::SlotVector<Buffer>& slot_buffers) noexcept {
+ for (auto it = slot_buffers.begin(); it != slot_buffers.end(); it++) {
+ it->ResetUsageTracking();
+ }
+}
+
void BufferCacheRuntime::Finish() {
scheduler.Finish();
}
+bool BufferCacheRuntime::CanReorderUpload(const Buffer& buffer,
+ std::span<const VideoCommon::BufferCopy> copies) {
+ if (Settings::values.disable_buffer_reorder) {
+ return false;
+ }
+ const bool can_use_upload_cmdbuf =
+ std::ranges::all_of(copies, [&](const VideoCommon::BufferCopy& copy) {
+ return !buffer.IsRegionUsed(copy.dst_offset, copy.size);
+ });
+ return can_use_upload_cmdbuf;
+}
+
void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
- std::span<const VideoCommon::BufferCopy> copies, bool barrier) {
+ std::span<const VideoCommon::BufferCopy> copies, bool barrier,
+ bool can_reorder_upload) {
if (dst_buffer == VK_NULL_HANDLE || src_buffer == VK_NULL_HANDLE) {
return;
}
@@ -376,9 +395,18 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
};
+
// Measuring a popular game, this number never exceeds the specified size once data is warmed up
boost::container::small_vector<VkBufferCopy, 8> vk_copies(copies.size());
std::ranges::transform(copies, vk_copies.begin(), MakeBufferCopy);
+ if (src_buffer == staging_pool.StreamBuf() && can_reorder_upload) {
+ scheduler.RecordWithUploadBuffer([src_buffer, dst_buffer, vk_copies](
+ vk::CommandBuffer, vk::CommandBuffer upload_cmdbuf) {
+ upload_cmdbuf.CopyBuffer(src_buffer, dst_buffer, vk_copies);
+ });
+ return;
+ }
+
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) {
if (barrier) {
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 95446c732..4416a902f 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -5,6 +5,7 @@
#include "video_core/buffer_cache/buffer_cache_base.h"
#include "video_core/buffer_cache/memory_tracker_base.h"
+#include "video_core/buffer_cache/usage_tracker.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_vulkan/vk_compute_pass.h"
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
@@ -34,6 +35,18 @@ public:
return *buffer;
}
+ [[nodiscard]] bool IsRegionUsed(u64 offset, u64 size) const noexcept {
+ return tracker.IsUsed(offset, size);
+ }
+
+ void MarkUsage(u64 offset, u64 size) noexcept {
+ tracker.Track(offset, size);
+ }
+
+ void ResetUsageTracking() noexcept {
+ tracker.Reset();
+ }
+
operator VkBuffer() const noexcept {
return *buffer;
}
@@ -49,6 +62,7 @@ private:
const Device* device{};
vk::Buffer buffer;
std::vector<BufferView> views;
+ VideoCommon::UsageTracker tracker;
};
class QuadArrayIndexBuffer;
@@ -67,6 +81,8 @@ public:
ComputePassDescriptorQueue& compute_pass_descriptor_queue,
DescriptorPool& descriptor_pool);
+ void TickFrame(VideoCommon::SlotVector<Buffer>& slot_buffers) noexcept;
+
void Finish();
u64 GetDeviceLocalMemory() const;
@@ -79,12 +95,15 @@ public:
[[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size, bool deferred = false);
+ bool CanReorderUpload(const Buffer& buffer, std::span<const VideoCommon::BufferCopy> copies);
+
void FreeDeferredStagingBuffer(StagingBufferRef& ref);
void PreCopyBarrier();
void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
- std::span<const VideoCommon::BufferCopy> copies, bool barrier = true);
+ std::span<const VideoCommon::BufferCopy> copies, bool barrier,
+ bool can_reorder_upload = false);
void PostCopyBarrier();
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
index 6b288b994..ac8b6e838 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
@@ -100,12 +100,14 @@ void MasterSemaphore::Wait(u64 tick) {
Refresh();
}
-VkResult MasterSemaphore::SubmitQueue(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore,
- VkSemaphore wait_semaphore, u64 host_tick) {
+VkResult MasterSemaphore::SubmitQueue(vk::CommandBuffer& cmdbuf, vk::CommandBuffer& upload_cmdbuf,
+ VkSemaphore signal_semaphore, VkSemaphore wait_semaphore,
+ u64 host_tick) {
if (semaphore) {
- return SubmitQueueTimeline(cmdbuf, signal_semaphore, wait_semaphore, host_tick);
+ return SubmitQueueTimeline(cmdbuf, upload_cmdbuf, signal_semaphore, wait_semaphore,
+ host_tick);
} else {
- return SubmitQueueFence(cmdbuf, signal_semaphore, wait_semaphore, host_tick);
+ return SubmitQueueFence(cmdbuf, upload_cmdbuf, signal_semaphore, wait_semaphore, host_tick);
}
}
@@ -115,6 +117,7 @@ static constexpr std::array<VkPipelineStageFlags, 2> wait_stage_masks{
};
VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf,
+ vk::CommandBuffer& upload_cmdbuf,
VkSemaphore signal_semaphore,
VkSemaphore wait_semaphore, u64 host_tick) {
const VkSemaphore timeline_semaphore = *semaphore;
@@ -123,6 +126,8 @@ VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf,
const std::array signal_values{host_tick, u64(0)};
const std::array signal_semaphores{timeline_semaphore, signal_semaphore};
+ const std::array cmdbuffers{*upload_cmdbuf, *cmdbuf};
+
const u32 num_wait_semaphores = wait_semaphore ? 1 : 0;
const VkTimelineSemaphoreSubmitInfo timeline_si{
.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
@@ -138,8 +143,8 @@ VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf,
.waitSemaphoreCount = num_wait_semaphores,
.pWaitSemaphores = &wait_semaphore,
.pWaitDstStageMask = wait_stage_masks.data(),
- .commandBufferCount = 1,
- .pCommandBuffers = cmdbuf.address(),
+ .commandBufferCount = static_cast<u32>(cmdbuffers.size()),
+ .pCommandBuffers = cmdbuffers.data(),
.signalSemaphoreCount = num_signal_semaphores,
.pSignalSemaphores = signal_semaphores.data(),
};
@@ -147,19 +152,23 @@ VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf,
return device.GetGraphicsQueue().Submit(submit_info);
}
-VkResult MasterSemaphore::SubmitQueueFence(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore,
- VkSemaphore wait_semaphore, u64 host_tick) {
+VkResult MasterSemaphore::SubmitQueueFence(vk::CommandBuffer& cmdbuf,
+ vk::CommandBuffer& upload_cmdbuf,
+ VkSemaphore signal_semaphore, VkSemaphore wait_semaphore,
+ u64 host_tick) {
const u32 num_signal_semaphores = signal_semaphore ? 1 : 0;
const u32 num_wait_semaphores = wait_semaphore ? 1 : 0;
+ const std::array cmdbuffers{*upload_cmdbuf, *cmdbuf};
+
const VkSubmitInfo submit_info{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = nullptr,
.waitSemaphoreCount = num_wait_semaphores,
.pWaitSemaphores = &wait_semaphore,
.pWaitDstStageMask = wait_stage_masks.data(),
- .commandBufferCount = 1,
- .pCommandBuffers = cmdbuf.address(),
+ .commandBufferCount = static_cast<u32>(cmdbuffers.size()),
+ .pCommandBuffers = cmdbuffers.data(),
.signalSemaphoreCount = num_signal_semaphores,
.pSignalSemaphores = &signal_semaphore,
};
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h
index 3f599d7bd..7dfb93ffb 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.h
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h
@@ -52,14 +52,16 @@ public:
void Wait(u64 tick);
/// Submits the device graphics queue, updating the tick as necessary
- VkResult SubmitQueue(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore,
- VkSemaphore wait_semaphore, u64 host_tick);
+ VkResult SubmitQueue(vk::CommandBuffer& cmdbuf, vk::CommandBuffer& upload_cmdbuf,
+ VkSemaphore signal_semaphore, VkSemaphore wait_semaphore, u64 host_tick);
private:
- VkResult SubmitQueueTimeline(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore,
- VkSemaphore wait_semaphore, u64 host_tick);
- VkResult SubmitQueueFence(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore,
- VkSemaphore wait_semaphore, u64 host_tick);
+ VkResult SubmitQueueTimeline(vk::CommandBuffer& cmdbuf, vk::CommandBuffer& upload_cmdbuf,
+ VkSemaphore signal_semaphore, VkSemaphore wait_semaphore,
+ u64 host_tick);
+ VkResult SubmitQueueFence(vk::CommandBuffer& cmdbuf, vk::CommandBuffer& upload_cmdbuf,
+ VkSemaphore signal_semaphore, VkSemaphore wait_semaphore,
+ u64 host_tick);
void WaitThread(std::stop_token token);
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp
index 3be7837f4..146923db4 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.cpp
+++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp
@@ -22,11 +22,12 @@ namespace Vulkan {
MICROPROFILE_DECLARE(Vulkan_WaitForWorker);
-void Scheduler::CommandChunk::ExecuteAll(vk::CommandBuffer cmdbuf) {
+void Scheduler::CommandChunk::ExecuteAll(vk::CommandBuffer cmdbuf,
+ vk::CommandBuffer upload_cmdbuf) {
auto command = first;
while (command != nullptr) {
auto next = command->GetNext();
- command->Execute(cmdbuf);
+ command->Execute(cmdbuf, upload_cmdbuf);
command->~Command();
command = next;
}
@@ -180,7 +181,7 @@ void Scheduler::WorkerThread(std::stop_token stop_token) {
// Perform the work, tracking whether the chunk was a submission
// before executing.
const bool has_submit = work->HasSubmit();
- work->ExecuteAll(current_cmdbuf);
+ work->ExecuteAll(current_cmdbuf, current_upload_cmdbuf);
// If the chunk was a submission, reallocate the command buffer.
if (has_submit) {
@@ -205,6 +206,13 @@ void Scheduler::AllocateWorkerCommandBuffer() {
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
.pInheritanceInfo = nullptr,
});
+ current_upload_cmdbuf = vk::CommandBuffer(command_pool->Commit(), device.GetDispatchLoader());
+ current_upload_cmdbuf.Begin({
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .pNext = nullptr,
+ .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+ .pInheritanceInfo = nullptr,
+ });
}
u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_semaphore) {
@@ -212,7 +220,17 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se
InvalidateState();
const u64 signal_value = master_semaphore->NextTick();
- Record([signal_semaphore, wait_semaphore, signal_value, this](vk::CommandBuffer cmdbuf) {
+ RecordWithUploadBuffer([signal_semaphore, wait_semaphore, signal_value,
+ this](vk::CommandBuffer cmdbuf, vk::CommandBuffer upload_cmdbuf) {
+ static constexpr VkMemoryBarrier WRITE_BARRIER{
+ .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
+ .pNext = nullptr,
+ .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+ .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
+ };
+ upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
+ upload_cmdbuf.End();
cmdbuf.End();
if (on_submit) {
@@ -221,7 +239,7 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se
std::scoped_lock lock{submit_mutex};
switch (const VkResult result = master_semaphore->SubmitQueue(
- cmdbuf, signal_semaphore, wait_semaphore, signal_value)) {
+ cmdbuf, upload_cmdbuf, signal_semaphore, wait_semaphore, signal_value)) {
case VK_SUCCESS:
break;
case VK_ERROR_DEVICE_LOST:
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h
index da03803aa..f8d8ca80a 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.h
+++ b/src/video_core/renderer_vulkan/vk_scheduler.h
@@ -80,7 +80,8 @@ public:
/// Send work to a separate thread.
template <typename T>
- void Record(T&& command) {
+ requires std::is_invocable_v<T, vk::CommandBuffer, vk::CommandBuffer>
+ void RecordWithUploadBuffer(T&& command) {
if (chunk->Record(command)) {
return;
}
@@ -88,6 +89,15 @@ public:
(void)chunk->Record(command);
}
+ template <typename T>
+ requires std::is_invocable_v<T, vk::CommandBuffer>
+ void Record(T&& c) {
+ this->RecordWithUploadBuffer(
+ [command = std::move(c)](vk::CommandBuffer cmdbuf, vk::CommandBuffer) {
+ command(cmdbuf);
+ });
+ }
+
/// Returns the current command buffer tick.
[[nodiscard]] u64 CurrentTick() const noexcept {
return master_semaphore->CurrentTick();
@@ -119,7 +129,7 @@ private:
public:
virtual ~Command() = default;
- virtual void Execute(vk::CommandBuffer cmdbuf) const = 0;
+ virtual void Execute(vk::CommandBuffer cmdbuf, vk::CommandBuffer upload_cmdbuf) const = 0;
Command* GetNext() const {
return next;
@@ -142,8 +152,8 @@ private:
TypedCommand(TypedCommand&&) = delete;
TypedCommand& operator=(TypedCommand&&) = delete;
- void Execute(vk::CommandBuffer cmdbuf) const override {
- command(cmdbuf);
+ void Execute(vk::CommandBuffer cmdbuf, vk::CommandBuffer upload_cmdbuf) const override {
+ command(cmdbuf, upload_cmdbuf);
}
private:
@@ -152,7 +162,7 @@ private:
class CommandChunk final {
public:
- void ExecuteAll(vk::CommandBuffer cmdbuf);
+ void ExecuteAll(vk::CommandBuffer cmdbuf, vk::CommandBuffer upload_cmdbuf);
template <typename T>
bool Record(T& command) {
@@ -228,6 +238,7 @@ private:
VideoCommon::QueryCacheBase<QueryCacheParams>* query_cache = nullptr;
vk::CommandBuffer current_cmdbuf;
+ vk::CommandBuffer current_upload_cmdbuf;
std::unique_ptr<CommandChunk> chunk;
std::function<void()> on_submit;
diff --git a/src/video_core/renderer_vulkan/vk_smaa.cpp b/src/video_core/renderer_vulkan/vk_smaa.cpp
index 5efd7d66e..70644ea82 100644
--- a/src/video_core/renderer_vulkan/vk_smaa.cpp
+++ b/src/video_core/renderer_vulkan/vk_smaa.cpp
@@ -672,7 +672,7 @@ void SMAA::UploadImages(Scheduler& scheduler) {
UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent,
VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes));
- scheduler.Record([&](vk::CommandBuffer& cmdbuf) {
+ scheduler.Record([&](vk::CommandBuffer cmdbuf) {
for (auto& images : m_dynamic_images) {
for (size_t i = 0; i < MaxDynamicImage; i++) {
ClearColorImage(cmdbuf, *images.images[i]);
@@ -707,7 +707,7 @@ VkImageView SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_
UpdateDescriptorSets(source_image_view, image_index);
scheduler.RequestOutsideRenderPassOperationContext();
- scheduler.Record([=, this](vk::CommandBuffer& cmdbuf) {
+ scheduler.Record([=, this](vk::CommandBuffer cmdbuf) {
TransitionImageLayout(cmdbuf, source_image, VK_IMAGE_LAYOUT_GENERAL);
TransitionImageLayout(cmdbuf, edges_image, VK_IMAGE_LAYOUT_GENERAL);
BeginRenderPass(cmdbuf, m_renderpasses[EdgeDetection], edge_detection_framebuffer,
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
index d3deb9072..f63a20327 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
@@ -36,6 +36,10 @@ public:
StagingBufferRef Request(size_t size, MemoryUsage usage, bool deferred = false);
void FreeDeferred(StagingBufferRef& ref);
+ [[nodiscard]] VkBuffer StreamBuf() const noexcept {
+ return *stream_buffer;
+ }
+
void TickFrame();
private:
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,
: VideoCommon::ImageViewBase{info, view_info, gpu_addr_},
buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {}
-ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams& params)
- : VideoCommon::ImageViewBase{params} {}
+ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageViewParams& params)
+ : VideoCommon::ImageViewBase{params}, device{&runtime.device} {
+ if (device->HasNullDescriptor()) {
+ return;
+ }
+
+ // Handle fallback for devices without nullDescriptor
+ ImageInfo info{};
+ info.format = PixelFormat::A8B8G8R8_UNORM;
+
+ null_image = MakeImage(*device, runtime.memory_allocator, info, {});
+ image_handle = *null_image;
+ for (u32 i = 0; i < Shader::NUM_TEXTURE_TYPES; i++) {
+ image_views[i] = MakeView(VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_IMAGE_ASPECT_COLOR_BIT);
+ }
+}
ImageView::~ImageView() = default;
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:
vk::ImageView depth_view;
vk::ImageView stencil_view;
vk::ImageView color_view;
+ vk::Image null_image;
VkImage image_handle = VK_NULL_HANDLE;
VkImageView render_target = VK_NULL_HANDLE;
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
diff --git a/src/video_core/texture_cache/slot_vector.h b/src/video_core/texture_cache/slot_vector.h
index 9df6a2903..3ffa2a661 100644
--- a/src/video_core/texture_cache/slot_vector.h
+++ b/src/video_core/texture_cache/slot_vector.h
@@ -138,6 +138,10 @@ public:
return Iterator(this, SlotId{SlotId::INVALID_INDEX});
}
+ [[nodiscard]] size_t size() const noexcept {
+ return values_capacity - free_list.size();
+ }
+
private:
struct NonTrivialDummy {
NonTrivialDummy() noexcept {}
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 6900b8ffa..fde36a49c 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -869,7 +869,8 @@ bool Device::ShouldBoostClocks() const {
driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA ||
driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP;
- const bool is_steam_deck = vendor_id == 0x1002 && device_id == 0x163F;
+ const bool is_steam_deck = (vendor_id == 0x1002 && device_id == 0x163F) ||
+ (vendor_id == 0x1002 && device_id == 0x1435);
const bool is_debugging = this->HasDebuggingToolAttached();
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 0487cd3b6..a0c70797f 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -1101,6 +1101,10 @@ public:
return &handle;
}
+ VkCommandBuffer operator*() const noexcept {
+ return handle;
+ }
+
void Begin(const VkCommandBufferBeginInfo& begin_info) const {
Check(dld->vkBeginCommandBuffer(handle, &begin_info));
}
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
compatdb.ui
compatibility_list.cpp
compatibility_list.h
- configuration/config.cpp
- configuration/config.h
configuration/configuration_shared.cpp
configuration/configuration_shared.h
configuration/configure.ui
@@ -147,6 +145,8 @@ add_executable(yuzu
configuration/shared_translation.h
configuration/shared_widget.cpp
configuration/shared_widget.h
+ configuration/qt_config.cpp
+ configuration/qt_config.h
debugger/console.cpp
debugger/console.h
debugger/controller.cpp
@@ -377,7 +377,7 @@ endif()
create_target_directory_groups(yuzu)
-target_link_libraries(yuzu PRIVATE common core input_common network video_core)
+target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core)
target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets)
target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
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 @@
-// SPDX-FileCopyrightText: 2014 Citra Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <algorithm>
-#include <array>
-#include <QKeySequence>
-#include <QSettings>
-#include "common/fs/fs.h"
-#include "common/fs/path_util.h"
-#include "common/settings.h"
-#include "common/settings_common.h"
-#include "common/settings_enums.h"
-#include "core/core.h"
-#include "core/hle/service/acc/profile_manager.h"
-#include "core/hle/service/hid/controllers/npad.h"
-#include "input_common/main.h"
-#include "network/network.h"
-#include "yuzu/configuration/config.h"
-
-namespace FS = Common::FS;
-
-Config::Config(const std::string& config_name, ConfigType config_type)
- : type(config_type), global{config_type == ConfigType::GlobalConfig} {
- Initialize(config_name);
-}
-
-Config::~Config() {
- if (global) {
- Save();
- }
-}
-
-const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {
- Qt::Key_C, Qt::Key_X, Qt::Key_V, Qt::Key_Z, Qt::Key_F,
- Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T,
- Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right,
- Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0,
- Qt::Key_Q, Qt::Key_E,
-};
-
-const std::array<int, Settings::NativeMotion::NumMotions> Config::default_motions = {
- Qt::Key_7,
- Qt::Key_8,
-};
-
-const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{
- {
- Qt::Key_W,
- Qt::Key_S,
- Qt::Key_A,
- Qt::Key_D,
- },
- {
- Qt::Key_I,
- Qt::Key_K,
- Qt::Key_J,
- Qt::Key_L,
- },
-}};
-
-const std::array<int, 2> Config::default_stick_mod = {
- Qt::Key_Shift,
- 0,
-};
-
-const std::array<int, 2> Config::default_ringcon_analogs{{
- Qt::Key_A,
- Qt::Key_D,
-}};
-
-const std::map<Settings::AntiAliasing, QString> Config::anti_aliasing_texts_map = {
- {Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))},
- {Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))},
- {Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))},
-};
-
-const std::map<Settings::ScalingFilter, QString> Config::scaling_filter_texts_map = {
- {Settings::ScalingFilter::NearestNeighbor,
- QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))},
- {Settings::ScalingFilter::Bilinear,
- QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))},
- {Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))},
- {Settings::ScalingFilter::Gaussian,
- QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))},
- {Settings::ScalingFilter::ScaleForce,
- QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))},
- {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
-};
-
-const std::map<Settings::ConsoleMode, QString> Config::use_docked_mode_texts_map = {
- {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
- {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
-};
-
-const std::map<Settings::GpuAccuracy, QString> Config::gpu_accuracy_texts_map = {
- {Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))},
- {Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))},
- {Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))},
-};
-
-const std::map<Settings::RendererBackend, QString> Config::renderer_backend_texts_map = {
- {Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))},
- {Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))},
- {Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))},
-};
-
-const std::map<Settings::ShaderBackend, QString> Config::shader_backend_texts_map = {
- {Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))},
- {Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))},
- {Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))},
-};
-
-// This shouldn't have anything except static initializers (no functions). So
-// QKeySequence(...).toString() is NOT ALLOWED HERE.
-// This must be in alphabetical order according to action name as it must have the same order as
-// UISetting::values.shortcuts, which is alphabetically ordered.
-// clang-format off
-const std::array<UISettings::Shortcut, 23> Config::default_hotkeys{{
- {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}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut, true}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut, true}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F11"), QStringLiteral("Home+B"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral("R+Plus+Minus"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral("L+Plus+Minus"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral(""), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut, false}},
-}};
-// clang-format on
-
-void Config::Initialize(const std::string& config_name) {
- const auto fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir);
- const auto config_file = fmt::format("{}.ini", config_name);
-
- switch (type) {
- case ConfigType::GlobalConfig:
- qt_config_loc = FS::PathToUTF8String(fs_config_loc / config_file);
- void(FS::CreateParentDir(qt_config_loc));
- qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
- QSettings::IniFormat);
- Reload();
- break;
- case ConfigType::PerGameConfig:
- qt_config_loc =
- FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file));
- void(FS::CreateParentDir(qt_config_loc));
- qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
- QSettings::IniFormat);
- Reload();
- break;
- case ConfigType::InputProfile:
- qt_config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file);
- void(FS::CreateParentDir(qt_config_loc));
- qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
- QSettings::IniFormat);
- break;
- }
-}
-
-bool Config::IsCustomConfig() {
- return type == ConfigType::PerGameConfig;
-}
-
-void Config::ReadPlayerValue(std::size_t player_index) {
- const QString player_prefix = [this, player_index] {
- if (type == ConfigType::InputProfile) {
- return QString{};
- } else {
- return QStringLiteral("player_%1_").arg(player_index);
- }
- }();
-
- auto& player = Settings::values.players.GetValue()[player_index];
- if (IsCustomConfig()) {
- const auto profile_name =
- qt_config->value(QStringLiteral("%1profile_name").arg(player_prefix), QString{})
- .toString()
- .toStdString();
- if (profile_name.empty()) {
- // Use the global input config
- player = Settings::values.players.GetValue(true)[player_index];
- return;
- }
- player.profile_name = profile_name;
- }
-
- if (player_prefix.isEmpty() && Settings::IsConfiguringGlobal()) {
- const auto controller = static_cast<Settings::ControllerType>(
- qt_config
- ->value(QStringLiteral("%1type").arg(player_prefix),
- static_cast<u8>(Settings::ControllerType::ProController))
- .toUInt());
-
- if (controller == Settings::ControllerType::LeftJoycon ||
- controller == Settings::ControllerType::RightJoycon) {
- player.controller_type = controller;
- }
- } else {
- player.connected =
- ReadSetting(QStringLiteral("%1connected").arg(player_prefix), player_index == 0)
- .toBool();
-
- player.controller_type = static_cast<Settings::ControllerType>(
- qt_config
- ->value(QStringLiteral("%1type").arg(player_prefix),
- static_cast<u8>(Settings::ControllerType::ProController))
- .toUInt());
-
- player.vibration_enabled =
- qt_config->value(QStringLiteral("%1vibration_enabled").arg(player_prefix), true)
- .toBool();
-
- player.vibration_strength =
- qt_config->value(QStringLiteral("%1vibration_strength").arg(player_prefix), 100)
- .toInt();
-
- player.body_color_left = qt_config
- ->value(QStringLiteral("%1body_color_left").arg(player_prefix),
- Settings::JOYCON_BODY_NEON_BLUE)
- .toUInt();
- player.body_color_right =
- qt_config
- ->value(QStringLiteral("%1body_color_right").arg(player_prefix),
- Settings::JOYCON_BODY_NEON_RED)
- .toUInt();
- player.button_color_left =
- qt_config
- ->value(QStringLiteral("%1button_color_left").arg(player_prefix),
- Settings::JOYCON_BUTTONS_NEON_BLUE)
- .toUInt();
- player.button_color_right =
- qt_config
- ->value(QStringLiteral("%1button_color_right").arg(player_prefix),
- Settings::JOYCON_BUTTONS_NEON_RED)
- .toUInt();
- }
-
- for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- auto& player_buttons = player.buttons[i];
-
- player_buttons = qt_config
- ->value(QStringLiteral("%1").arg(player_prefix) +
- QString::fromUtf8(Settings::NativeButton::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (player_buttons.empty()) {
- player_buttons = default_param;
- }
- }
-
- for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
- default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
- default_analogs[i][3], default_stick_mod[i], 0.5f);
- auto& player_analogs = player.analogs[i];
-
- player_analogs = qt_config
- ->value(QStringLiteral("%1").arg(player_prefix) +
- QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (player_analogs.empty()) {
- player_analogs = default_param;
- }
- }
-
- for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
- const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
- auto& player_motions = player.motions[i];
-
- player_motions = qt_config
- ->value(QStringLiteral("%1").arg(player_prefix) +
- QString::fromUtf8(Settings::NativeMotion::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (player_motions.empty()) {
- player_motions = default_param;
- }
- }
-}
-
-void Config::ReadDebugValues() {
- for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i];
-
- debug_pad_buttons = qt_config
- ->value(QStringLiteral("debug_pad_") +
- QString::fromUtf8(Settings::NativeButton::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (debug_pad_buttons.empty()) {
- debug_pad_buttons = default_param;
- }
- }
-
- for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
- default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
- default_analogs[i][3], default_stick_mod[i], 0.5f);
- auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i];
-
- debug_pad_analogs = qt_config
- ->value(QStringLiteral("debug_pad_") +
- QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (debug_pad_analogs.empty()) {
- debug_pad_analogs = default_param;
- }
- }
-}
-
-void Config::ReadTouchscreenValues() {
- Settings::values.touchscreen.enabled =
- ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool();
-
- Settings::values.touchscreen.rotation_angle =
- ReadSetting(QStringLiteral("touchscreen_angle"), 0).toUInt();
- Settings::values.touchscreen.diameter_x =
- ReadSetting(QStringLiteral("touchscreen_diameter_x"), 15).toUInt();
- Settings::values.touchscreen.diameter_y =
- ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt();
-}
-
-void Config::ReadHidbusValues() {
- const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
- 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
- auto& ringcon_analogs = Settings::values.ringcon_analogs;
-
- ringcon_analogs =
- qt_config->value(QStringLiteral("ring_controller"), QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (ringcon_analogs.empty()) {
- ringcon_analogs = default_param;
- }
-}
-
-void Config::ReadAudioValues() {
- qt_config->beginGroup(QStringLiteral("Audio"));
-
- ReadCategory(Settings::Category::Audio);
- ReadCategory(Settings::Category::UiAudio);
-
- qt_config->endGroup();
-}
-
-void Config::ReadControlValues() {
- qt_config->beginGroup(QStringLiteral("Controls"));
-
- ReadCategory(Settings::Category::Controls);
-
- Settings::values.players.SetGlobal(!IsCustomConfig());
- for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
- ReadPlayerValue(p);
- }
-
- // Disable docked mode if handheld is selected
- const auto controller_type = Settings::values.players.GetValue()[0].controller_type;
- if (controller_type == Settings::ControllerType::Handheld) {
- Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig());
- Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
- }
-
- if (IsCustomConfig()) {
- qt_config->endGroup();
- return;
- }
- ReadDebugValues();
- ReadTouchscreenValues();
- ReadMotionTouchValues();
- ReadHidbusValues();
-
- qt_config->endGroup();
-}
-
-void Config::ReadMotionTouchValues() {
- int num_touch_from_button_maps =
- qt_config->beginReadArray(QStringLiteral("touch_from_button_maps"));
-
- if (num_touch_from_button_maps > 0) {
- const auto append_touch_from_button_map = [this] {
- Settings::TouchFromButtonMap map;
- map.name = ReadSetting(QStringLiteral("name"), QStringLiteral("default"))
- .toString()
- .toStdString();
- const int num_touch_maps = qt_config->beginReadArray(QStringLiteral("entries"));
- map.buttons.reserve(num_touch_maps);
- for (int i = 0; i < num_touch_maps; i++) {
- qt_config->setArrayIndex(i);
- std::string touch_mapping =
- ReadSetting(QStringLiteral("bind")).toString().toStdString();
- map.buttons.emplace_back(std::move(touch_mapping));
- }
- qt_config->endArray(); // entries
- Settings::values.touch_from_button_maps.emplace_back(std::move(map));
- };
-
- for (int i = 0; i < num_touch_from_button_maps; ++i) {
- qt_config->setArrayIndex(i);
- append_touch_from_button_map();
- }
- } else {
- Settings::values.touch_from_button_maps.emplace_back(
- Settings::TouchFromButtonMap{"default", {}});
- num_touch_from_button_maps = 1;
- }
- qt_config->endArray();
-
- Settings::values.touch_from_button_map_index = std::clamp(
- Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
-}
-
-void Config::ReadCoreValues() {
- qt_config->beginGroup(QStringLiteral("Core"));
-
- ReadCategory(Settings::Category::Core);
-
- qt_config->endGroup();
-}
-
-void Config::ReadDataStorageValues() {
- qt_config->beginGroup(QStringLiteral("Data Storage"));
-
- FS::SetYuzuPath(
- FS::YuzuPath::NANDDir,
- qt_config
- ->value(QStringLiteral("nand_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)))
- .toString()
- .toStdString());
- FS::SetYuzuPath(
- FS::YuzuPath::SDMCDir,
- qt_config
- ->value(QStringLiteral("sdmc_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)))
- .toString()
- .toStdString());
- FS::SetYuzuPath(
- FS::YuzuPath::LoadDir,
- qt_config
- ->value(QStringLiteral("load_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)))
- .toString()
- .toStdString());
- FS::SetYuzuPath(
- FS::YuzuPath::DumpDir,
- qt_config
- ->value(QStringLiteral("dump_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)))
- .toString()
- .toStdString());
- FS::SetYuzuPath(FS::YuzuPath::TASDir,
- qt_config
- ->value(QStringLiteral("tas_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)))
- .toString()
- .toStdString());
-
- ReadCategory(Settings::Category::DataStorage);
-
- qt_config->endGroup();
-}
-
-void Config::ReadDebuggingValues() {
- qt_config->beginGroup(QStringLiteral("Debugging"));
-
- // Intentionally not using the QT default setting as this is intended to be changed in the ini
- Settings::values.record_frame_times =
- qt_config->value(QStringLiteral("record_frame_times"), false).toBool();
-
- ReadCategory(Settings::Category::Debugging);
- ReadCategory(Settings::Category::DebuggingGraphics);
-
- qt_config->endGroup();
-}
-
-void Config::ReadServiceValues() {
- qt_config->beginGroup(QStringLiteral("Services"));
-
- ReadCategory(Settings::Category::Services);
-
- qt_config->endGroup();
-}
-
-void Config::ReadDisabledAddOnValues() {
- const auto size = qt_config->beginReadArray(QStringLiteral("DisabledAddOns"));
-
- for (int i = 0; i < size; ++i) {
- qt_config->setArrayIndex(i);
- const auto title_id = ReadSetting(QStringLiteral("title_id"), 0).toULongLong();
- std::vector<std::string> out;
- const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled"));
- for (int j = 0; j < d_size; ++j) {
- qt_config->setArrayIndex(j);
- out.push_back(ReadSetting(QStringLiteral("d"), QString{}).toString().toStdString());
- }
- qt_config->endArray();
- Settings::values.disabled_addons.insert_or_assign(title_id, out);
- }
-
- qt_config->endArray();
-}
-
-void Config::ReadMiscellaneousValues() {
- qt_config->beginGroup(QStringLiteral("Miscellaneous"));
-
- ReadCategory(Settings::Category::Miscellaneous);
-
- qt_config->endGroup();
-}
-
-void Config::ReadPathValues() {
- qt_config->beginGroup(QStringLiteral("Paths"));
-
- UISettings::values.roms_path = ReadSetting(QStringLiteral("romsPath")).toString();
- UISettings::values.symbols_path = ReadSetting(QStringLiteral("symbolsPath")).toString();
- UISettings::values.game_dir_deprecated =
- ReadSetting(QStringLiteral("gameListRootDir"), QStringLiteral(".")).toString();
- UISettings::values.game_dir_deprecated_deepscan =
- ReadSetting(QStringLiteral("gameListDeepScan"), false).toBool();
- const int gamedirs_size = qt_config->beginReadArray(QStringLiteral("gamedirs"));
- for (int i = 0; i < gamedirs_size; ++i) {
- qt_config->setArrayIndex(i);
- UISettings::GameDir game_dir;
- game_dir.path = ReadSetting(QStringLiteral("path")).toString();
- game_dir.deep_scan = ReadSetting(QStringLiteral("deep_scan"), false).toBool();
- game_dir.expanded = ReadSetting(QStringLiteral("expanded"), true).toBool();
- UISettings::values.game_dirs.append(game_dir);
- }
- qt_config->endArray();
- // create NAND and SD card directories if empty, these are not removable through the UI,
- // also carries over old game list settings if present
- if (UISettings::values.game_dirs.isEmpty()) {
- UISettings::GameDir game_dir;
- game_dir.path = QStringLiteral("SDMC");
- game_dir.expanded = true;
- UISettings::values.game_dirs.append(game_dir);
- game_dir.path = QStringLiteral("UserNAND");
- UISettings::values.game_dirs.append(game_dir);
- game_dir.path = QStringLiteral("SysNAND");
- UISettings::values.game_dirs.append(game_dir);
- if (UISettings::values.game_dir_deprecated != QStringLiteral(".")) {
- game_dir.path = UISettings::values.game_dir_deprecated;
- game_dir.deep_scan = UISettings::values.game_dir_deprecated_deepscan;
- UISettings::values.game_dirs.append(game_dir);
- }
- }
- UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList();
- UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString();
-
- qt_config->endGroup();
-}
-
-void Config::ReadCpuValues() {
- qt_config->beginGroup(QStringLiteral("Cpu"));
-
- ReadCategory(Settings::Category::Cpu);
- ReadCategory(Settings::Category::CpuDebug);
- ReadCategory(Settings::Category::CpuUnsafe);
-
- qt_config->endGroup();
-}
-
-void Config::ReadRendererValues() {
- qt_config->beginGroup(QStringLiteral("Renderer"));
-
- ReadCategory(Settings::Category::Renderer);
- ReadCategory(Settings::Category::RendererAdvanced);
- ReadCategory(Settings::Category::RendererDebug);
-
- qt_config->endGroup();
-}
-
-void Config::ReadScreenshotValues() {
- qt_config->beginGroup(QStringLiteral("Screenshots"));
-
- ReadCategory(Settings::Category::Screenshots);
- FS::SetYuzuPath(
- FS::YuzuPath::ScreenshotsDir,
- qt_config
- ->value(QStringLiteral("screenshot_path"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir)))
- .toString()
- .toStdString());
-
- qt_config->endGroup();
-}
-
-void Config::ReadShortcutValues() {
- qt_config->beginGroup(QStringLiteral("Shortcuts"));
-
- for (const auto& [name, group, shortcut] : default_hotkeys) {
- qt_config->beginGroup(group);
- qt_config->beginGroup(name);
- // No longer using ReadSetting for shortcut.second as it inaccurately returns a value of 1
- // for WidgetWithChildrenShortcut which is a value of 3. Needed to fix shortcuts the open
- // a file dialog in windowed mode
- UISettings::values.shortcuts.push_back(
- {name,
- group,
- {ReadSetting(QStringLiteral("KeySeq"), shortcut.keyseq).toString(),
- ReadSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq)
- .toString(),
- shortcut.context, ReadSetting(QStringLiteral("Repeat"), shortcut.repeat).toBool()}});
- qt_config->endGroup();
- qt_config->endGroup();
- }
-
- qt_config->endGroup();
-}
-
-void Config::ReadSystemValues() {
- qt_config->beginGroup(QStringLiteral("System"));
-
- ReadCategory(Settings::Category::System);
- ReadCategory(Settings::Category::SystemAudio);
-
- qt_config->endGroup();
-}
-
-void Config::ReadUIValues() {
- qt_config->beginGroup(QStringLiteral("UI"));
-
- UISettings::values.theme =
- ReadSetting(
- QStringLiteral("theme"),
- QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second))
- .toString();
-
- ReadUIGamelistValues();
- ReadUILayoutValues();
- ReadPathValues();
- ReadScreenshotValues();
- ReadShortcutValues();
- ReadMultiplayerValues();
-
- ReadCategory(Settings::Category::Ui);
- ReadCategory(Settings::Category::UiGeneral);
-
- qt_config->endGroup();
-}
-
-void Config::ReadUIGamelistValues() {
- qt_config->beginGroup(QStringLiteral("UIGameList"));
-
- ReadCategory(Settings::Category::UiGameList);
-
- const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites"));
- for (int i = 0; i < favorites_size; i++) {
- qt_config->setArrayIndex(i);
- UISettings::values.favorited_ids.append(
- ReadSetting(QStringLiteral("program_id")).toULongLong());
- }
- qt_config->endArray();
-
- qt_config->endGroup();
-}
-
-void Config::ReadUILayoutValues() {
- qt_config->beginGroup(QStringLiteral("UILayout"));
-
- UISettings::values.geometry = ReadSetting(QStringLiteral("geometry")).toByteArray();
- UISettings::values.state = ReadSetting(QStringLiteral("state")).toByteArray();
- UISettings::values.renderwindow_geometry =
- ReadSetting(QStringLiteral("geometryRenderWindow")).toByteArray();
- UISettings::values.gamelist_header_state =
- ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray();
- UISettings::values.microprofile_geometry =
- ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray();
-
- ReadCategory(Settings::Category::UiLayout);
-
- qt_config->endGroup();
-}
-
-void Config::ReadWebServiceValues() {
- qt_config->beginGroup(QStringLiteral("WebService"));
-
- ReadCategory(Settings::Category::WebService);
-
- qt_config->endGroup();
-}
-
-void Config::ReadMultiplayerValues() {
- qt_config->beginGroup(QStringLiteral("Multiplayer"));
-
- ReadCategory(Settings::Category::Multiplayer);
-
- // Read ban list back
- int size = qt_config->beginReadArray(QStringLiteral("username_ban_list"));
- UISettings::values.multiplayer_ban_list.first.resize(size);
- for (int i = 0; i < size; ++i) {
- qt_config->setArrayIndex(i);
- UISettings::values.multiplayer_ban_list.first[i] =
- ReadSetting(QStringLiteral("username")).toString().toStdString();
- }
- qt_config->endArray();
- size = qt_config->beginReadArray(QStringLiteral("ip_ban_list"));
- UISettings::values.multiplayer_ban_list.second.resize(size);
- for (int i = 0; i < size; ++i) {
- qt_config->setArrayIndex(i);
- UISettings::values.multiplayer_ban_list.second[i] =
- ReadSetting(QStringLiteral("ip")).toString().toStdString();
- }
- qt_config->endArray();
-
- qt_config->endGroup();
-}
-
-void Config::ReadNetworkValues() {
- qt_config->beginGroup(QString::fromStdString("Services"));
-
- ReadCategory(Settings::Category::Network);
-
- qt_config->endGroup();
-}
-
-void Config::ReadValues() {
- if (global) {
- ReadDataStorageValues();
- ReadDebuggingValues();
- ReadDisabledAddOnValues();
- ReadNetworkValues();
- ReadServiceValues();
- ReadUIValues();
- ReadWebServiceValues();
- ReadMiscellaneousValues();
- }
- ReadControlValues();
- ReadCoreValues();
- ReadCpuValues();
- ReadRendererValues();
- ReadAudioValues();
- ReadSystemValues();
-}
-
-void Config::SavePlayerValue(std::size_t player_index) {
- const QString player_prefix = [this, player_index] {
- if (type == ConfigType::InputProfile) {
- return QString{};
- } else {
- return QStringLiteral("player_%1_").arg(player_index);
- }
- }();
-
- const auto& player = Settings::values.players.GetValue()[player_index];
- if (IsCustomConfig()) {
- if (player.profile_name.empty()) {
- // No custom profile selected
- return;
- }
- WriteSetting(QStringLiteral("%1profile_name").arg(player_prefix),
- QString::fromStdString(player.profile_name), QString{});
- }
-
- WriteSetting(QStringLiteral("%1type").arg(player_prefix),
- static_cast<u8>(player.controller_type),
- static_cast<u8>(Settings::ControllerType::ProController));
-
- if (!player_prefix.isEmpty() || !Settings::IsConfiguringGlobal()) {
- WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected,
- player_index == 0);
- WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix),
- player.vibration_enabled, true);
- WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix),
- player.vibration_strength, 100);
- WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left,
- Settings::JOYCON_BODY_NEON_BLUE);
- WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix),
- player.body_color_right, Settings::JOYCON_BODY_NEON_RED);
- WriteSetting(QStringLiteral("%1button_color_left").arg(player_prefix),
- player.button_color_left, Settings::JOYCON_BUTTONS_NEON_BLUE);
- WriteSetting(QStringLiteral("%1button_color_right").arg(player_prefix),
- player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED);
- }
-
- for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- WriteSetting(QStringLiteral("%1").arg(player_prefix) +
- QString::fromStdString(Settings::NativeButton::mapping[i]),
- QString::fromStdString(player.buttons[i]),
- QString::fromStdString(default_param));
- }
- for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
- default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
- default_analogs[i][3], default_stick_mod[i], 0.5f);
- WriteSetting(QStringLiteral("%1").arg(player_prefix) +
- QString::fromStdString(Settings::NativeAnalog::mapping[i]),
- QString::fromStdString(player.analogs[i]),
- QString::fromStdString(default_param));
- }
- for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
- const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
- WriteSetting(QStringLiteral("%1").arg(player_prefix) +
- QString::fromStdString(Settings::NativeMotion::mapping[i]),
- QString::fromStdString(player.motions[i]),
- QString::fromStdString(default_param));
- }
-}
-
-void Config::SaveDebugValues() {
- for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- WriteSetting(QStringLiteral("debug_pad_") +
- QString::fromStdString(Settings::NativeButton::mapping[i]),
- QString::fromStdString(Settings::values.debug_pad_buttons[i]),
- QString::fromStdString(default_param));
- }
- for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
- default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
- default_analogs[i][3], default_stick_mod[i], 0.5f);
- WriteSetting(QStringLiteral("debug_pad_") +
- QString::fromStdString(Settings::NativeAnalog::mapping[i]),
- QString::fromStdString(Settings::values.debug_pad_analogs[i]),
- QString::fromStdString(default_param));
- }
-}
-
-void Config::SaveTouchscreenValues() {
- const auto& touchscreen = Settings::values.touchscreen;
-
- WriteSetting(QStringLiteral("touchscreen_enabled"), touchscreen.enabled, true);
-
- WriteSetting(QStringLiteral("touchscreen_angle"), touchscreen.rotation_angle, 0);
- WriteSetting(QStringLiteral("touchscreen_diameter_x"), touchscreen.diameter_x, 15);
- WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15);
-}
-
-void Config::SaveMotionTouchValues() {
- qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps"));
- for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
- qt_config->setArrayIndex(static_cast<int>(p));
- WriteSetting(QStringLiteral("name"),
- QString::fromStdString(Settings::values.touch_from_button_maps[p].name),
- QStringLiteral("default"));
- qt_config->beginWriteArray(QStringLiteral("entries"));
- for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size();
- ++q) {
- qt_config->setArrayIndex(static_cast<int>(q));
- WriteSetting(
- QStringLiteral("bind"),
- QString::fromStdString(Settings::values.touch_from_button_maps[p].buttons[q]));
- }
- qt_config->endArray();
- }
- qt_config->endArray();
-}
-
-void Config::SaveHidbusValues() {
- const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
- 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
- WriteSetting(QStringLiteral("ring_controller"),
- QString::fromStdString(Settings::values.ringcon_analogs),
- QString::fromStdString(default_param));
-}
-
-void Config::SaveValues() {
- if (global) {
- SaveDataStorageValues();
- SaveDebuggingValues();
- SaveDisabledAddOnValues();
- SaveNetworkValues();
- SaveUIValues();
- SaveWebServiceValues();
- SaveMiscellaneousValues();
- }
- SaveControlValues();
- SaveCoreValues();
- SaveCpuValues();
- SaveRendererValues();
- SaveAudioValues();
- SaveSystemValues();
-
- qt_config->sync();
-}
-
-void Config::SaveAudioValues() {
- qt_config->beginGroup(QStringLiteral("Audio"));
-
- WriteCategory(Settings::Category::Audio);
- WriteCategory(Settings::Category::UiAudio);
-
- qt_config->endGroup();
-}
-
-void Config::SaveControlValues() {
- qt_config->beginGroup(QStringLiteral("Controls"));
-
- WriteCategory(Settings::Category::Controls);
-
- Settings::values.players.SetGlobal(!IsCustomConfig());
- for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
- SavePlayerValue(p);
- }
- if (IsCustomConfig()) {
- qt_config->endGroup();
- return;
- }
- SaveDebugValues();
- SaveTouchscreenValues();
- SaveMotionTouchValues();
- SaveHidbusValues();
-
- qt_config->endGroup();
-}
-
-void Config::SaveCoreValues() {
- qt_config->beginGroup(QStringLiteral("Core"));
-
- WriteCategory(Settings::Category::Core);
-
- qt_config->endGroup();
-}
-
-void Config::SaveDataStorageValues() {
- qt_config->beginGroup(QStringLiteral("Data Storage"));
-
- WriteSetting(QStringLiteral("nand_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
- WriteSetting(QStringLiteral("sdmc_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
- WriteSetting(QStringLiteral("load_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
- WriteSetting(QStringLiteral("dump_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
- WriteSetting(QStringLiteral("tas_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)));
-
- WriteCategory(Settings::Category::DataStorage);
-
- qt_config->endGroup();
-}
-
-void Config::SaveDebuggingValues() {
- qt_config->beginGroup(QStringLiteral("Debugging"));
-
- // Intentionally not using the QT default setting as this is intended to be changed in the ini
- qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times);
-
- WriteCategory(Settings::Category::Debugging);
- WriteCategory(Settings::Category::DebuggingGraphics);
-
- qt_config->endGroup();
-}
-
-void Config::SaveNetworkValues() {
- qt_config->beginGroup(QStringLiteral("Services"));
-
- WriteCategory(Settings::Category::Network);
-
- qt_config->endGroup();
-}
-
-void Config::SaveDisabledAddOnValues() {
- qt_config->beginWriteArray(QStringLiteral("DisabledAddOns"));
-
- int i = 0;
- for (const auto& elem : Settings::values.disabled_addons) {
- qt_config->setArrayIndex(i);
- WriteSetting(QStringLiteral("title_id"), QVariant::fromValue<u64>(elem.first), 0);
- qt_config->beginWriteArray(QStringLiteral("disabled"));
- for (std::size_t j = 0; j < elem.second.size(); ++j) {
- qt_config->setArrayIndex(static_cast<int>(j));
- WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), QString{});
- }
- qt_config->endArray();
- ++i;
- }
-
- qt_config->endArray();
-}
-
-void Config::SaveMiscellaneousValues() {
- qt_config->beginGroup(QStringLiteral("Miscellaneous"));
-
- WriteCategory(Settings::Category::Miscellaneous);
-
- qt_config->endGroup();
-}
-
-void Config::SavePathValues() {
- qt_config->beginGroup(QStringLiteral("Paths"));
-
- WriteSetting(QStringLiteral("romsPath"), UISettings::values.roms_path);
- WriteSetting(QStringLiteral("symbolsPath"), UISettings::values.symbols_path);
- qt_config->beginWriteArray(QStringLiteral("gamedirs"));
- for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) {
- qt_config->setArrayIndex(i);
- const auto& game_dir = UISettings::values.game_dirs[i];
- WriteSetting(QStringLiteral("path"), game_dir.path);
- WriteSetting(QStringLiteral("deep_scan"), game_dir.deep_scan, false);
- WriteSetting(QStringLiteral("expanded"), game_dir.expanded, true);
- }
- qt_config->endArray();
- WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files);
- WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{});
-
- qt_config->endGroup();
-}
-
-void Config::SaveCpuValues() {
- qt_config->beginGroup(QStringLiteral("Cpu"));
-
- WriteCategory(Settings::Category::Cpu);
- WriteCategory(Settings::Category::CpuDebug);
- WriteCategory(Settings::Category::CpuUnsafe);
-
- qt_config->endGroup();
-}
-
-void Config::SaveRendererValues() {
- qt_config->beginGroup(QStringLiteral("Renderer"));
-
- WriteCategory(Settings::Category::Renderer);
- WriteCategory(Settings::Category::RendererAdvanced);
- WriteCategory(Settings::Category::RendererDebug);
-
- qt_config->endGroup();
-}
-
-void Config::SaveScreenshotValues() {
- qt_config->beginGroup(QStringLiteral("Screenshots"));
-
- WriteSetting(QStringLiteral("screenshot_path"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir)));
- WriteCategory(Settings::Category::Screenshots);
-
- qt_config->endGroup();
-}
-
-void Config::SaveShortcutValues() {
- qt_config->beginGroup(QStringLiteral("Shortcuts"));
-
- // Lengths of UISettings::values.shortcuts & default_hotkeys are same.
- // However, their ordering must also be the same.
- for (std::size_t i = 0; i < default_hotkeys.size(); i++) {
- const auto& [name, group, shortcut] = UISettings::values.shortcuts[i];
- const auto& default_hotkey = default_hotkeys[i].shortcut;
-
- qt_config->beginGroup(group);
- qt_config->beginGroup(name);
- WriteSetting(QStringLiteral("KeySeq"), shortcut.keyseq, default_hotkey.keyseq);
- WriteSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq,
- default_hotkey.controller_keyseq);
- WriteSetting(QStringLiteral("Context"), shortcut.context, default_hotkey.context);
- WriteSetting(QStringLiteral("Repeat"), shortcut.repeat, default_hotkey.repeat);
- qt_config->endGroup();
- qt_config->endGroup();
- }
-
- qt_config->endGroup();
-}
-
-void Config::SaveSystemValues() {
- qt_config->beginGroup(QStringLiteral("System"));
-
- WriteCategory(Settings::Category::System);
- WriteCategory(Settings::Category::SystemAudio);
-
- qt_config->endGroup();
-}
-
-void Config::SaveUIValues() {
- qt_config->beginGroup(QStringLiteral("UI"));
-
- WriteCategory(Settings::Category::Ui);
- WriteCategory(Settings::Category::UiGeneral);
-
- WriteSetting(QStringLiteral("theme"), UISettings::values.theme,
- QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second));
-
- SaveUIGamelistValues();
- SaveUILayoutValues();
- SavePathValues();
- SaveScreenshotValues();
- SaveShortcutValues();
- SaveMultiplayerValues();
-
- qt_config->endGroup();
-}
-
-void Config::SaveUIGamelistValues() {
- qt_config->beginGroup(QStringLiteral("UIGameList"));
-
- WriteCategory(Settings::Category::UiGameList);
-
- qt_config->beginWriteArray(QStringLiteral("favorites"));
- for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
- qt_config->setArrayIndex(i);
- WriteSetting(QStringLiteral("program_id"),
- QVariant::fromValue(UISettings::values.favorited_ids[i]));
- }
- qt_config->endArray();
-
- qt_config->endGroup();
-}
-
-void Config::SaveUILayoutValues() {
- qt_config->beginGroup(QStringLiteral("UILayout"));
-
- WriteSetting(QStringLiteral("geometry"), UISettings::values.geometry);
- WriteSetting(QStringLiteral("state"), UISettings::values.state);
- WriteSetting(QStringLiteral("geometryRenderWindow"), UISettings::values.renderwindow_geometry);
- WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state);
- WriteSetting(QStringLiteral("microProfileDialogGeometry"),
- UISettings::values.microprofile_geometry);
-
- WriteCategory(Settings::Category::UiLayout);
-
- qt_config->endGroup();
-}
-
-void Config::SaveWebServiceValues() {
- qt_config->beginGroup(QStringLiteral("WebService"));
-
- WriteCategory(Settings::Category::WebService);
-
- qt_config->endGroup();
-}
-
-void Config::SaveMultiplayerValues() {
- qt_config->beginGroup(QStringLiteral("Multiplayer"));
-
- WriteCategory(Settings::Category::Multiplayer);
-
- // Write ban list
- qt_config->beginWriteArray(QStringLiteral("username_ban_list"));
- for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.first.size(); ++i) {
- qt_config->setArrayIndex(static_cast<int>(i));
- WriteSetting(QStringLiteral("username"),
- QString::fromStdString(UISettings::values.multiplayer_ban_list.first[i]));
- }
- qt_config->endArray();
- qt_config->beginWriteArray(QStringLiteral("ip_ban_list"));
- for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.second.size(); ++i) {
- qt_config->setArrayIndex(static_cast<int>(i));
- WriteSetting(QStringLiteral("ip"),
- QString::fromStdString(UISettings::values.multiplayer_ban_list.second[i]));
- }
- qt_config->endArray();
-
- qt_config->endGroup();
-}
-
-QVariant Config::ReadSetting(const QString& name) const {
- return qt_config->value(name);
-}
-
-QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) const {
- QVariant result;
- if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) {
- result = default_value;
- } else {
- result = qt_config->value(name, default_value);
- }
- return result;
-}
-
-void Config::WriteSetting(const QString& name, const QVariant& value) {
- qt_config->setValue(name, value);
-}
-
-void Config::WriteSetting(const QString& name, const QVariant& value,
- const QVariant& default_value) {
- qt_config->setValue(name + QStringLiteral("/default"), value == default_value);
- qt_config->setValue(name, value);
-}
-
-void Config::WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value,
- bool use_global) {
- if (!global) {
- qt_config->setValue(name + QStringLiteral("/use_global"), use_global);
- }
- if (global || !use_global) {
- qt_config->setValue(name + QStringLiteral("/default"), value == default_value);
- qt_config->setValue(name, value);
- }
-}
-
-void Config::Reload() {
- ReadValues();
- // To apply default value changes
- SaveValues();
-}
-
-void Config::Save() {
- SaveValues();
-}
-
-void Config::ReadControlPlayerValue(std::size_t player_index) {
- qt_config->beginGroup(QStringLiteral("Controls"));
- ReadPlayerValue(player_index);
- qt_config->endGroup();
-}
-
-void Config::SaveControlPlayerValue(std::size_t player_index) {
- qt_config->beginGroup(QStringLiteral("Controls"));
- SavePlayerValue(player_index);
- qt_config->endGroup();
-}
-
-void Config::ClearControlPlayerValues() {
- qt_config->beginGroup(QStringLiteral("Controls"));
- // If key is an empty string, all keys in the current group() are removed.
- qt_config->remove(QString{});
- qt_config->endGroup();
-}
-
-const std::string& Config::GetConfigFilePath() const {
- return qt_config_loc;
-}
-
-static auto FindRelevantList(Settings::Category category) {
- auto& map = Settings::values.linkage.by_category;
- if (map.contains(category)) {
- return Settings::values.linkage.by_category[category];
- }
- return UISettings::values.linkage.by_category[category];
-}
-
-void Config::ReadCategory(Settings::Category category) {
- const auto& settings = FindRelevantList(category);
- std::for_each(settings.begin(), settings.end(),
- [&](const auto& setting) { ReadSettingGeneric(setting); });
-}
-
-void Config::WriteCategory(Settings::Category category) {
- const auto& settings = FindRelevantList(category);
- std::for_each(settings.begin(), settings.end(),
- [&](const auto& setting) { WriteSettingGeneric(setting); });
-}
-
-void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) {
- if (!setting->Save() || (!setting->Switchable() && !global)) {
- return;
- }
- const QString name = QString::fromStdString(setting->GetLabel());
- const auto default_value =
- QVariant::fromValue<QString>(QString::fromStdString(setting->DefaultToString()));
-
- bool use_global = true;
- if (setting->Switchable() && !global) {
- use_global = qt_config->value(name + QStringLiteral("/use_global"), true).value<bool>();
- setting->SetGlobal(use_global);
- }
-
- if (global || !use_global) {
- const bool is_default =
- qt_config->value(name + QStringLiteral("/default"), true).value<bool>();
- if (!is_default) {
- setting->LoadString(
- qt_config->value(name, default_value).value<QString>().toStdString());
- } else {
- // Empty string resets the Setting to default
- setting->LoadString("");
- }
- }
-}
-
-void Config::WriteSettingGeneric(Settings::BasicSetting* const setting) const {
- if (!setting->Save()) {
- return;
- }
- const QVariant value = QVariant::fromValue(QString::fromStdString(setting->ToString()));
- const QVariant default_value =
- QVariant::fromValue(QString::fromStdString(setting->DefaultToString()));
- const QString label = QString::fromStdString(setting->GetLabel());
- if (setting->Switchable()) {
- if (!global) {
- qt_config->setValue(label + QStringLiteral("/use_global"), setting->UsingGlobal());
- }
- if (global || !setting->UsingGlobal()) {
- qt_config->setValue(label + QStringLiteral("/default"), value == default_value);
- qt_config->setValue(label, value);
- }
- } else if (global) {
- qt_config->setValue(label + QStringLiteral("/default"), value == default_value);
- qt_config->setValue(label, value);
- }
-}
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 @@
-// SPDX-FileCopyrightText: 2014 Citra Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <array>
-#include <memory>
-#include <string>
-#include <QMetaType>
-#include <QVariant>
-#include "common/settings.h"
-#include "common/settings_enums.h"
-#include "yuzu/uisettings.h"
-
-class QSettings;
-
-namespace Core {
-class System;
-}
-
-class Config {
-public:
- enum class ConfigType {
- GlobalConfig,
- PerGameConfig,
- InputProfile,
- };
-
- explicit Config(const std::string& config_name = "qt-config",
- ConfigType config_type = ConfigType::GlobalConfig);
- ~Config();
-
- void Reload();
- void Save();
-
- void ReadControlPlayerValue(std::size_t player_index);
- void SaveControlPlayerValue(std::size_t player_index);
- void ClearControlPlayerValues();
-
- const std::string& GetConfigFilePath() const;
-
- static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
- static const std::array<int, Settings::NativeMotion::NumMotions> default_motions;
- static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
- static const std::array<int, 2> default_stick_mod;
- static const std::array<int, 2> default_ringcon_analogs;
- static const std::array<int, Settings::NativeMouseButton::NumMouseButtons>
- default_mouse_buttons;
- static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;
- static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods;
- static const std::array<UISettings::Shortcut, 23> default_hotkeys;
-
- static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map;
- static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map;
- static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map;
- static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map;
- static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map;
- static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map;
-
- static constexpr UISettings::Theme default_theme{
-#ifdef _WIN32
- UISettings::Theme::DarkColorful
-#else
- UISettings::Theme::DefaultColorful
-#endif
- };
-
-private:
- void Initialize(const std::string& config_name);
- bool IsCustomConfig();
-
- void ReadValues();
- void ReadPlayerValue(std::size_t player_index);
- void ReadDebugValues();
- void ReadKeyboardValues();
- void ReadMouseValues();
- void ReadTouchscreenValues();
- void ReadMotionTouchValues();
- void ReadHidbusValues();
- void ReadIrCameraValues();
-
- // Read functions bases off the respective config section names.
- void ReadAudioValues();
- void ReadControlValues();
- void ReadCoreValues();
- void ReadDataStorageValues();
- void ReadDebuggingValues();
- void ReadServiceValues();
- void ReadDisabledAddOnValues();
- void ReadMiscellaneousValues();
- void ReadPathValues();
- void ReadCpuValues();
- void ReadRendererValues();
- void ReadScreenshotValues();
- void ReadShortcutValues();
- void ReadSystemValues();
- void ReadUIValues();
- void ReadUIGamelistValues();
- void ReadUILayoutValues();
- void ReadWebServiceValues();
- void ReadMultiplayerValues();
- void ReadNetworkValues();
-
- void SaveValues();
- void SavePlayerValue(std::size_t player_index);
- void SaveDebugValues();
- void SaveMouseValues();
- void SaveTouchscreenValues();
- void SaveMotionTouchValues();
- void SaveHidbusValues();
- void SaveIrCameraValues();
-
- // Save functions based off the respective config section names.
- void SaveAudioValues();
- void SaveControlValues();
- void SaveCoreValues();
- void SaveDataStorageValues();
- void SaveDebuggingValues();
- void SaveNetworkValues();
- void SaveDisabledAddOnValues();
- void SaveMiscellaneousValues();
- void SavePathValues();
- void SaveCpuValues();
- void SaveRendererValues();
- void SaveScreenshotValues();
- void SaveShortcutValues();
- void SaveSystemValues();
- void SaveUIValues();
- void SaveUIGamelistValues();
- void SaveUILayoutValues();
- void SaveWebServiceValues();
- void SaveMultiplayerValues();
-
- /**
- * Reads a setting from the qt_config.
- *
- * @param name The setting's identifier
- * @param default_value The value to use when the setting is not already present in the config
- */
- QVariant ReadSetting(const QString& name) const;
- QVariant ReadSetting(const QString& name, const QVariant& default_value) const;
-
- /**
- * Writes a setting to the qt_config.
- *
- * @param name The setting's idetentifier
- * @param value Value of the setting
- * @param default_value Default of the setting if not present in qt_config
- * @param use_global Specifies if the custom or global config should be in use, for custom
- * configs
- */
- void WriteSetting(const QString& name, const QVariant& value);
- void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value);
- void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value,
- bool use_global);
-
- void ReadCategory(Settings::Category category);
- void WriteCategory(Settings::Category category);
- void ReadSettingGeneric(Settings::BasicSetting* const setting);
- void WriteSettingGeneric(Settings::BasicSetting* const setting) const;
-
- const ConfigType type;
- std::unique_ptr<QSettings> qt_config;
- std::string qt_config_loc;
- const bool global;
-};
-
-// These metatype declarations cannot be in common/settings.h because core is devoid of QT
-Q_DECLARE_METATYPE(Settings::CpuAccuracy);
-Q_DECLARE_METATYPE(Settings::GpuAccuracy);
-Q_DECLARE_METATYPE(Settings::FullscreenMode);
-Q_DECLARE_METATYPE(Settings::NvdecEmulation);
-Q_DECLARE_METATYPE(Settings::ResolutionSetup);
-Q_DECLARE_METATYPE(Settings::ScalingFilter);
-Q_DECLARE_METATYPE(Settings::AntiAliasing);
-Q_DECLARE_METATYPE(Settings::RendererBackend);
-Q_DECLARE_METATYPE(Settings::ShaderBackend);
-Q_DECLARE_METATYPE(Settings::AstcRecompression);
-Q_DECLARE_METATYPE(Settings::AstcDecodeMode);
diff --git a/src/yuzu/configuration/configure_camera.cpp b/src/yuzu/configuration/configure_camera.cpp
index d95e96696..3368f53f3 100644
--- a/src/yuzu/configuration/configure_camera.cpp
+++ b/src/yuzu/configuration/configure_camera.cpp
@@ -10,10 +10,10 @@
#include <QStandardItemModel>
#include <QTimer>
+#include "common/settings.h"
#include "input_common/drivers/camera.h"
#include "input_common/main.h"
#include "ui_configure_camera.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_camera.h"
ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_)
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index ef421c754..1010038b7 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -51,6 +51,8 @@ void ConfigureDebug::SetConfiguration() {
ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue());
ui->enable_renderdoc_hotkey->setEnabled(runtime_lock);
ui->enable_renderdoc_hotkey->setChecked(Settings::values.enable_renderdoc_hotkey.GetValue());
+ ui->disable_buffer_reorder->setEnabled(runtime_lock);
+ ui->disable_buffer_reorder->setChecked(Settings::values.disable_buffer_reorder.GetValue());
ui->enable_graphics_debugging->setEnabled(runtime_lock);
ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue());
ui->enable_shader_feedback->setEnabled(runtime_lock);
@@ -96,6 +98,7 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.enable_all_controllers = ui->enable_all_controllers->isChecked();
Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
Settings::values.enable_renderdoc_hotkey = ui->enable_renderdoc_hotkey->isChecked();
+ Settings::values.disable_buffer_reorder = ui->disable_buffer_reorder->isChecked();
Settings::values.renderer_shader_feedback = ui->enable_shader_feedback->isChecked();
Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked();
Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked();
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 76fe98924..22b51f39c 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -271,19 +271,6 @@
</widget>
</item>
<item row="8" column="0">
- <widget class="QCheckBox" name="disable_macro_hle">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="toolTip">
- <string>When checked, it disables the macro HLE functions. Enabling this makes games run slower</string>
- </property>
- <property name="text">
- <string>Disable Macro HLE</string>
- </property>
- </widget>
- </item>
- <item row="7" column="0">
<widget class="QCheckBox" name="dump_macros">
<property name="enabled">
<bool>true</bool>
@@ -306,17 +293,27 @@
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QCheckBox" name="enable_shader_feedback">
+ <item row="6" column="0">
+ <widget class="QCheckBox" name="dump_shaders">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
<property name="toolTip">
- <string>When checked, yuzu will log statistics about the compiled pipeline cache</string>
+ <string>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</string>
</property>
<property name="text">
- <string>Enable Shader Feedback</string>
+ <string>Dump Game Shaders</string>
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="enable_renderdoc_hotkey">
+ <property name="text">
+ <string>Enable Renderdoc Hotkey</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
<widget class="QCheckBox" name="disable_macro_jit">
<property name="enabled">
<bool>true</bool>
@@ -330,20 +327,17 @@
</widget>
</item>
<item row="9" column="0">
- <spacer name="verticalSpacer_5">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <widget class="QCheckBox" name="disable_macro_hle">
+ <property name="enabled">
+ <bool>true</bool>
</property>
- <property name="sizeType">
- <enum>QSizePolicy::Preferred</enum>
+ <property name="toolTip">
+ <string>When checked, it disables the macro HLE functions. Enabling this makes games run slower</string>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>0</height>
- </size>
+ <property name="text">
+ <string>Disable Macro HLE</string>
</property>
- </spacer>
+ </widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="enable_graphics_debugging">
@@ -358,23 +352,39 @@
</property>
</widget>
</item>
- <item row="5" column="0">
- <widget class="QCheckBox" name="dump_shaders">
- <property name="enabled">
- <bool>true</bool>
+ <item row="10" column="0">
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Preferred</enum>
</property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="enable_shader_feedback">
<property name="toolTip">
- <string>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</string>
+ <string>When checked, yuzu will log statistics about the compiled pipeline cache</string>
</property>
<property name="text">
- <string>Dump Game Shaders</string>
+ <string>Enable Shader Feedback</string>
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QCheckBox" name="enable_renderdoc_hotkey">
+ <item row="5" column="0">
+ <widget class="QCheckBox" name="disable_buffer_reorder">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When checked, disables reording of mapped memory uploads which allows to associate uploads with specific draws. May reduce performance in some cases.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
<property name="text">
- <string>Enable Renderdoc Hotkey</string>
+ <string>Disable Buffer Reorder</string>
</property>
</widget>
</item>
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 @@
#include "core/core.h"
#include "ui_configure.h"
#include "vk_device_info.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_audio.h"
#include "yuzu/configuration/configure_cpu.h"
#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 @@
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
+#include "frontend_common/config.h"
#include "ui_configure_hotkeys.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_hotkeys.h"
#include "yuzu/hotkeys.h"
+#include "yuzu/uisettings.h"
#include "yuzu/util/sequence_dialog/sequence_dialog.h"
constexpr int name_column = 0;
@@ -62,18 +63,21 @@ ConfigureHotkeys::~ConfigureHotkeys() = default;
void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) {
for (const auto& group : registry.hotkey_groups) {
+ QString parent_item_data = QString::fromStdString(group.first);
auto* parent_item =
- new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(group.first)));
+ new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(parent_item_data)));
parent_item->setEditable(false);
- parent_item->setData(group.first);
+ parent_item->setData(parent_item_data);
for (const auto& hotkey : group.second) {
- auto* action =
- new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(hotkey.first)));
+ QString hotkey_action_data = QString::fromStdString(hotkey.first);
+ auto* action = new QStandardItem(
+ QCoreApplication::translate("Hotkeys", qPrintable(hotkey_action_data)));
auto* keyseq =
new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText));
- auto* controller_keyseq = new QStandardItem(hotkey.second.controller_keyseq);
+ auto* controller_keyseq =
+ new QStandardItem(QString::fromStdString(hotkey.second.controller_keyseq));
action->setEditable(false);
- action->setData(hotkey.first);
+ action->setData(hotkey_action_data);
keyseq->setEditable(false);
controller_keyseq->setEditable(false);
parent_item->appendRow({action, keyseq, controller_keyseq});
@@ -301,13 +305,13 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) {
const QStandardItem* controller_keyseq =
parent->child(key_column_id, controller_column);
for (auto& [group, sub_actions] : registry.hotkey_groups) {
- if (group != parent->data())
+ if (group != parent->data().toString().toStdString())
continue;
for (auto& [action_name, hotkey] : sub_actions) {
- if (action_name != action->data())
+ if (action_name != action->data().toString().toStdString())
continue;
hotkey.keyseq = QKeySequence(keyseq->text());
- hotkey.controller_keyseq = controller_keyseq->text();
+ hotkey.controller_keyseq = controller_keyseq->text().toStdString();
}
}
}
@@ -319,7 +323,7 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) {
void ConfigureHotkeys::RestoreDefaults() {
for (int r = 0; r < model->rowCount(); ++r) {
const QStandardItem* parent = model->item(r, 0);
- const int hotkey_size = static_cast<int>(Config::default_hotkeys.size());
+ const int hotkey_size = static_cast<int>(UISettings::default_hotkeys.size());
if (hotkey_size != parent->rowCount()) {
QMessageBox::warning(this, tr("Invalid hotkey settings"),
@@ -330,10 +334,11 @@ void ConfigureHotkeys::RestoreDefaults() {
for (int r2 = 0; r2 < parent->rowCount(); ++r2) {
model->item(r, 0)
->child(r2, hotkey_column)
- ->setText(Config::default_hotkeys[r2].shortcut.keyseq);
+ ->setText(QString::fromStdString(UISettings::default_hotkeys[r2].shortcut.keyseq));
model->item(r, 0)
->child(r2, controller_column)
- ->setText(Config::default_hotkeys[r2].shortcut.controller_keyseq);
+ ->setText(QString::fromStdString(
+ UISettings::default_hotkeys[r2].shortcut.controller_keyseq));
}
}
}
@@ -379,7 +384,7 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) {
void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) {
const QString& default_key_sequence =
- Config::default_hotkeys[index.row()].shortcut.controller_keyseq;
+ QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.controller_keyseq);
const auto [key_sequence_used, used_action] = IsUsedControllerKey(default_key_sequence);
if (key_sequence_used && default_key_sequence != model->data(index).toString()) {
@@ -393,7 +398,8 @@ void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) {
void ConfigureHotkeys::RestoreHotkey(QModelIndex index) {
const QKeySequence& default_key_sequence = QKeySequence::fromString(
- Config::default_hotkeys[index.row()].shortcut.keyseq, QKeySequence::NativeText);
+ QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.keyseq),
+ QKeySequence::NativeText);
const auto [key_sequence_used, used_action] = IsUsedKey(default_key_sequence);
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 @@
#include "core/core.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
+#include "frontend_common/config.h"
#include "ui_configure_input_per_game.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_input_per_game.h"
#include "yuzu/configuration/input_profiles.h"
-ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, Config* config_,
+ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, QtConfig* config_,
QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPerGame>()),
profiles(std::make_unique<InputProfiles>()), system{system_}, config{config_} {
@@ -110,6 +110,6 @@ void ConfigureInputPerGame::SaveConfiguration() {
// Clear all controls from the config in case the user reverted back to globals
config->ClearControlPlayerValues();
for (size_t index = 0; index < Settings::values.players.GetValue().size(); ++index) {
- config->SaveControlPlayerValue(index);
+ config->SaveQtControlPlayerValues(index);
}
}
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 @@
#include "ui_configure_input_per_game.h"
#include "yuzu/configuration/input_profiles.h"
+#include "yuzu/configuration/qt_config.h"
class QComboBox;
@@ -22,7 +23,7 @@ class ConfigureInputPerGame : public QWidget {
Q_OBJECT
public:
- explicit ConfigureInputPerGame(Core::System& system_, Config* config_,
+ explicit ConfigureInputPerGame(Core::System& system_, QtConfig* config_,
QWidget* parent = nullptr);
/// Load and Save configurations to settings file.
@@ -41,5 +42,5 @@ private:
std::array<QComboBox*, 8> profile_comboboxes;
Core::System& system;
- Config* config;
+ QtConfig* config;
};
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 @@
#include <QTimer>
#include "common/assert.h"
#include "common/param_package.h"
+#include "configuration/qt_config.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "core/hid/hid_types.h"
+#include "frontend_common/config.h"
#include "input_common/drivers/keyboard.h"
#include "input_common/drivers/mouse.h"
#include "input_common/main.h"
#include "ui_configure_input_player.h"
#include "yuzu/bootmanager.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_input_player.h"
#include "yuzu/configuration/configure_input_player_widget.h"
#include "yuzu/configuration/configure_mouse_panning.h"
@@ -1397,25 +1398,25 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
emulated_controller->SetButtonParam(
button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
- Config::default_buttons[button_id])});
+ QtConfig::default_buttons[button_id])});
}
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
Common::ParamPackage analog_param{};
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
- Config::default_analogs[analog_id][sub_button_id])};
+ QtConfig::default_analogs[analog_id][sub_button_id])};
SetAnalogParam(params, analog_param, analog_sub_buttons[sub_button_id]);
}
analog_param.Set("modifier", InputCommon::GenerateKeyboardParam(
- Config::default_stick_mod[analog_id]));
+ QtConfig::default_stick_mod[analog_id]));
emulated_controller->SetStickParam(analog_id, analog_param);
}
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
emulated_controller->SetMotionParam(
motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
- Config::default_motions[motion_id])});
+ QtConfig::default_motions[motion_id])});
}
// 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 @@
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/xts_archive.h"
#include "core/loader/loader.h"
+#include "frontend_common/config.h"
#include "ui_configure_per_game.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_audio.h"
#include "yuzu/configuration/configure_cpu.h"
@@ -50,8 +50,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));
const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename())
: fmt::format("{:016X}", title_id);
- game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig);
-
+ game_config = std::make_unique<QtConfig>(config_file_name, Config::ConfigType::PerGameConfig);
addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this);
audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, *builder, this);
cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, *builder, this);
@@ -108,7 +107,7 @@ void ConfigurePerGame::ApplyConfiguration() {
system.ApplySettings();
Settings::LogSettings();
- game_config->Save();
+ game_config->SaveAllValues();
}
void ConfigurePerGame::changeEvent(QEvent* event) {
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index cc2513001..c8ee46c04 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -12,9 +12,10 @@
#include "configuration/shared_widget.h"
#include "core/file_sys/vfs_types.h"
+#include "frontend_common/config.h"
#include "vk_device_info.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configuration_shared.h"
+#include "yuzu/configuration/qt_config.h"
#include "yuzu/configuration/shared_translation.h"
namespace Core {
@@ -72,7 +73,7 @@ private:
QGraphicsScene* scene;
- std::unique_ptr<Config> game_config;
+ std::unique_ptr<QtConfig> game_config;
Core::System& system;
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 @@
#include "core/file_sys/xts_archive.h"
#include "core/loader/loader.h"
#include "ui_configure_per_game_addons.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_input.h"
#include "yuzu/configuration/configure_per_game_addons.h"
#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 @@
#include <QTimer>
#include <fmt/format.h>
+#include "configuration/qt_config.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "input_common/drivers/keyboard.h"
@@ -15,7 +16,6 @@
#include "input_common/main.h"
#include "ui_configure_ringcon.h"
#include "yuzu/bootmanager.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_ringcon.h"
const std::array<std::string, ConfigureRingController::ANALOG_SUB_BUTTONS_NUM>
@@ -270,7 +270,7 @@ void ConfigureRingController::LoadConfiguration() {
void ConfigureRingController::RestoreDefaults() {
const std::string default_ring_string = InputCommon::GenerateAnalogParamFromKeys(
- 0, 0, Config::default_ringcon_analogs[0], Config::default_ringcon_analogs[1], 0, 0.05f);
+ 0, 0, QtConfig::default_ringcon_analogs[0], QtConfig::default_ringcon_analogs[1], 0, 0.05f);
emulated_controller->SetRingParam(Common::ParamPackage(default_ring_string));
UpdateUI();
}
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 @@
#include "core/core.h"
#include "core/hle/service/time/time_manager.h"
#include "ui_configure_system.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_system.h"
#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 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <memory>
+#include "common/settings.h"
#include "ui_configure_touchscreen_advanced.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_touchscreen_advanced.h"
ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent)
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index 82f3b6e78..dd43f0a0e 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -164,7 +164,7 @@ ConfigureUi::~ConfigureUi() = default;
void ConfigureUi::ApplyConfiguration() {
UISettings::values.theme =
- ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
+ ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString().toStdString();
UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
UISettings::values.show_compat = ui->show_compat->isChecked();
UISettings::values.show_size = ui->show_size->isChecked();
@@ -191,9 +191,10 @@ void ConfigureUi::RequestGameListUpdate() {
}
void ConfigureUi::SetConfiguration() {
- ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
+ ui->theme_combobox->setCurrentIndex(
+ ui->theme_combobox->findData(QString::fromStdString(UISettings::values.theme)));
ui->language_combobox->setCurrentIndex(
- ui->language_combobox->findData(UISettings::values.language));
+ ui->language_combobox->findData(QString::fromStdString(UISettings::values.language)));
ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue());
ui->show_compat->setChecked(UISettings::values.show_compat.GetValue());
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 @@
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
-#include "yuzu/configuration/config.h"
+#include "frontend_common/config.h"
#include "yuzu/configuration/input_profiles.h"
namespace FS = Common::FS;
@@ -44,7 +44,7 @@ InputProfiles::InputProfiles() {
if (IsINI(filename) && IsProfileNameValid(name_without_ext)) {
map_profiles.insert_or_assign(
name_without_ext,
- std::make_unique<Config>(name_without_ext, Config::ConfigType::InputProfile));
+ std::make_unique<QtConfig>(name_without_ext, Config::ConfigType::InputProfile));
}
return true;
@@ -85,7 +85,7 @@ bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t p
}
map_profiles.insert_or_assign(
- profile_name, std::make_unique<Config>(profile_name, Config::ConfigType::InputProfile));
+ profile_name, std::make_unique<QtConfig>(profile_name, Config::ConfigType::InputProfile));
return SaveProfile(profile_name, player_index);
}
@@ -113,7 +113,7 @@ bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t pla
return false;
}
- map_profiles[profile_name]->ReadControlPlayerValue(player_index);
+ map_profiles[profile_name]->ReadQtControlPlayerValues(player_index);
return true;
}
@@ -122,7 +122,7 @@ bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t pla
return false;
}
- map_profiles[profile_name]->SaveControlPlayerValue(player_index);
+ map_profiles[profile_name]->SaveQtControlPlayerValues(player_index);
return true;
}
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 @@
#include <string>
#include <unordered_map>
+#include "configuration/qt_config.h"
+
namespace Core {
class System;
}
@@ -30,5 +32,5 @@ public:
private:
bool ProfileExistsInMap(const std::string& profile_name) const;
- std::unordered_map<std::string, std::unique_ptr<Config>> map_profiles;
+ std::unordered_map<std::string, std::unique_ptr<QtConfig>> map_profiles;
};
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 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "input_common/main.h"
+#include "qt_config.h"
+#include "uisettings.h"
+
+const std::array<int, Settings::NativeButton::NumButtons> QtConfig::default_buttons = {
+ Qt::Key_C, Qt::Key_X, Qt::Key_V, Qt::Key_Z, Qt::Key_F,
+ Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T,
+ Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right,
+ Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0,
+ Qt::Key_Q, Qt::Key_E,
+};
+
+const std::array<int, Settings::NativeMotion::NumMotions> QtConfig::default_motions = {
+ Qt::Key_7,
+ Qt::Key_8,
+};
+
+const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> QtConfig::default_analogs{{
+ {
+ Qt::Key_W,
+ Qt::Key_S,
+ Qt::Key_A,
+ Qt::Key_D,
+ },
+ {
+ Qt::Key_I,
+ Qt::Key_K,
+ Qt::Key_J,
+ Qt::Key_L,
+ },
+}};
+
+const std::array<int, 2> QtConfig::default_stick_mod = {
+ Qt::Key_Shift,
+ 0,
+};
+
+const std::array<int, 2> QtConfig::default_ringcon_analogs{{
+ Qt::Key_A,
+ Qt::Key_D,
+}};
+
+QtConfig::QtConfig(const std::string& config_name, const ConfigType config_type)
+ : Config(config_type) {
+ Initialize(config_name);
+ if (config_type != ConfigType::InputProfile) {
+ ReadQtValues();
+ SaveQtValues();
+ }
+}
+
+QtConfig::~QtConfig() {
+ if (global) {
+ QtConfig::SaveAllValues();
+ }
+}
+
+void QtConfig::ReloadAllValues() {
+ Reload();
+ ReadQtValues();
+ SaveQtValues();
+}
+
+void QtConfig::SaveAllValues() {
+ Save();
+ SaveQtValues();
+}
+
+void QtConfig::ReadQtValues() {
+ if (global) {
+ ReadUIValues();
+ }
+ ReadQtControlValues();
+}
+
+void QtConfig::ReadQtPlayerValues(const std::size_t player_index) {
+ std::string player_prefix;
+ if (type != ConfigType::InputProfile) {
+ player_prefix.append("player_").append(ToString(player_index)).append("_");
+ }
+
+ auto& player = Settings::values.players.GetValue()[player_index];
+ if (IsCustomConfig()) {
+ const auto profile_name =
+ ReadStringSetting(std::string(player_prefix).append("profile_name"));
+ if (profile_name.empty()) {
+ // Use the global input config
+ player = Settings::values.players.GetValue(true)[player_index];
+ return;
+ }
+ }
+
+ for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ auto& player_buttons = player.buttons[i];
+
+ player_buttons = ReadStringSetting(
+ std::string(player_prefix).append(Settings::NativeButton::mapping[i]), default_param);
+ if (player_buttons.empty()) {
+ player_buttons = default_param;
+ }
+ }
+
+ for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
+ default_analogs[i][3], default_stick_mod[i], 0.5f);
+ auto& player_analogs = player.analogs[i];
+
+ player_analogs = ReadStringSetting(
+ std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), default_param);
+ if (player_analogs.empty()) {
+ player_analogs = default_param;
+ }
+ }
+
+ for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
+ auto& player_motions = player.motions[i];
+
+ player_motions = ReadStringSetting(
+ std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), default_param);
+ if (player_motions.empty()) {
+ player_motions = default_param;
+ }
+ }
+}
+
+void QtConfig::ReadHidbusValues() {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
+ auto& ringcon_analogs = Settings::values.ringcon_analogs;
+
+ ringcon_analogs = ReadStringSetting(std::string("ring_controller"), default_param);
+ if (ringcon_analogs.empty()) {
+ ringcon_analogs = default_param;
+ }
+}
+
+void QtConfig::ReadDebugControlValues() {
+ for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i];
+
+ debug_pad_buttons = ReadStringSetting(
+ std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), default_param);
+ if (debug_pad_buttons.empty()) {
+ debug_pad_buttons = default_param;
+ }
+ }
+
+ for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
+ default_analogs[i][3], default_stick_mod[i], 0.5f);
+ auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i];
+
+ debug_pad_analogs = ReadStringSetting(
+ std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), default_param);
+ if (debug_pad_analogs.empty()) {
+ debug_pad_analogs = default_param;
+ }
+ }
+}
+
+void QtConfig::ReadQtControlValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
+
+ Settings::values.players.SetGlobal(!IsCustomConfig());
+ for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
+ ReadQtPlayerValues(p);
+ }
+ if (IsCustomConfig()) {
+ EndGroup();
+ return;
+ }
+ ReadDebugControlValues();
+ ReadHidbusValues();
+
+ EndGroup();
+}
+
+void QtConfig::ReadPathValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Paths));
+
+ UISettings::values.roms_path = ReadStringSetting(std::string("romsPath"));
+ UISettings::values.symbols_path = ReadStringSetting(std::string("symbolsPath"));
+ UISettings::values.game_dir_deprecated =
+ ReadStringSetting(std::string("gameListRootDir"), std::string("."));
+ UISettings::values.game_dir_deprecated_deepscan =
+ ReadBooleanSetting(std::string("gameListDeepScan"), std::make_optional(false));
+
+ const int gamedirs_size = BeginArray(std::string("gamedirs"));
+ for (int i = 0; i < gamedirs_size; ++i) {
+ SetArrayIndex(i);
+ UISettings::GameDir game_dir;
+ game_dir.path = ReadStringSetting(std::string("path"));
+ game_dir.deep_scan =
+ ReadBooleanSetting(std::string("deep_scan"), std::make_optional(false));
+ game_dir.expanded = ReadBooleanSetting(std::string("expanded"), std::make_optional(true));
+ UISettings::values.game_dirs.append(game_dir);
+ }
+ EndArray();
+
+ // Create NAND and SD card directories if empty, these are not removable through the UI,
+ // also carries over old game list settings if present
+ if (UISettings::values.game_dirs.empty()) {
+ UISettings::GameDir game_dir;
+ game_dir.path = std::string("SDMC");
+ game_dir.expanded = true;
+ UISettings::values.game_dirs.append(game_dir);
+ game_dir.path = std::string("UserNAND");
+ UISettings::values.game_dirs.append(game_dir);
+ game_dir.path = std::string("SysNAND");
+ UISettings::values.game_dirs.append(game_dir);
+ if (UISettings::values.game_dir_deprecated != std::string(".")) {
+ game_dir.path = UISettings::values.game_dir_deprecated;
+ game_dir.deep_scan = UISettings::values.game_dir_deprecated_deepscan;
+ UISettings::values.game_dirs.append(game_dir);
+ }
+ }
+ UISettings::values.recent_files =
+ QString::fromStdString(ReadStringSetting(std::string("recentFiles")))
+ .split(QStringLiteral(", "), Qt::SkipEmptyParts, Qt::CaseSensitive);
+ UISettings::values.language = ReadStringSetting(std::string("language"), std::string(""));
+
+ EndGroup();
+}
+
+void QtConfig::ReadShortcutValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts));
+
+ for (const auto& [name, group, shortcut] : UISettings::default_hotkeys) {
+ BeginGroup(group);
+ BeginGroup(name);
+
+ // No longer using ReadSetting for shortcut.second as it inaccurately returns a value of 1
+ // for WidgetWithChildrenShortcut which is a value of 3. Needed to fix shortcuts the open
+ // a file dialog in windowed mode
+ UISettings::values.shortcuts.push_back(
+ {name,
+ group,
+ {ReadStringSetting(std::string("KeySeq"), shortcut.keyseq),
+ ReadStringSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq),
+ shortcut.context,
+ ReadBooleanSetting(std::string("Repeat"), std::optional(shortcut.repeat))}});
+
+ EndGroup(); // name
+ EndGroup(); // group
+ }
+
+ EndGroup();
+}
+
+void QtConfig::ReadUIValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Ui));
+
+ UISettings::values.theme = ReadStringSetting(
+ std::string("theme"),
+ std::string(UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second));
+
+ ReadUIGamelistValues();
+ ReadUILayoutValues();
+ ReadPathValues();
+ ReadScreenshotValues();
+ ReadShortcutValues();
+ ReadMultiplayerValues();
+
+ ReadCategory(Settings::Category::Ui);
+ ReadCategory(Settings::Category::UiGeneral);
+
+ EndGroup();
+}
+
+void QtConfig::ReadUIGamelistValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
+
+ ReadCategory(Settings::Category::UiGameList);
+
+ const int favorites_size = BeginArray("favorites");
+ for (int i = 0; i < favorites_size; i++) {
+ SetArrayIndex(i);
+ UISettings::values.favorited_ids.append(
+ ReadUnsignedIntegerSetting(std::string("program_id")));
+ }
+ EndArray();
+
+ EndGroup();
+}
+
+void QtConfig::ReadUILayoutValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
+
+ ReadCategory(Settings::Category::UiLayout);
+
+ EndGroup();
+}
+
+void QtConfig::ReadMultiplayerValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Multiplayer));
+
+ ReadCategory(Settings::Category::Multiplayer);
+
+ // Read ban list back
+ int size = BeginArray(std::string("username_ban_list"));
+ UISettings::values.multiplayer_ban_list.first.resize(size);
+ for (int i = 0; i < size; ++i) {
+ SetArrayIndex(i);
+ UISettings::values.multiplayer_ban_list.first[i] =
+ ReadStringSetting(std::string("username"), std::string(""));
+ }
+ EndArray();
+
+ size = BeginArray(std::string("ip_ban_list"));
+ UISettings::values.multiplayer_ban_list.second.resize(size);
+ for (int i = 0; i < size; ++i) {
+ UISettings::values.multiplayer_ban_list.second[i] =
+ ReadStringSetting("username", std::string(""));
+ }
+ EndArray();
+
+ EndGroup();
+}
+
+void QtConfig::SaveQtValues() {
+ if (global) {
+ SaveUIValues();
+ }
+ SaveQtControlValues();
+
+ WriteToIni();
+}
+
+void QtConfig::SaveQtPlayerValues(const std::size_t player_index) {
+ std::string player_prefix;
+ if (type != ConfigType::InputProfile) {
+ player_prefix = std::string("player_").append(ToString(player_index)).append("_");
+ }
+
+ const auto& player = Settings::values.players.GetValue()[player_index];
+ if (IsCustomConfig() && player.profile_name.empty()) {
+ // No custom profile selected
+ return;
+ }
+
+ for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ WriteSetting(std::string(player_prefix).append(Settings::NativeButton::mapping[i]),
+ player.buttons[i], std::make_optional(default_param));
+ }
+ for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
+ default_analogs[i][3], default_stick_mod[i], 0.5f);
+ WriteSetting(std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]),
+ player.analogs[i], std::make_optional(default_param));
+ }
+ for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
+ WriteSetting(std::string(player_prefix).append(Settings::NativeMotion::mapping[i]),
+ player.motions[i], std::make_optional(default_param));
+ }
+}
+
+void QtConfig::SaveDebugControlValues() {
+ for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ WriteSetting(std::string("debug_pad_").append(Settings::NativeButton::mapping[i]),
+ Settings::values.debug_pad_buttons[i], std::make_optional(default_param));
+ }
+ for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
+ default_analogs[i][3], default_stick_mod[i], 0.5f);
+ WriteSetting(std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]),
+ Settings::values.debug_pad_analogs[i], std::make_optional(default_param));
+ }
+}
+
+void QtConfig::SaveHidbusValues() {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
+ WriteSetting(std::string("ring_controller"), Settings::values.ringcon_analogs,
+ std::make_optional(default_param));
+}
+
+void QtConfig::SaveQtControlValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
+
+ Settings::values.players.SetGlobal(!IsCustomConfig());
+ for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
+ SaveQtPlayerValues(p);
+ }
+ if (IsCustomConfig()) {
+ EndGroup();
+ return;
+ }
+ SaveDebugControlValues();
+ SaveHidbusValues();
+
+ EndGroup();
+}
+
+void QtConfig::SavePathValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Paths));
+
+ WriteSetting(std::string("romsPath"), UISettings::values.roms_path);
+ WriteSetting(std::string("symbolsPath"), UISettings::values.symbols_path);
+ BeginArray(std::string("gamedirs"));
+ for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) {
+ SetArrayIndex(i);
+ const auto& game_dir = UISettings::values.game_dirs[i];
+ WriteSetting(std::string("path"), game_dir.path);
+ WriteSetting(std::string("deep_scan"), game_dir.deep_scan, std::make_optional(false));
+ WriteSetting(std::string("expanded"), game_dir.expanded, std::make_optional(true));
+ }
+ EndArray();
+
+ WriteSetting(std::string("recentFiles"),
+ UISettings::values.recent_files.join(QStringLiteral(", ")).toStdString());
+ WriteSetting(std::string("language"), UISettings::values.language);
+
+ EndGroup();
+}
+
+void QtConfig::SaveShortcutValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts));
+
+ // Lengths of UISettings::values.shortcuts & default_hotkeys are same.
+ // However, their ordering must also be the same.
+ for (std::size_t i = 0; i < UISettings::default_hotkeys.size(); i++) {
+ const auto& [name, group, shortcut] = UISettings::values.shortcuts[i];
+ const auto& default_hotkey = UISettings::default_hotkeys[i].shortcut;
+
+ BeginGroup(group);
+ BeginGroup(name);
+
+ WriteSetting(std::string("KeySeq"), shortcut.keyseq,
+ std::make_optional(default_hotkey.keyseq));
+ WriteSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq,
+ std::make_optional(default_hotkey.controller_keyseq));
+ WriteSetting(std::string("Context"), shortcut.context,
+ std::make_optional(default_hotkey.context));
+ WriteSetting(std::string("Repeat"), shortcut.repeat,
+ std::make_optional(default_hotkey.repeat));
+
+ EndGroup(); // name
+ EndGroup(); // group
+ }
+
+ EndGroup();
+}
+
+void QtConfig::SaveUIValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Ui));
+
+ WriteCategory(Settings::Category::Ui);
+ WriteCategory(Settings::Category::UiGeneral);
+
+ WriteSetting(std::string("theme"), UISettings::values.theme,
+ std::make_optional(std::string(
+ UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second)));
+
+ SaveUIGamelistValues();
+ SaveUILayoutValues();
+ SavePathValues();
+ SaveScreenshotValues();
+ SaveShortcutValues();
+ SaveMultiplayerValues();
+
+ EndGroup();
+}
+
+void QtConfig::SaveUIGamelistValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
+
+ WriteCategory(Settings::Category::UiGameList);
+
+ BeginArray(std::string("favorites"));
+ for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
+ SetArrayIndex(i);
+ WriteSetting(std::string("program_id"), UISettings::values.favorited_ids[i]);
+ }
+ EndArray(); // favorites
+
+ EndGroup();
+}
+
+void QtConfig::SaveUILayoutValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::UiLayout));
+
+ WriteCategory(Settings::Category::UiLayout);
+
+ EndGroup();
+}
+
+void QtConfig::SaveMultiplayerValues() {
+ BeginGroup(std::string("Multiplayer"));
+
+ WriteCategory(Settings::Category::Multiplayer);
+
+ // Write ban list
+ BeginArray(std::string("username_ban_list"));
+ for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.first.size(); ++i) {
+ SetArrayIndex(static_cast<int>(i));
+ WriteSetting(std::string("username"), UISettings::values.multiplayer_ban_list.first[i]);
+ }
+ EndArray(); // username_ban_list
+
+ BeginArray(std::string("ip_ban_list"));
+ for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.second.size(); ++i) {
+ SetArrayIndex(static_cast<int>(i));
+ WriteSetting(std::string("ip"), UISettings::values.multiplayer_ban_list.second[i]);
+ }
+ EndArray(); // ip_ban_list
+
+ EndGroup();
+}
+
+std::vector<Settings::BasicSetting*>& QtConfig::FindRelevantList(Settings::Category category) {
+ auto& map = Settings::values.linkage.by_category;
+ if (map.contains(category)) {
+ return Settings::values.linkage.by_category[category];
+ }
+ return UISettings::values.linkage.by_category[category];
+}
+
+void QtConfig::ReadQtControlPlayerValues(std::size_t player_index) {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
+
+ ReadPlayerValues(player_index);
+ ReadQtPlayerValues(player_index);
+
+ EndGroup();
+}
+
+void QtConfig::SaveQtControlPlayerValues(std::size_t player_index) {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
+
+ SavePlayerValues(player_index);
+ SaveQtPlayerValues(player_index);
+
+ EndGroup();
+
+ WriteToIni();
+}
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 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <QMetaType>
+
+#include "frontend_common/config.h"
+
+class QtConfig final : public Config {
+public:
+ explicit QtConfig(const std::string& config_name = "qt-config",
+ ConfigType config_type = ConfigType::GlobalConfig);
+ ~QtConfig() override;
+
+ void ReloadAllValues() override;
+ void SaveAllValues() override;
+
+ void ReadQtControlPlayerValues(std::size_t player_index);
+ void SaveQtControlPlayerValues(std::size_t player_index);
+
+protected:
+ void ReadQtValues();
+ void ReadQtPlayerValues(std::size_t player_index);
+ void ReadQtControlValues();
+ void ReadHidbusValues() override;
+ void ReadDebugControlValues() override;
+ void ReadPathValues() override;
+ void ReadShortcutValues() override;
+ void ReadUIValues() override;
+ void ReadUIGamelistValues() override;
+ void ReadUILayoutValues() override;
+ void ReadMultiplayerValues() override;
+
+ void SaveQtValues();
+ void SaveQtPlayerValues(std::size_t player_index);
+ void SaveQtControlValues();
+ void SaveHidbusValues() override;
+ void SaveDebugControlValues() override;
+ void SavePathValues() override;
+ void SaveShortcutValues() override;
+ void SaveUIValues() override;
+ void SaveUIGamelistValues() override;
+ void SaveUILayoutValues() override;
+ void SaveMultiplayerValues() override;
+
+ std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override;
+
+public:
+ static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
+ static const std::array<int, Settings::NativeMotion::NumMotions> default_motions;
+ static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
+ static const std::array<int, 2> default_stick_mod;
+ static const std::array<int, 2> default_ringcon_analogs;
+};
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 @@
#include <vector>
#include <QString>
#include "common/common_types.h"
+#include "common/settings.h"
class QWidget;
@@ -22,4 +23,46 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent);
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent);
+static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map = {
+ {Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))},
+ {Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))},
+ {Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))},
+};
+
+static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map = {
+ {Settings::ScalingFilter::NearestNeighbor,
+ QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))},
+ {Settings::ScalingFilter::Bilinear,
+ QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))},
+ {Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))},
+ {Settings::ScalingFilter::Gaussian,
+ QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))},
+ {Settings::ScalingFilter::ScaleForce,
+ QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))},
+ {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
+};
+
+static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map = {
+ {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
+ {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
+};
+
+static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map = {
+ {Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))},
+ {Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))},
+ {Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))},
+};
+
+static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map = {
+ {Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))},
+ {Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))},
+ {Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))},
+};
+
+static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map = {
+ {Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))},
+ {Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))},
+ {Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))},
+};
+
} // 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{{
bool IsDarkTheme() {
const auto& theme = UISettings::values.theme;
- return theme == QStringLiteral("qdarkstyle") ||
- theme == QStringLiteral("qdarkstyle_midnight_blue") ||
- theme == QStringLiteral("colorful_dark") ||
- theme == QStringLiteral("colorful_midnight_blue");
+ return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") ||
+ theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue");
}
} // 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() {
case GameListItemType::CustomDir: {
const UISettings::GameDir& game_dir =
UISettings::values.game_dirs[child->data(GameListDir::GameDirRole).toInt()];
- const QString icon_name = QFileInfo::exists(game_dir.path)
+ const QString icon_name = QFileInfo::exists(QString::fromStdString(game_dir.path))
? QStringLiteral("folder")
: QStringLiteral("bad_folder");
child->setData(
@@ -727,7 +727,8 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) {
});
connect(open_directory_location, &QAction::triggered, [this, game_dir_index] {
- emit OpenDirectory(UISettings::values.game_dirs[game_dir_index].path);
+ emit OpenDirectory(
+ QString::fromStdString(UISettings::values.game_dirs[game_dir_index].path));
});
}
@@ -869,7 +870,7 @@ const QStringList GameList::supported_file_extensions = {
QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")};
void GameList::RefreshGameDirectory() {
- if (!UISettings::values.game_dirs.isEmpty() && current_worker != nullptr) {
+ if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {
LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
PopulateAsync(UISettings::values.game_dirs);
}
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:
setData(QObject::tr("System Titles"), Qt::DisplayRole);
break;
case GameListItemType::CustomDir: {
- const QString icon_name = QFileInfo::exists(game_dir->path)
- ? QStringLiteral("folder")
- : QStringLiteral("bad_folder");
+ const QString path = QString::fromStdString(game_dir->path);
+ const QString icon_name =
+ QFileInfo::exists(path) ? QStringLiteral("folder") : QStringLiteral("bad_folder");
setData(QIcon::fromTheme(icon_name).pixmap(icon_size).scaled(
icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
- setData(game_dir->path, Qt::DisplayRole);
+ setData(path, Qt::DisplayRole);
break;
}
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() {
break;
}
- if (game_dir.path == QStringLiteral("SDMC")) {
+ if (game_dir.path == std::string("SDMC")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir);
DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
- } else if (game_dir.path == QStringLiteral("UserNAND")) {
+ } else if (game_dir.path == std::string("UserNAND")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir);
DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
- } else if (game_dir.path == QStringLiteral("SysNAND")) {
+ } else if (game_dir.path == std::string("SysNAND")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir);
DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
} else {
- watch_list.append(game_dir.path);
+ watch_list.append(QString::fromStdString(game_dir.path));
auto* const game_list_dir = new GameListDir(game_dir);
DirEntryReady(game_list_dir);
- ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(),
- game_dir.deep_scan, game_list_dir);
- ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(),
- game_dir.deep_scan, game_list_dir);
+ ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan,
+ game_list_dir);
+ ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path, game_dir.deep_scan,
+ game_list_dir);
}
}
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() {
for (const auto& hotkey : group.second) {
UISettings::values.shortcuts.push_back(
{hotkey.first, group.first,
- UISettings::ContextualShortcut({hotkey.second.keyseq.toString(),
+ UISettings::ContextualShortcut({hotkey.second.keyseq.toString().toStdString(),
hotkey.second.controller_keyseq,
hotkey.second.context, hotkey.second.repeat})});
}
@@ -31,12 +31,12 @@ void HotkeyRegistry::LoadHotkeys() {
// beginGroup()
for (auto shortcut : UISettings::values.shortcuts) {
Hotkey& hk = hotkey_groups[shortcut.group][shortcut.name];
- if (!shortcut.shortcut.keyseq.isEmpty()) {
- hk.keyseq =
- QKeySequence::fromString(shortcut.shortcut.keyseq, QKeySequence::NativeText);
+ if (!shortcut.shortcut.keyseq.empty()) {
+ hk.keyseq = QKeySequence::fromString(QString::fromStdString(shortcut.shortcut.keyseq),
+ QKeySequence::NativeText);
hk.context = static_cast<Qt::ShortcutContext>(shortcut.shortcut.context);
}
- if (!shortcut.shortcut.controller_keyseq.isEmpty()) {
+ if (!shortcut.shortcut.controller_keyseq.empty()) {
hk.controller_keyseq = shortcut.shortcut.controller_keyseq;
}
if (hk.shortcut) {
@@ -51,7 +51,8 @@ void HotkeyRegistry::LoadHotkeys() {
}
}
-QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) {
+QShortcut* HotkeyRegistry::GetHotkey(const std::string& group, const std::string& action,
+ QWidget* widget) {
Hotkey& hk = hotkey_groups[group][action];
if (!hk.shortcut) {
@@ -62,7 +63,8 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action
return hk.shortcut;
}
-ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, const QString& action,
+ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const std::string& group,
+ const std::string& action,
Core::HID::EmulatedController* controller) {
Hotkey& hk = hotkey_groups[group][action];
@@ -74,12 +76,12 @@ ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, co
return hk.controller_shortcut;
}
-QKeySequence HotkeyRegistry::GetKeySequence(const QString& group, const QString& action) {
+QKeySequence HotkeyRegistry::GetKeySequence(const std::string& group, const std::string& action) {
return hotkey_groups[group][action].keyseq;
}
-Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const QString& group,
- const QString& action) {
+Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const std::string& group,
+ const std::string& action) {
return hotkey_groups[group][action].context;
}
@@ -101,10 +103,10 @@ void ControllerShortcut::SetKey(const ControllerButtonSequence& buttons) {
button_sequence = buttons;
}
-void ControllerShortcut::SetKey(const QString& buttons_shortcut) {
+void ControllerShortcut::SetKey(const std::string& buttons_shortcut) {
ControllerButtonSequence sequence{};
- name = buttons_shortcut.toStdString();
- std::istringstream command_line(buttons_shortcut.toStdString());
+ name = buttons_shortcut;
+ std::istringstream command_line(buttons_shortcut);
std::string line;
while (std::getline(command_line, line, '+')) {
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:
~ControllerShortcut();
void SetKey(const ControllerButtonSequence& buttons);
- void SetKey(const QString& buttons_shortcut);
+ void SetKey(const std::string& buttons_shortcut);
ControllerButtonSequence ButtonSequence() const;
@@ -88,8 +88,8 @@ public:
* will be the same. Thus, you shouldn't rely on the caller really being the
* QShortcut's parent.
*/
- QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget);
- ControllerShortcut* GetControllerHotkey(const QString& group, const QString& action,
+ QShortcut* GetHotkey(const std::string& group, const std::string& action, QWidget* widget);
+ ControllerShortcut* GetControllerHotkey(const std::string& group, const std::string& action,
Core::HID::EmulatedController* controller);
/**
@@ -98,7 +98,7 @@ public:
* @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger").
* @param action Name of the action (e.g. "Start Emulation", "Load Image").
*/
- QKeySequence GetKeySequence(const QString& group, const QString& action);
+ QKeySequence GetKeySequence(const std::string& group, const std::string& action);
/**
* Returns a Qt::ShortcutContext object who can be connected to other
@@ -108,20 +108,20 @@ public:
* "Debugger").
* @param action Name of the action (e.g. "Start Emulation", "Load Image").
*/
- Qt::ShortcutContext GetShortcutContext(const QString& group, const QString& action);
+ Qt::ShortcutContext GetShortcutContext(const std::string& group, const std::string& action);
private:
struct Hotkey {
QKeySequence keyseq;
- QString controller_keyseq;
+ std::string controller_keyseq;
QShortcut* shortcut = nullptr;
ControllerShortcut* controller_shortcut = nullptr;
Qt::ShortcutContext context = Qt::WindowShortcut;
bool repeat;
};
- using HotkeyMap = std::map<QString, Hotkey>;
- using HotkeyGroupMap = std::map<QString, HotkeyMap>;
+ using HotkeyMap = std::map<std::string, Hotkey>;
+ using HotkeyGroupMap = std::map<std::string, HotkeyMap>;
HotkeyGroupMap hotkey_groups;
};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index e4b782fea..31aabb78a 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -47,6 +47,7 @@
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/set/set_sys.h"
#include "yuzu/multiplayer/state.h"
#include "yuzu/util/controller_navigation.h"
@@ -128,6 +129,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "core/loader/loader.h"
#include "core/perf_stats.h"
#include "core/telemetry_session.h"
+#include "frontend_common/config.h"
#include "input_common/drivers/tas_input.h"
#include "input_common/drivers/virtual_amiibo.h"
#include "input_common/main.h"
@@ -140,9 +142,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "yuzu/bootmanager.h"
#include "yuzu/compatdb.h"
#include "yuzu/compatibility_list.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_dialog.h"
#include "yuzu/configuration/configure_input_per_game.h"
+#include "yuzu/configuration/qt_config.h"
#include "yuzu/debugger/console.h"
#include "yuzu/debugger/controller.h"
#include "yuzu/debugger/profiler.h"
@@ -310,7 +312,7 @@ bool GMainWindow::CheckDarkMode() {
#endif // __unix__
}
-GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan)
+GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan)
: ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, config{std::move(config_)},
vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
@@ -672,7 +674,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers(
// Don't forget to apply settings.
system->HIDCore().DisableAllControllerConfiguration();
system->ApplySettings();
- config->Save();
+ config->SaveAllValues();
UpdateStatusButtons();
@@ -1043,7 +1045,12 @@ void GMainWindow::InitializeWidgets() {
statusBar()->addPermanentWidget(label);
}
- // TODO (flTobi): Add the widget when multiplayer is fully implemented
+ firmware_label = new QLabel();
+ firmware_label->setObjectName(QStringLiteral("FirmwareLabel"));
+ firmware_label->setVisible(false);
+ firmware_label->setFocusPolicy(Qt::NoFocus);
+ statusBar()->addPermanentWidget(firmware_label);
+
statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0);
statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0);
@@ -1125,7 +1132,7 @@ void GMainWindow::InitializeWidgets() {
connect(aa_status_button, &QPushButton::customContextMenuRequested,
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& aa_text_pair : Config::anti_aliasing_texts_map) {
+ for (auto const& aa_text_pair : ConfigurationShared::anti_aliasing_texts_map) {
context_menu.addAction(aa_text_pair.second, [this, aa_text_pair] {
Settings::values.anti_aliasing.SetValue(aa_text_pair.first);
UpdateAAText();
@@ -1149,7 +1156,7 @@ void GMainWindow::InitializeWidgets() {
connect(filter_status_button, &QPushButton::customContextMenuRequested,
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& filter_text_pair : Config::scaling_filter_texts_map) {
+ for (auto const& filter_text_pair : ConfigurationShared::scaling_filter_texts_map) {
context_menu.addAction(filter_text_pair.second, [this, filter_text_pair] {
Settings::values.scaling_filter.SetValue(filter_text_pair.first);
UpdateFilterText();
@@ -1172,7 +1179,7 @@ void GMainWindow::InitializeWidgets() {
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& pair : Config::use_docked_mode_texts_map) {
+ for (auto const& pair : ConfigurationShared::use_docked_mode_texts_map) {
context_menu.addAction(pair.second, [this, &pair] {
if (pair.first != Settings::values.use_docked_mode.GetValue()) {
OnToggleDockedMode();
@@ -1196,7 +1203,7 @@ void GMainWindow::InitializeWidgets() {
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& gpu_accuracy_pair : Config::gpu_accuracy_texts_map) {
+ for (auto const& gpu_accuracy_pair : ConfigurationShared::gpu_accuracy_texts_map) {
if (gpu_accuracy_pair.first == Settings::GpuAccuracy::Extreme) {
continue;
}
@@ -1225,7 +1232,8 @@ void GMainWindow::InitializeWidgets() {
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& renderer_backend_pair : Config::renderer_backend_texts_map) {
+ for (auto const& renderer_backend_pair :
+ ConfigurationShared::renderer_backend_texts_map) {
if (renderer_backend_pair.first == Settings::RendererBackend::Null) {
continue;
}
@@ -1290,16 +1298,17 @@ void GMainWindow::InitializeRecentFileMenuActions() {
void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name,
const bool tas_allowed) {
- static const QString main_window = QStringLiteral("Main Window");
- action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name));
- action->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, action_name));
+ static const auto main_window = std::string("Main Window");
+ action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name.toStdString()));
+ action->setShortcutContext(
+ hotkey_registry.GetShortcutContext(main_window, action_name.toStdString()));
action->setAutoRepeat(false);
this->addAction(action);
auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
const auto* controller_hotkey =
- hotkey_registry.GetControllerHotkey(main_window, action_name, controller);
+ hotkey_registry.GetControllerHotkey(main_window, action_name.toStdString(), controller);
connect(
controller_hotkey, &ControllerShortcut::Activated, this,
[action, tas_allowed, this] {
@@ -1331,10 +1340,11 @@ void GMainWindow::InitializeHotkeys() {
static const QString main_window = QStringLiteral("Main Window");
const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) {
- const auto* hotkey = hotkey_registry.GetHotkey(main_window, action_name, this);
+ const auto* hotkey =
+ hotkey_registry.GetHotkey(main_window.toStdString(), action_name.toStdString(), this);
auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
- const auto* controller_hotkey =
- hotkey_registry.GetControllerHotkey(main_window, action_name, controller);
+ const auto* controller_hotkey = hotkey_registry.GetControllerHotkey(
+ main_window.toStdString(), action_name.toStdString(), controller);
connect(hotkey, &QShortcut::activated, this, function);
connect(controller_hotkey, &ControllerShortcut::Activated, this, function,
Qt::QueuedConnection);
@@ -1906,7 +1916,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
// Save configurations
UpdateUISettings();
game_list->SaveInterfaceLayout();
- config->Save();
+ config->SaveAllValues();
u64 title_id{0};
@@ -1924,7 +1934,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
const auto config_file_name = title_id == 0
? Common::FS::PathToUTF8String(file_path.filename())
: fmt::format("{:016X}", title_id);
- Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig);
+ QtConfig per_game_config(config_file_name, Config::ConfigType::PerGameConfig);
system->HIDCore().ReloadInputDevices();
system->ApplySettings();
}
@@ -2149,6 +2159,10 @@ void GMainWindow::OnEmulationStopped() {
emu_frametime_label->setVisible(false);
renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan);
+ if (!firmware_label->text().isEmpty()) {
+ firmware_label->setVisible(true);
+ }
+
current_game_path.clear();
// When closing the game, destroy the GLWindow to clear the context after the game is closed
@@ -3123,7 +3137,7 @@ void GMainWindow::OnGameListAddDirectory() {
return;
}
- UISettings::GameDir game_dir{dir_path, false, true};
+ UISettings::GameDir game_dir{dir_path.toStdString(), false, true};
if (!UISettings::values.game_dirs.contains(game_dir)) {
UISettings::values.game_dirs.append(game_dir);
game_list->PopulateAsync(UISettings::values.game_dirs);
@@ -3169,14 +3183,14 @@ void GMainWindow::OnMenuLoadFile() {
"%1 is an identifier for the Switch executable file extensions.")
.arg(extensions);
const QString filename = QFileDialog::getOpenFileName(
- this, tr("Load File"), UISettings::values.roms_path, file_filter);
+ this, tr("Load File"), QString::fromStdString(UISettings::values.roms_path), file_filter);
is_load_file_select_active = false;
if (filename.isEmpty()) {
return;
}
- UISettings::values.roms_path = QFileInfo(filename).path();
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
BootGame(filename);
}
@@ -3209,7 +3223,8 @@ void GMainWindow::OnMenuInstallToNAND() {
"Image (*.xci)");
QStringList filenames = QFileDialog::getOpenFileNames(
- this, tr("Install Files"), UISettings::values.roms_path, file_filter);
+ this, tr("Install Files"), QString::fromStdString(UISettings::values.roms_path),
+ file_filter);
if (filenames.isEmpty()) {
return;
@@ -3227,7 +3242,7 @@ void GMainWindow::OnMenuInstallToNAND() {
}
// Save folder location of the first selected file
- UISettings::values.roms_path = QFileInfo(filenames[0]).path();
+ UISettings::values.roms_path = QFileInfo(filenames[0]).path().toStdString();
int remaining = filenames.size();
@@ -3572,7 +3587,7 @@ void GMainWindow::OnExit() {
void GMainWindow::OnSaveConfig() {
system->ApplySettings();
- config->Save();
+ config->SaveAllValues();
}
void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
@@ -3828,7 +3843,7 @@ void GMainWindow::OnConfigure() {
Settings::values.disabled_addons.clear();
- config = std::make_unique<Config>();
+ config = std::make_unique<QtConfig>();
UISettings::values.reset_to_defaults = false;
UISettings::values.game_dirs = std::move(old_game_dirs);
@@ -3863,7 +3878,7 @@ void GMainWindow::OnConfigure() {
UISettings::values.configuration_applied = false;
- config->Save();
+ config->SaveAllValues();
if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) {
render_window->installEventFilter(render_window);
@@ -4079,7 +4094,7 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file
UISettings::values.configuration_applied = false;
if (!is_powered_on) {
- config->Save();
+ config->SaveAllValues();
}
}
@@ -4312,7 +4327,7 @@ void GMainWindow::OnAlbum() {
system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::PhotoViewer);
const auto filename = QString::fromStdString(album_nca->GetFullPath());
- UISettings::values.roms_path = QFileInfo(filename).path();
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
BootGame(filename, AlbumId);
}
@@ -4336,7 +4351,7 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
system->GetAppletManager().SetCabinetMode(mode);
const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
- UISettings::values.roms_path = QFileInfo(filename).path();
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
BootGame(filename, CabinetId);
}
@@ -4359,7 +4374,7 @@ void GMainWindow::OnMiiEdit() {
system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit);
const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
- UISettings::values.roms_path = QFileInfo(filename).path();
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
BootGame(filename, MiiEditId);
}
@@ -4384,7 +4399,7 @@ void GMainWindow::OnOpenControllerMenu() {
system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Controller);
const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath()));
- UISettings::values.roms_path = QFileInfo(filename).path();
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
BootGame(filename, ControllerAppletId);
}
@@ -4574,11 +4589,13 @@ void GMainWindow::UpdateStatusBar() {
emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue());
game_fps_label->setVisible(true);
emu_frametime_label->setVisible(true);
+ firmware_label->setVisible(false);
}
void GMainWindow::UpdateGPUAccuracyButton() {
const auto gpu_accuracy = Settings::values.gpu_accuracy.GetValue();
- const auto gpu_accuracy_text = Config::gpu_accuracy_texts_map.find(gpu_accuracy)->second;
+ const auto gpu_accuracy_text =
+ ConfigurationShared::gpu_accuracy_texts_map.find(gpu_accuracy)->second;
gpu_accuracy_button->setText(gpu_accuracy_text.toUpper());
gpu_accuracy_button->setChecked(gpu_accuracy != Settings::GpuAccuracy::Normal);
}
@@ -4587,31 +4604,32 @@ void GMainWindow::UpdateDockedButton() {
const auto console_mode = Settings::values.use_docked_mode.GetValue();
dock_status_button->setChecked(Settings::IsDockedMode());
dock_status_button->setText(
- Config::use_docked_mode_texts_map.find(console_mode)->second.toUpper());
+ ConfigurationShared::use_docked_mode_texts_map.find(console_mode)->second.toUpper());
}
void GMainWindow::UpdateAPIText() {
const auto api = Settings::values.renderer_backend.GetValue();
- const auto renderer_status_text = Config::renderer_backend_texts_map.find(api)->second;
+ const auto renderer_status_text =
+ ConfigurationShared::renderer_backend_texts_map.find(api)->second;
renderer_status_button->setText(
api == Settings::RendererBackend::OpenGL
- ? tr("%1 %2").arg(
- renderer_status_text.toUpper(),
- Config::shader_backend_texts_map.find(Settings::values.shader_backend.GetValue())
- ->second)
+ ? tr("%1 %2").arg(renderer_status_text.toUpper(),
+ ConfigurationShared::shader_backend_texts_map
+ .find(Settings::values.shader_backend.GetValue())
+ ->second)
: renderer_status_text.toUpper());
}
void GMainWindow::UpdateFilterText() {
const auto filter = Settings::values.scaling_filter.GetValue();
- const auto filter_text = Config::scaling_filter_texts_map.find(filter)->second;
+ const auto filter_text = ConfigurationShared::scaling_filter_texts_map.find(filter)->second;
filter_status_button->setText(filter == Settings::ScalingFilter::Fsr ? tr("FSR")
: filter_text.toUpper());
}
void GMainWindow::UpdateAAText() {
const auto aa_mode = Settings::values.anti_aliasing.GetValue();
- const auto aa_text = Config::anti_aliasing_texts_map.find(aa_mode)->second;
+ const auto aa_text = ConfigurationShared::anti_aliasing_texts_map.find(aa_mode)->second;
aa_status_button->setText(aa_mode == Settings::AntiAliasing::None
? QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "NO AA"))
: aa_text.toUpper());
@@ -4775,6 +4793,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
"games."));
}
+ SetFirmwareVersion();
+
if (behavior == ReinitializeKeyBehavior::Warning) {
game_list->PopulateAsync(UISettings::values.game_dirs);
}
@@ -4802,7 +4822,7 @@ bool GMainWindow::CheckSystemArchiveDecryption() {
}
bool GMainWindow::CheckFirmwarePresence() {
- constexpr u64 MiiEditId = 0x0100000000001009ull;
+ constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
@@ -4817,6 +4837,28 @@ bool GMainWindow::CheckFirmwarePresence() {
return true;
}
+void GMainWindow::SetFirmwareVersion() {
+ Service::Set::FirmwareVersionFormat firmware_data{};
+ const auto result = Service::Set::GetFirmwareVersionImpl(
+ firmware_data, *system, Service::Set::GetFirmwareVersionType::Version2);
+
+ if (result.IsError() || !CheckFirmwarePresence()) {
+ LOG_INFO(Frontend, "Installed firmware: No firmware available");
+ firmware_label->setVisible(false);
+ return;
+ }
+
+ firmware_label->setVisible(true);
+
+ const std::string display_version(firmware_data.display_version.data());
+ const std::string display_title(firmware_data.display_title.data());
+
+ LOG_INFO(Frontend, "Installed firmware: {}", display_title);
+
+ firmware_label->setText(QString::fromStdString(display_version));
+ firmware_label->setToolTip(QString::fromStdString(display_title));
+}
+
bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id,
u64* selected_title_id, u8* selected_content_record_type) {
using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>;
@@ -4898,6 +4940,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
UpdateUISettings();
game_list->SaveInterfaceLayout();
+ UISettings::SaveWindowState();
hotkey_registry.SaveHotkeys();
// Unload controllers early
@@ -5036,9 +5079,9 @@ static void AdjustLinkColor() {
}
void GMainWindow::UpdateUITheme() {
- const QString default_theme =
- QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second);
- QString current_theme = UISettings::values.theme;
+ const QString default_theme = QString::fromUtf8(
+ UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second);
+ QString current_theme = QString::fromStdString(UISettings::values.theme);
if (current_theme.isEmpty()) {
current_theme = default_theme;
@@ -5066,7 +5109,7 @@ void GMainWindow::UpdateUITheme() {
QFile f(theme_uri);
if (!f.open(QFile::ReadOnly | QFile::Text)) {
LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme",
- UISettings::values.theme.toStdString());
+ UISettings::values.theme);
current_theme = default_theme;
}
}
@@ -5079,7 +5122,7 @@ void GMainWindow::UpdateUITheme() {
setStyleSheet(ts.readAll());
} else {
LOG_ERROR(Frontend, "Unable to set style \"{}\", stylesheet file not found",
- UISettings::values.theme.toStdString());
+ UISettings::values.theme);
qApp->setStyleSheet({});
setStyleSheet({});
}
@@ -5088,27 +5131,28 @@ void GMainWindow::UpdateUITheme() {
void GMainWindow::LoadTranslation() {
bool loaded;
- if (UISettings::values.language.isEmpty()) {
+ if (UISettings::values.language.empty()) {
// If the selected language is empty, use system locale
loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/"));
} else {
// Otherwise load from the specified file
- loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/"));
+ loaded = translator.load(QString::fromStdString(UISettings::values.language),
+ QStringLiteral(":/languages/"));
}
if (loaded) {
qApp->installTranslator(&translator);
} else {
- UISettings::values.language = QStringLiteral("en");
+ UISettings::values.language = std::string("en");
}
}
void GMainWindow::OnLanguageChanged(const QString& locale) {
- if (UISettings::values.language != QStringLiteral("en")) {
+ if (UISettings::values.language != std::string("en")) {
qApp->removeTranslator(&translator);
}
- UISettings::values.language = locale;
+ UISettings::values.language = locale.toStdString();
LoadTranslation();
ui->retranslateUi(this);
multiplayer_state->retranslateUi();
@@ -5134,7 +5178,7 @@ void GMainWindow::changeEvent(QEvent* event) {
// UpdateUITheme is a decent work around
if (event->type() == QEvent::PaletteChange) {
const QPalette test_palette(qApp->palette());
- const QString current_theme = UISettings::values.theme;
+ const QString current_theme = QString::fromStdString(UISettings::values.theme);
// Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
static QColor last_window_color;
const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
@@ -5228,7 +5272,8 @@ static void SetHighDPIAttributes() {
}
int main(int argc, char* argv[]) {
- std::unique_ptr<Config> config = std::make_unique<Config>();
+ std::unique_ptr<QtConfig> config = std::make_unique<QtConfig>();
+ UISettings::RestoreWindowState(config);
bool has_broken_vulkan = false;
bool is_child = false;
if (CheckEnvVars(&is_child)) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index eea39815a..733d6291e 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -15,6 +15,7 @@
#include "common/announce_multiplayer_room.h"
#include "common/common_types.h"
+#include "configuration/qt_config.h"
#include "input_common/drivers/tas_input.h"
#include "yuzu/compatibility_list.h"
#include "yuzu/hotkeys.h"
@@ -26,7 +27,7 @@
#include <QtDBus/QtDBus>
#endif
-class Config;
+class QtConfig;
class ClickableLabel;
class EmuThread;
class GameList;
@@ -185,7 +186,7 @@ class GMainWindow : public QMainWindow {
public:
void filterBarSetChecked(bool state);
void UpdateUITheme();
- explicit GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan);
+ explicit GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan);
~GMainWindow() override;
bool DropAction(QDropEvent* event);
@@ -456,6 +457,7 @@ private:
bool CheckDarkMode();
bool CheckSystemArchiveDecryption();
bool CheckFirmwarePresence();
+ void SetFirmwareVersion();
void ConfigureFilesystemProvider(const std::string& filepath);
/**
* Open (or not) the right confirm dialog based on current setting and game exit lock
@@ -510,6 +512,7 @@ private:
QLabel* game_fps_label = nullptr;
QLabel* emu_frametime_label = nullptr;
QLabel* tas_label = nullptr;
+ QLabel* firmware_label = nullptr;
QPushButton* gpu_accuracy_button = nullptr;
QPushButton* renderer_status_button = nullptr;
QPushButton* dock_status_button = nullptr;
@@ -520,7 +523,7 @@ private:
QSlider* volume_slider = nullptr;
QTimer status_bar_update_timer;
- std::unique_ptr<Config> config;
+ std::unique_ptr<QtConfig> config;
// Whether emulation is currently running in yuzu.
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 @@
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include <QSettings>
+#include "common/fs/fs.h"
+#include "common/fs/path_util.h"
#include "yuzu/uisettings.h"
#ifndef CANNOT_EXPLICITLY_INSTANTIATE
@@ -15,6 +18,8 @@ template class Setting<unsigned long long>;
} // namespace Settings
#endif
+namespace FS = Common::FS;
+
namespace UISettings {
const Themes themes{{
@@ -28,10 +33,8 @@ const Themes themes{{
bool IsDarkTheme() {
const auto& theme = UISettings::values.theme;
- return theme == QStringLiteral("qdarkstyle") ||
- theme == QStringLiteral("qdarkstyle_midnight_blue") ||
- theme == QStringLiteral("colorful_dark") ||
- theme == QStringLiteral("colorful_midnight_blue");
+ return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") ||
+ theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue");
}
Values values = {};
@@ -52,4 +55,58 @@ u32 CalculateWidth(u32 height, Settings::AspectRatio ratio) {
return height * 16 / 9;
}
+void SaveWindowState() {
+ const auto window_state_config_loc =
+ FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini");
+
+ void(FS::CreateParentDir(window_state_config_loc));
+ QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat);
+
+ config.setValue(QStringLiteral("geometry"), values.geometry);
+ config.setValue(QStringLiteral("state"), values.state);
+ config.setValue(QStringLiteral("geometryRenderWindow"), values.renderwindow_geometry);
+ config.setValue(QStringLiteral("gameListHeaderState"), values.gamelist_header_state);
+ config.setValue(QStringLiteral("microProfileDialogGeometry"), values.microprofile_geometry);
+
+ config.sync();
+}
+
+void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig) {
+ const auto window_state_config_loc =
+ FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini");
+
+ // Migrate window state from old location
+ if (!FS::Exists(window_state_config_loc) && qtConfig->Exists("UI", "UILayout\\geometry")) {
+ const auto config_loc =
+ FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "qt-config.ini");
+ QSettings config(QString::fromStdString(config_loc), QSettings::IniFormat);
+
+ config.beginGroup(QStringLiteral("UI"));
+ config.beginGroup(QStringLiteral("UILayout"));
+ values.geometry = config.value(QStringLiteral("geometry")).toByteArray();
+ values.state = config.value(QStringLiteral("state")).toByteArray();
+ values.renderwindow_geometry =
+ config.value(QStringLiteral("geometryRenderWindow")).toByteArray();
+ values.gamelist_header_state =
+ config.value(QStringLiteral("gameListHeaderState")).toByteArray();
+ values.microprofile_geometry =
+ config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray();
+ config.endGroup();
+ config.endGroup();
+ return;
+ }
+
+ void(FS::CreateParentDir(window_state_config_loc));
+ const QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat);
+
+ values.geometry = config.value(QStringLiteral("geometry")).toByteArray();
+ values.state = config.value(QStringLiteral("state")).toByteArray();
+ values.renderwindow_geometry =
+ config.value(QStringLiteral("geometryRenderWindow")).toByteArray();
+ values.gamelist_header_state =
+ config.value(QStringLiteral("gameListHeaderState")).toByteArray();
+ values.microprofile_geometry =
+ config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray();
+}
+
} // 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 @@
#include "common/common_types.h"
#include "common/settings.h"
#include "common/settings_enums.h"
+#include "configuration/qt_config.h"
using Settings::Category;
using Settings::ConfirmStop;
@@ -37,15 +38,15 @@ namespace UISettings {
bool IsDarkTheme();
struct ContextualShortcut {
- QString keyseq;
- QString controller_keyseq;
+ std::string keyseq;
+ std::string controller_keyseq;
int context;
bool repeat;
};
struct Shortcut {
- QString name;
- QString group;
+ std::string name;
+ std::string group;
ContextualShortcut shortcut;
};
@@ -58,11 +59,19 @@ enum class Theme {
MidnightBlueColorful,
};
+static constexpr Theme default_theme{
+#ifdef _WIN32
+ Theme::DarkColorful
+#else
+ Theme::DefaultColorful
+#endif
+};
+
using Themes = std::array<std::pair<const char*, const char*>, 6>;
extern const Themes themes;
struct GameDir {
- QString path;
+ std::string path;
bool deep_scan = false;
bool expanded = false;
bool operator==(const GameDir& rhs) const {
@@ -144,15 +153,15 @@ struct Values {
Category::Screenshots};
Setting<u32> screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots};
- QString roms_path;
- QString symbols_path;
- QString game_dir_deprecated;
+ std::string roms_path;
+ std::string symbols_path;
+ std::string game_dir_deprecated;
bool game_dir_deprecated_deepscan;
- QVector<UISettings::GameDir> game_dirs;
+ QVector<GameDir> game_dirs;
QStringList recent_files;
- QString language;
+ std::string language;
- QString theme;
+ std::string theme;
// Shortcut name <Shortcut, context>
std::vector<Shortcut> shortcuts;
@@ -206,6 +215,54 @@ extern Values values;
u32 CalculateWidth(u32 height, Settings::AspectRatio ratio);
+void SaveWindowState();
+void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig);
+
+// This shouldn't have anything except static initializers (no functions). So
+// QKeySequence(...).toString() is NOT ALLOWED HERE.
+// This must be in alphabetical order according to action name as it must have the same order as
+// UISetting::values.shortcuts, which is alphabetically ordered.
+// clang-format off
+const std::array<Shortcut, 23> default_hotkeys{{
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Esc"), std::string(""), Qt::WindowShortcut, false}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {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}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string(""), std::string(""), Qt::ApplicationShortcut, false}},
+ {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}},
+}};
+// clang-format on
+
} // namespace UISettings
Q_DECLARE_METATYPE(UISettings::GameDir*);
+
+// These metatype declarations cannot be in common/settings.h because core is devoid of QT
+Q_DECLARE_METATYPE(Settings::CpuAccuracy);
+Q_DECLARE_METATYPE(Settings::GpuAccuracy);
+Q_DECLARE_METATYPE(Settings::FullscreenMode);
+Q_DECLARE_METATYPE(Settings::NvdecEmulation);
+Q_DECLARE_METATYPE(Settings::ResolutionSetup);
+Q_DECLARE_METATYPE(Settings::ScalingFilter);
+Q_DECLARE_METATYPE(Settings::AntiAliasing);
+Q_DECLARE_METATYPE(Settings::RendererBackend);
+Q_DECLARE_METATYPE(Settings::ShaderBackend);
+Q_DECLARE_METATYPE(Settings::AstcRecompression);
+Q_DECLARE_METATYPE(Settings::AstcDecodeMode);
diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt
index 46eddf423..fbeba8813 100644
--- a/src/yuzu_cmd/CMakeLists.txt
+++ b/src/yuzu_cmd/CMakeLists.txt
@@ -13,9 +13,6 @@ function(create_resource file output filename)
endfunction()
add_executable(yuzu-cmd
- config.cpp
- config.h
- default_ini.h
emu_window/emu_window_sdl2.cpp
emu_window/emu_window_sdl2.h
emu_window/emu_window_sdl2_gl.cpp
@@ -25,14 +22,16 @@ add_executable(yuzu-cmd
emu_window/emu_window_sdl2_vk.cpp
emu_window/emu_window_sdl2_vk.h
precompiled_headers.h
+ sdl_config.cpp
+ sdl_config.h
yuzu.cpp
yuzu.rc
)
create_target_directory_groups(yuzu-cmd)
-target_link_libraries(yuzu-cmd PRIVATE common core input_common)
-target_link_libraries(yuzu-cmd PRIVATE inih::INIReader glad)
+target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common)
+target_link_libraries(yuzu-cmd PRIVATE glad)
if (MSVC)
target_link_libraries(yuzu-cmd PRIVATE getopt)
endif()
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
deleted file mode 100644
index 0d25ff400..000000000
--- a/src/yuzu_cmd/config.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-// SPDX-FileCopyrightText: 2014 Citra Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <memory>
-#include <optional>
-#include <sstream>
-#include <INIReader.h>
-#include <SDL.h>
-#include "common/fs/file.h"
-#include "common/fs/fs.h"
-#include "common/fs/path_util.h"
-#include "common/logging/log.h"
-#include "common/settings.h"
-#include "core/hle/service/acc/profile_manager.h"
-#include "input_common/main.h"
-#include "yuzu_cmd/config.h"
-#include "yuzu_cmd/default_ini.h"
-
-namespace FS = Common::FS;
-
-const std::filesystem::path default_config_path =
- FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini";
-
-Config::Config(std::optional<std::filesystem::path> config_path)
- : sdl2_config_loc{config_path.value_or(default_config_path)},
- sdl2_config{std::make_unique<INIReader>(FS::PathToUTF8String(sdl2_config_loc))} {
- Reload();
-}
-
-Config::~Config() = default;
-
-bool Config::LoadINI(const std::string& default_contents, bool retry) {
- const auto config_loc_str = FS::PathToUTF8String(sdl2_config_loc);
- if (sdl2_config->ParseError() < 0) {
- if (retry) {
- LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...",
- config_loc_str);
-
- void(FS::CreateParentDir(sdl2_config_loc));
- void(FS::WriteStringToFile(sdl2_config_loc, FS::FileType::TextFile, default_contents));
-
- sdl2_config = std::make_unique<INIReader>(config_loc_str);
-
- return LoadINI(default_contents, false);
- }
- LOG_ERROR(Config, "Failed.");
- return false;
- }
- LOG_INFO(Config, "Successfully loaded {}", config_loc_str);
- return true;
-}
-
-static const std::array<int, Settings::NativeButton::NumButtons> default_buttons = {
- SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T,
- SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W,
- SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
-};
-
-static const std::array<int, Settings::NativeMotion::NumMotions> default_motions = {
- SDL_SCANCODE_7,
- SDL_SCANCODE_8,
-};
-
-static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs{{
- {
- SDL_SCANCODE_UP,
- SDL_SCANCODE_DOWN,
- SDL_SCANCODE_LEFT,
- SDL_SCANCODE_RIGHT,
- SDL_SCANCODE_D,
- },
- {
- SDL_SCANCODE_I,
- SDL_SCANCODE_K,
- SDL_SCANCODE_J,
- SDL_SCANCODE_L,
- SDL_SCANCODE_D,
- },
-}};
-
-template <>
-void Config::ReadSetting(const std::string& group, Settings::Setting<std::string>& setting) {
- std::string setting_value = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault());
- if (setting_value.empty()) {
- setting_value = setting.GetDefault();
- }
- setting = std::move(setting_value);
-}
-
-template <>
-void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) {
- setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
-}
-
-template <typename Type, bool ranged>
-void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) {
- setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(),
- static_cast<long>(setting.GetDefault())));
-}
-
-void Config::ReadCategory(Settings::Category category) {
- for (const auto setting : Settings::values.linkage.by_category[category]) {
- const char* category_name = [&]() {
- if (category == Settings::Category::Controls) {
- // For compatibility with older configs
- return "ControlsGeneral";
- } else {
- return Settings::TranslateCategory(category);
- }
- }();
- std::string setting_value =
- sdl2_config->Get(category_name, setting->GetLabel(), setting->DefaultToString());
- setting->LoadString(setting_value);
- }
-}
-
-void Config::ReadValues() {
- // Controls
- ReadCategory(Settings::Category::Controls);
-
- for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
- auto& player = Settings::values.players.GetValue()[p];
-
- const auto group = fmt::format("ControlsP{}", p);
- for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- player.buttons[i] =
- sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param);
- if (player.buttons[i].empty()) {
- player.buttons[i] = default_param;
- }
- }
-
- for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
- default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
- default_analogs[i][3], default_analogs[i][4], 0.5f);
- player.analogs[i] =
- sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param);
- if (player.analogs[i].empty()) {
- player.analogs[i] = default_param;
- }
- }
-
- for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
- const std::string default_param =
- InputCommon::GenerateKeyboardParam(default_motions[i]);
- auto& player_motions = player.motions[i];
-
- player_motions =
- sdl2_config->Get(group, Settings::NativeMotion::mapping[i], default_param);
- if (player_motions.empty()) {
- player_motions = default_param;
- }
- }
-
- player.connected = sdl2_config->GetBoolean(group, "connected", false);
- }
-
- for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- Settings::values.debug_pad_buttons[i] = sdl2_config->Get(
- "ControlsGeneral", std::string("debug_pad_") + Settings::NativeButton::mapping[i],
- default_param);
- if (Settings::values.debug_pad_buttons[i].empty())
- Settings::values.debug_pad_buttons[i] = default_param;
- }
-
- for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
- std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
- default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
- default_analogs[i][3], default_analogs[i][4], 0.5f);
- Settings::values.debug_pad_analogs[i] = sdl2_config->Get(
- "ControlsGeneral", std::string("debug_pad_") + Settings::NativeAnalog::mapping[i],
- default_param);
- if (Settings::values.debug_pad_analogs[i].empty())
- Settings::values.debug_pad_analogs[i] = default_param;
- }
-
- Settings::values.touchscreen.enabled =
- sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true);
- Settings::values.touchscreen.rotation_angle =
- sdl2_config->GetInteger("ControlsGeneral", "touch_angle", 0);
- Settings::values.touchscreen.diameter_x =
- sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_x", 15);
- Settings::values.touchscreen.diameter_y =
- sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_y", 15);
-
- int num_touch_from_button_maps =
- sdl2_config->GetInteger("ControlsGeneral", "touch_from_button_map", 0);
- if (num_touch_from_button_maps > 0) {
- for (int i = 0; i < num_touch_from_button_maps; ++i) {
- Settings::TouchFromButtonMap map;
- map.name = sdl2_config->Get("ControlsGeneral",
- std::string("touch_from_button_maps_") + std::to_string(i) +
- std::string("_name"),
- "default");
- const int num_touch_maps = sdl2_config->GetInteger(
- "ControlsGeneral",
- std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"),
- 0);
- map.buttons.reserve(num_touch_maps);
-
- for (int j = 0; j < num_touch_maps; ++j) {
- std::string touch_mapping =
- sdl2_config->Get("ControlsGeneral",
- std::string("touch_from_button_maps_") + std::to_string(i) +
- std::string("_bind_") + std::to_string(j),
- "");
- map.buttons.emplace_back(std::move(touch_mapping));
- }
-
- Settings::values.touch_from_button_maps.emplace_back(std::move(map));
- }
- } else {
- Settings::values.touch_from_button_maps.emplace_back(
- Settings::TouchFromButtonMap{"default", {}});
- num_touch_from_button_maps = 1;
- }
- Settings::values.touch_from_button_map_index = std::clamp(
- Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
-
- ReadCategory(Settings::Category::Audio);
- ReadCategory(Settings::Category::Core);
- ReadCategory(Settings::Category::Cpu);
- ReadCategory(Settings::Category::CpuDebug);
- ReadCategory(Settings::Category::CpuUnsafe);
- ReadCategory(Settings::Category::Renderer);
- ReadCategory(Settings::Category::RendererAdvanced);
- ReadCategory(Settings::Category::RendererDebug);
- ReadCategory(Settings::Category::System);
- ReadCategory(Settings::Category::SystemAudio);
- ReadCategory(Settings::Category::DataStorage);
- ReadCategory(Settings::Category::Debugging);
- ReadCategory(Settings::Category::DebuggingGraphics);
- ReadCategory(Settings::Category::Miscellaneous);
- ReadCategory(Settings::Category::Network);
- ReadCategory(Settings::Category::WebService);
-
- // Data Storage
- FS::SetYuzuPath(FS::YuzuPath::NANDDir,
- sdl2_config->Get("Data Storage", "nand_directory",
- FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
- FS::SetYuzuPath(FS::YuzuPath::SDMCDir,
- sdl2_config->Get("Data Storage", "sdmc_directory",
- FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
- FS::SetYuzuPath(FS::YuzuPath::LoadDir,
- sdl2_config->Get("Data Storage", "load_directory",
- FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
- FS::SetYuzuPath(FS::YuzuPath::DumpDir,
- sdl2_config->Get("Data Storage", "dump_directory",
- FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
-
- // Debugging
- Settings::values.record_frame_times =
- sdl2_config->GetBoolean("Debugging", "record_frame_times", false);
-
- const auto title_list = sdl2_config->Get("AddOns", "title_ids", "");
- std::stringstream ss(title_list);
- std::string line;
- while (std::getline(ss, line, '|')) {
- const auto title_id = std::strtoul(line.c_str(), nullptr, 16);
- const auto disabled_list = sdl2_config->Get("AddOns", "disabled_" + line, "");
-
- std::stringstream inner_ss(disabled_list);
- std::string inner_line;
- std::vector<std::string> out;
- while (std::getline(inner_ss, inner_line, '|')) {
- out.push_back(inner_line);
- }
-
- Settings::values.disabled_addons.insert_or_assign(title_id, out);
- }
-}
-
-void Config::Reload() {
- LoadINI(DefaultINI::sdl2_config_file);
- ReadValues();
-}
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 @@
-// SPDX-FileCopyrightText: 2014 Citra Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <filesystem>
-#include <memory>
-#include <optional>
-#include <string>
-
-#include "common/settings.h"
-
-class INIReader;
-
-class Config {
- std::filesystem::path sdl2_config_loc;
- std::unique_ptr<INIReader> sdl2_config;
-
- bool LoadINI(const std::string& default_contents = "", bool retry = true);
- void ReadValues();
-
-public:
- explicit Config(std::optional<std::filesystem::path> config_path);
- ~Config();
-
- void Reload();
-
-private:
- /**
- * Applies a value read from the sdl2_config to a Setting.
- *
- * @param group The name of the INI group
- * @param setting The yuzu setting to modify
- */
- template <typename Type, bool ranged>
- void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
- void ReadCategory(Settings::Category category);
-};
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 @@
-// SPDX-FileCopyrightText: 2014 Citra Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-namespace DefaultINI {
-
-const char* sdl2_config_file =
- R"(
-[ControlsP0]
-# The input devices and parameters for each Switch native input
-# The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ...
-# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
-# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
-
-# Indicates if this player should be connected at boot
-# 0 (default): Disabled, 1: Enabled
-connected=
-
-# for button input, the following devices are available:
-# - "keyboard" (default) for keyboard input. Required parameters:
-# - "code": the code of the key to bind
-# - "sdl" for joystick input using SDL. Required parameters:
-# - "guid": SDL identification GUID of the joystick
-# - "port": the index of the joystick to bind
-# - "button"(optional): the index of the button to bind
-# - "hat"(optional): the index of the hat to bind as direction buttons
-# - "axis"(optional): the index of the axis to bind
-# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right"
-# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
-# triggered if the axis value crosses
-# - "direction"(only used for axis): "+" means the button is triggered when the axis value
-# is greater than the threshold; "-" means the button is triggered when the axis value
-# is smaller than the threshold
-button_a=
-button_b=
-button_x=
-button_y=
-button_lstick=
-button_rstick=
-button_l=
-button_r=
-button_zl=
-button_zr=
-button_plus=
-button_minus=
-button_dleft=
-button_dup=
-button_dright=
-button_ddown=
-button_lstick_left=
-button_lstick_up=
-button_lstick_right=
-button_lstick_down=
-button_sl=
-button_sr=
-button_home=
-button_screenshot=
-
-# for analog input, the following devices are available:
-# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters:
-# - "up", "down", "left", "right": sub-devices for each direction.
-# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00"
-# - "modifier": sub-devices as a modifier.
-# - "modifier_scale": a float number representing the applied modifier scale to the analog input.
-# Must be in range of 0.0-1.0. Defaults to 0.5
-# - "sdl" for joystick input using SDL. Required parameters:
-# - "guid": SDL identification GUID of the joystick
-# - "port": the index of the joystick to bind
-# - "axis_x": the index of the axis to bind as x-axis (default to 0)
-# - "axis_y": the index of the axis to bind as y-axis (default to 1)
-lstick=
-rstick=
-
-# for motion input, the following devices are available:
-# - "keyboard" (default) for emulating random motion input from buttons. Required parameters:
-# - "code": the code of the key to bind
-# - "sdl" for motion input using SDL. Required parameters:
-# - "guid": SDL identification GUID of the joystick
-# - "port": the index of the joystick to bind
-# - "motion": the index of the motion sensor to bind
-# - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters:
-# - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001"
-# - "port": the port of the cemu hook server
-# - "pad": the index of the joystick
-# - "motion": the index of the motion sensor of the joystick to bind
-motionleft=
-motionright=
-
-[ControlsGeneral]
-# To use the debug_pad, prepend `debug_pad_` before each button setting above.
-# i.e. debug_pad_button_a=
-
-# Enable debug pad inputs to the guest
-# 0 (default): Disabled, 1: Enabled
-debug_pad_enabled =
-
-# Enable sdl raw input. Allows to configure up to 8 xinput controllers.
-# 0 (default): Disabled, 1: Enabled
-enable_raw_input =
-
-# Enable yuzu joycon driver instead of SDL drive.
-# 0: Disabled, 1 (default): Enabled
-enable_joycon_driver =
-
-# Emulates an analog input from buttons. Allowing to dial any angle.
-# 0 (default): Disabled, 1: Enabled
-emulate_analog_keyboard =
-
-# Whether to enable or disable vibration
-# 0: Disabled, 1 (default): Enabled
-vibration_enabled=
-
-# Whether to enable or disable accurate vibrations
-# 0 (default): Disabled, 1: Enabled
-enable_accurate_vibrations=
-
-# Enables controller motion inputs
-# 0: Disabled, 1 (default): Enabled
-motion_enabled =
-
-# Defines the udp device's touch screen coordinate system for cemuhookudp devices
-# - "min_x", "min_y", "max_x", "max_y"
-touch_device=
-
-# for mapping buttons to touch inputs.
-#touch_from_button_map=1
-#touch_from_button_maps_0_name=default
-#touch_from_button_maps_0_count=2
-#touch_from_button_maps_0_bind_0=foo
-#touch_from_button_maps_0_bind_1=bar
-# etc.
-
-# List of Cemuhook UDP servers, delimited by ','.
-# Default: 127.0.0.1:26760
-# Example: 127.0.0.1:26760,123.4.5.67:26761
-udp_input_servers =
-
-# Enable controlling an axis via a mouse input.
-# 0 (default): Off, 1: On
-mouse_panning =
-
-# Set mouse panning horizontal sensitivity.
-# Default: 50.0
-mouse_panning_x_sensitivity =
-
-# Set mouse panning vertical sensitivity.
-# Default: 50.0
-mouse_panning_y_sensitivity =
-
-# Set mouse panning deadzone horizontal counterweight.
-# Default: 0.0
-mouse_panning_deadzone_x_counterweight =
-
-# Set mouse panning deadzone vertical counterweight.
-# Default: 0.0
-mouse_panning_deadzone_y_counterweight =
-
-# Set mouse panning stick decay strength.
-# Default: 22.0
-mouse_panning_decay_strength =
-
-# Set mouse panning stick minimum decay.
-# Default: 5.0
-mouse_panning_minimum_decay =
-
-# Emulate an analog control stick from keyboard inputs.
-# 0 (default): Disabled, 1: Enabled
-emulate_analog_keyboard =
-
-# Enable mouse inputs to the guest
-# 0 (default): Disabled, 1: Enabled
-mouse_enabled =
-
-# Enable keyboard inputs to the guest
-# 0 (default): Disabled, 1: Enabled
-keyboard_enabled =
-
-)"
- R"(
-[Core]
-# Whether to use multi-core for CPU emulation
-# 0: Disabled, 1 (default): Enabled
-use_multi_core =
-
-# Enable unsafe extended guest system memory layout (8GB DRAM)
-# 0 (default): Disabled, 1: Enabled
-use_unsafe_extended_memory_layout =
-
-[Cpu]
-# Adjusts various optimizations.
-# Auto-select mode enables choice unsafe optimizations.
-# Accurate enables only safe optimizations.
-# Unsafe allows any unsafe optimizations.
-# 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations
-cpu_accuracy =
-
-# Allow disabling safe optimizations.
-# 0 (default): Disabled, 1: Enabled
-cpu_debug_mode =
-
-# Enable inline page tables optimization (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_page_tables =
-
-# Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_block_linking =
-
-# Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_return_stack_buffer =
-
-# Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_fast_dispatcher =
-
-# Enable context elimination CPU Optimization (reduce host memory use for guest context)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_context_elimination =
-
-# Enable constant propagation CPU optimization (basic IR optimization)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_const_prop =
-
-# Enable miscellaneous CPU optimizations (basic IR optimization)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_misc_ir =
-
-# Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_reduce_misalign_checks =
-
-# Enable Host MMU Emulation (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_fastmem =
-
-# Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_fastmem_exclusives =
-
-# Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_recompile_exclusives =
-
-# Enable optimization to ignore invalid memory accesses (faster guest memory access)
-# 0: Disabled, 1 (default): Enabled
-cpuopt_ignore_memory_aborts =
-
-# Enable unfuse FMA (improve performance on CPUs without FMA)
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_unfuse_fma =
-
-# Enable faster FRSQRTE and FRECPE
-# Only enabled if cpu_accuracy is set to Unsafe.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_reduce_fp_error =
-
-# Enable faster ASIMD instructions (32 bits only)
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_ignore_standard_fpcr =
-
-# Enable inaccurate NaN handling
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_inaccurate_nan =
-
-# Disable address space checks (64 bits only)
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_fastmem_check =
-
-# Enable faster exclusive instructions
-# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
-# 0: Disabled, 1 (default): Enabled
-cpuopt_unsafe_ignore_global_monitor =
-
-)"
- R"(
-[Renderer]
-# Which backend API to use.
-# 0: OpenGL, 1 (default): Vulkan
-backend =
-
-# Whether to enable asynchronous presentation (Vulkan only)
-# 0 (default): Off, 1: On
-async_presentation =
-
-# Enable graphics API debugging mode.
-# 0 (default): Disabled, 1: Enabled
-debug =
-
-# Enable shader feedback.
-# 0 (default): Disabled, 1: Enabled
-renderer_shader_feedback =
-
-# Enable Nsight Aftermath crash dumps
-# 0 (default): Disabled, 1: Enabled
-nsight_aftermath =
-
-# Disable shader loop safety checks, executing the shader without loop logic changes
-# 0 (default): Disabled, 1: Enabled
-disable_shader_loop_safety_checks =
-
-# Which Vulkan physical device to use (defaults to 0)
-vulkan_device =
-
-# 0: 0.5x (360p/540p) [EXPERIMENTAL]
-# 1: 0.75x (540p/810p) [EXPERIMENTAL]
-# 2 (default): 1x (720p/1080p)
-# 3: 1.5x (1080p/1620p) [EXPERIMENTAL]
-# 4: 2x (1440p/2160p)
-# 5: 3x (2160p/3240p)
-# 6: 4x (2880p/4320p)
-# 7: 5x (3600p/5400p)
-# 8: 6x (4320p/6480p)
-# 9: 7x (5040p/7560p)
-# 10: 8x (5760/8640p)
-resolution_setup =
-
-# Pixel filter to use when up- or down-sampling rendered frames.
-# 0: Nearest Neighbor
-# 1 (default): Bilinear
-# 2: Bicubic
-# 3: Gaussian
-# 4: ScaleForce
-# 5: AMD FidelityFX™️ Super Resolution
-scaling_filter =
-
-# Anti-Aliasing (AA)
-# 0 (default): None, 1: FXAA, 2: SMAA
-anti_aliasing =
-
-# Whether to use fullscreen or borderless window mode
-# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen
-fullscreen_mode =
-
-# Aspect ratio
-# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Force 16:10, 4: Stretch to Window
-aspect_ratio =
-
-# Anisotropic filtering
-# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x
-max_anisotropy =
-
-# Whether to enable VSync or not.
-# OpenGL: Values other than 0 enable VSync
-# Vulkan: FIFO is selected if the requested mode is not supported by the driver.
-# FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate.
-# FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down.
-# Mailbox can have lower latency than FIFO and does not tear but may drop frames.
-# Immediate (no synchronization) just presents whatever is available and can exhibit tearing.
-# 0: Immediate (Off), 1: Mailbox, 2 (Default): FIFO (On), 3: FIFO Relaxed
-use_vsync =
-
-# Selects the OpenGL shader backend. NV_gpu_program5 is required for GLASM. If NV_gpu_program5 is
-# not available and GLASM is selected, GLSL will be used.
-# 0: GLSL, 1 (default): GLASM, 2: SPIR-V
-shader_backend =
-
-# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.
-# 0: Off, 1 (default): On
-use_reactive_flushing =
-
-# Whether to allow asynchronous shader building.
-# 0 (default): Off, 1: On
-use_asynchronous_shaders =
-
-# NVDEC emulation.
-# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding
-nvdec_emulation =
-
-# Accelerate ASTC texture decoding.
-# 0: Off, 1 (default): On
-accelerate_astc =
-
-# Decode ASTC textures asynchronously.
-# 0 (default): Off, 1: On
-async_astc =
-
-# Recompress ASTC textures to a different format.
-# 0 (default): Uncompressed, 1: BC1 (Low quality), 2: BC3: (Medium quality)
-async_astc =
-
-# Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value
-# 0: Off, 1: On (default)
-use_speed_limit =
-
-# Limits the speed of the game to run no faster than this value as a percentage of target speed
-# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
-speed_limit =
-
-# Whether to use disk based shader cache
-# 0: Off, 1 (default): On
-use_disk_shader_cache =
-
-# Which gpu accuracy level to use
-# 0: Normal, 1 (default): High, 2: Extreme (Very slow)
-gpu_accuracy =
-
-# Whether to use asynchronous GPU emulation
-# 0 : Off (slow), 1 (default): On (fast)
-use_asynchronous_gpu_emulation =
-
-# Inform the guest that GPU operations completed more quickly than they did.
-# 0: Off, 1 (default): On
-use_fast_gpu_time =
-
-# Whether to use garbage collection or not for GPU caches.
-# 0 (default): Off, 1: On
-use_caches_gc =
-
-# The clear color for the renderer. What shows up on the sides of the bottom screen.
-# Must be in range of 0-255. Defaults to 0 for all.
-bg_red =
-bg_blue =
-bg_green =
-
-)"
- R"(
-[Audio]
-# Which audio output engine to use.
-# auto (default): Auto-select
-# cubeb: Cubeb audio engine (if available)
-# sdl2: SDL2 audio engine (if available)
-# null: No audio output
-output_engine =
-
-# Which audio device to use.
-# auto (default): Auto-select
-output_device =
-
-# Output volume.
-# 100 (default): 100%, 0; mute
-volume =
-
-[Data Storage]
-# Whether to create a virtual SD card.
-# 1 (default): Yes, 0: No
-use_virtual_sd =
-
-# Whether or not to enable gamecard emulation
-# 1: Yes, 0 (default): No
-gamecard_inserted =
-
-# Whether or not the gamecard should be emulated as the current game
-# If 'gamecard_inserted' is 0 this setting is irrelevant
-# 1: Yes, 0 (default): No
-gamecard_current_game =
-
-# Path to an XCI file to use as the gamecard
-# If 'gamecard_inserted' is 0 this setting is irrelevant
-# If 'gamecard_current_game' is 1 this setting is irrelevant
-gamecard_path =
-
-[System]
-# Whether the system is docked
-# 1 (default): Yes, 0: No
-use_docked_mode =
-
-# Sets the seed for the RNG generator built into the switch
-# rng_seed will be ignored and randomly generated if rng_seed_enabled is false
-rng_seed_enabled =
-rng_seed =
-
-# Sets the current time (in seconds since 12:00 AM Jan 1, 1970) that will be used by the time service
-# This will auto-increment, with the time set being the time the game is started
-# This override will only occur if custom_rtc_enabled is true, otherwise the current time is used
-custom_rtc_enabled =
-custom_rtc =
-
-# Sets the systems language index
-# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese,
-# 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French,
-# 14: Latin American Spanish, 15: Simplified Chinese, 16: Traditional Chinese, 17: Brazilian Portuguese
-language_index =
-
-# The system region that yuzu will use during emulation
-# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan
-region_index =
-
-# The system time zone that yuzu will use during emulation
-# 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone
-time_zone_index =
-
-# Sets the sound output mode.
-# 0: Mono, 1 (default): Stereo, 2: Surround
-sound_index =
-
-[Miscellaneous]
-# A filter which removes logs below a certain logging level.
-# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
-log_filter = *:Trace
-
-# Use developer keys
-# 0 (default): Disabled, 1: Enabled
-use_dev_keys =
-
-[Debugging]
-# Record frame time data, can be found in the log directory. Boolean value
-record_frame_times =
-# Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them
-dump_exefs=false
-# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
-dump_nso=false
-# Determines whether or not yuzu will save the filesystem access log.
-enable_fs_access_log=false
-# Enables verbose reporting services
-reporting_services =
-# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode
-# false: Retail/Normal Mode (default), true: Kiosk Mode
-quest_flag =
-# Determines whether debug asserts should be enabled, which will throw an exception on asserts.
-# false: Disabled (default), true: Enabled
-use_debug_asserts =
-# Determines whether unimplemented HLE service calls should be automatically stubbed.
-# false: Disabled (default), true: Enabled
-use_auto_stub =
-# Enables/Disables the macro JIT compiler
-disable_macro_jit=false
-# Determines whether to enable the GDB stub and wait for the debugger to attach before running.
-# false: Disabled (default), true: Enabled
-use_gdbstub=false
-# The port to use for the GDB server, if it is enabled.
-gdbstub_port=6543
-
-[WebService]
-# Whether or not to enable telemetry
-# 0: No, 1 (default): Yes
-enable_telemetry =
-# URL for Web API
-web_api_url = https://api.yuzu-emu.org
-# Username and token for yuzu Web Service
-# See https://profile.yuzu-emu.org/ for more info
-yuzu_username =
-yuzu_token =
-
-[Network]
-# Name of the network interface device to use with yuzu LAN play.
-# e.g. On *nix: 'enp7s0', 'wlp6s0u1u3u3', 'lo'
-# e.g. On Windows: 'Ethernet', 'Wi-Fi'
-network_interface =
-
-[AddOns]
-# Used to disable add-ons
-# List of title IDs of games that will have add-ons disabled (separated by '|'):
-title_ids =
-# 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 '|')
-# e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey
-)";
-} // 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 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+// SDL will break our main function in yuzu-cmd if we don't define this before adding SDL.h
+#define SDL_MAIN_HANDLED
+#include <SDL.h>
+
+#include "input_common/main.h"
+#include "sdl_config.h"
+
+const std::array<int, Settings::NativeButton::NumButtons> SdlConfig::default_buttons = {
+ SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T,
+ SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W,
+ SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
+};
+
+const std::array<int, Settings::NativeMotion::NumMotions> SdlConfig::default_motions = {
+ SDL_SCANCODE_7,
+ SDL_SCANCODE_8,
+};
+
+const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> SdlConfig::default_analogs{
+ {
+ {
+ SDL_SCANCODE_UP,
+ SDL_SCANCODE_DOWN,
+ SDL_SCANCODE_LEFT,
+ SDL_SCANCODE_RIGHT,
+ },
+ {
+ SDL_SCANCODE_I,
+ SDL_SCANCODE_K,
+ SDL_SCANCODE_J,
+ SDL_SCANCODE_L,
+ },
+ }};
+
+const std::array<int, 2> SdlConfig::default_stick_mod = {
+ SDL_SCANCODE_D,
+ 0,
+};
+
+const std::array<int, 2> SdlConfig::default_ringcon_analogs{{
+ 0,
+ 0,
+}};
+
+SdlConfig::SdlConfig(const std::optional<std::string> config_path) {
+ Initialize(config_path);
+ ReadSdlValues();
+ SaveSdlValues();
+}
+
+SdlConfig::~SdlConfig() {
+ if (global) {
+ SdlConfig::SaveAllValues();
+ }
+}
+
+void SdlConfig::ReloadAllValues() {
+ Reload();
+ ReadSdlValues();
+ SaveSdlValues();
+}
+
+void SdlConfig::SaveAllValues() {
+ Save();
+ SaveSdlValues();
+}
+
+void SdlConfig::ReadSdlValues() {
+ ReadSdlControlValues();
+}
+
+void SdlConfig::ReadSdlControlValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
+
+ Settings::values.players.SetGlobal(!IsCustomConfig());
+ for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
+ ReadSdlPlayerValues(p);
+ }
+ if (IsCustomConfig()) {
+ EndGroup();
+ return;
+ }
+ ReadDebugControlValues();
+ ReadHidbusValues();
+
+ EndGroup();
+}
+
+void SdlConfig::ReadSdlPlayerValues(const std::size_t player_index) {
+ std::string player_prefix;
+ if (type != ConfigType::InputProfile) {
+ player_prefix.append("player_").append(ToString(player_index)).append("_");
+ }
+
+ auto& player = Settings::values.players.GetValue()[player_index];
+ if (IsCustomConfig()) {
+ const auto profile_name =
+ ReadStringSetting(std::string(player_prefix).append("profile_name"));
+ if (profile_name.empty()) {
+ // Use the global input config
+ player = Settings::values.players.GetValue(true)[player_index];
+ return;
+ }
+ }
+
+ for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ auto& player_buttons = player.buttons[i];
+
+ player_buttons = ReadStringSetting(
+ std::string(player_prefix).append(Settings::NativeButton::mapping[i]), default_param);
+ if (player_buttons.empty()) {
+ player_buttons = default_param;
+ }
+ }
+
+ for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
+ default_analogs[i][3], default_stick_mod[i], 0.5f);
+ auto& player_analogs = player.analogs[i];
+
+ player_analogs = ReadStringSetting(
+ std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), default_param);
+ if (player_analogs.empty()) {
+ player_analogs = default_param;
+ }
+ }
+
+ for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
+ auto& player_motions = player.motions[i];
+
+ player_motions = ReadStringSetting(
+ std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), default_param);
+ if (player_motions.empty()) {
+ player_motions = default_param;
+ }
+ }
+}
+
+void SdlConfig::ReadDebugControlValues() {
+ for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i];
+ debug_pad_buttons = ReadStringSetting(
+ std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), default_param);
+ if (debug_pad_buttons.empty()) {
+ debug_pad_buttons = default_param;
+ }
+ }
+ for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
+ default_analogs[i][3], default_stick_mod[i], 0.5f);
+ auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i];
+ debug_pad_analogs = ReadStringSetting(
+ std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), default_param);
+ if (debug_pad_analogs.empty()) {
+ debug_pad_analogs = default_param;
+ }
+ }
+}
+
+void SdlConfig::ReadHidbusValues() {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
+ auto& ringcon_analogs = Settings::values.ringcon_analogs;
+
+ ringcon_analogs = ReadStringSetting(std::string("ring_controller"), default_param);
+ if (ringcon_analogs.empty()) {
+ ringcon_analogs = default_param;
+ }
+}
+
+void SdlConfig::SaveSdlValues() {
+ SaveSdlControlValues();
+
+ WriteToIni();
+}
+
+void SdlConfig::SaveSdlControlValues() {
+ BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
+
+ Settings::values.players.SetGlobal(!IsCustomConfig());
+ for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
+ SaveSdlPlayerValues(p);
+ }
+ if (IsCustomConfig()) {
+ EndGroup();
+ return;
+ }
+ SaveDebugControlValues();
+ SaveHidbusValues();
+
+ EndGroup();
+}
+
+void SdlConfig::SaveSdlPlayerValues(const std::size_t player_index) {
+ std::string player_prefix;
+ if (type != ConfigType::InputProfile) {
+ player_prefix = std::string("player_").append(ToString(player_index)).append("_");
+ }
+
+ const auto& player = Settings::values.players.GetValue()[player_index];
+ if (IsCustomConfig() && player.profile_name.empty()) {
+ // No custom profile selected
+ return;
+ }
+
+ for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ WriteSetting(std::string(player_prefix).append(Settings::NativeButton::mapping[i]),
+ player.buttons[i], std::make_optional(default_param));
+ }
+ for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
+ default_analogs[i][3], default_stick_mod[i], 0.5f);
+ WriteSetting(std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]),
+ player.analogs[i], std::make_optional(default_param));
+ }
+ for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
+ WriteSetting(std::string(player_prefix).append(Settings::NativeMotion::mapping[i]),
+ player.motions[i], std::make_optional(default_param));
+ }
+}
+
+void SdlConfig::SaveDebugControlValues() {
+ for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
+ const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
+ WriteSetting(std::string("debug_pad_").append(Settings::NativeButton::mapping[i]),
+ Settings::values.debug_pad_buttons[i], std::make_optional(default_param));
+ }
+ for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
+ default_analogs[i][3], default_stick_mod[i], 0.5f);
+ WriteSetting(std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]),
+ Settings::values.debug_pad_analogs[i], std::make_optional(default_param));
+ }
+}
+
+void SdlConfig::SaveHidbusValues() {
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
+ WriteSetting(std::string("ring_controller"), Settings::values.ringcon_analogs,
+ std::make_optional(default_param));
+}
+
+std::vector<Settings::BasicSetting*>& SdlConfig::FindRelevantList(Settings::Category category) {
+ return Settings::values.linkage.by_category[category];
+}
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 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "frontend_common/config.h"
+
+class SdlConfig final : public Config {
+public:
+ explicit SdlConfig(std::optional<std::string> config_path);
+ ~SdlConfig() override;
+
+ void ReloadAllValues() override;
+ void SaveAllValues() override;
+
+protected:
+ void ReadSdlValues();
+ void ReadSdlPlayerValues(std::size_t player_index);
+ void ReadSdlControlValues();
+ void ReadHidbusValues() override;
+ void ReadDebugControlValues() override;
+ void ReadPathValues() override {}
+ void ReadShortcutValues() override {}
+ void ReadUIValues() override {}
+ void ReadUIGamelistValues() override {}
+ void ReadUILayoutValues() override {}
+ void ReadMultiplayerValues() override {}
+
+ void SaveSdlValues();
+ void SaveSdlPlayerValues(std::size_t player_index);
+ void SaveSdlControlValues();
+ void SaveHidbusValues() override;
+ void SaveDebugControlValues() override;
+ void SavePathValues() override {}
+ void SaveShortcutValues() override {}
+ void SaveUIValues() override {}
+ void SaveUIGamelistValues() override {}
+ void SaveUILayoutValues() override {}
+ void SaveMultiplayerValues() override {}
+
+ std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override;
+
+public:
+ static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
+ static const std::array<int, Settings::NativeMotion::NumMotions> default_motions;
+ static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
+ static const std::array<int, 2> default_stick_mod;
+ static const std::array<int, 2> default_ringcon_analogs;
+};
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 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
#include "core/telemetry_session.h"
+#include "frontend_common/config.h"
#include "input_common/main.h"
#include "network/network.h"
+#include "sdl_config.h"
#include "video_core/renderer_base.h"
-#include "yuzu_cmd/config.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2_null.h"
@@ -300,7 +301,7 @@ int main(int argc, char** argv) {
}
}
- Config config{config_path};
+ SdlConfig config{config_path};
// apply the log_filter setting
// the logger was initialized before and doesn't pick up the filter on its own