summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt6
-rw-r--r--externals/CMakeLists.txt5
m---------externals/Vulkan-Utility-Libraries0
-rw-r--r--externals/nx_tzdb/CMakeLists.txt2
-rw-r--r--externals/nx_tzdb/NxTzdbCreateHeader.cmake4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt8
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt8
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt54
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt5
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt33
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt7
-rw-r--r--src/android/app/src/main/jni/CMakeLists.txt2
-rw-r--r--src/android/app/src/main/jni/id_cache.cpp7
-rw-r--r--src/android/app/src/main/jni/id_cache.h1
-rw-r--r--src/android/app/src/main/jni/native.cpp68
-rw-r--r--src/android/app/src/main/jni/native.h7
-rw-r--r--src/android/app/src/main/res/layout/fragment_emulation.xml4
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp7
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/audio_renderer.h7
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/command_buffer.h5
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp7
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/command_list_processor.h7
-rw-r--r--src/audio_core/renderer/audio_renderer.cpp6
-rw-r--r--src/audio_core/renderer/audio_renderer.h6
-rw-r--r--src/audio_core/renderer/system.cpp10
-rw-r--r--src/audio_core/renderer/system.h6
-rw-r--r--src/common/atomic_ops.h79
-rw-r--r--src/core/hle/kernel/k_thread.cpp3
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.cpp2
-rw-r--r--src/core/hle/service/audio/audctl.cpp84
-rw-r--r--src/core/hle/service/audio/audctl.h20
-rw-r--r--src/core/hle/service/audio/audren_u.cpp16
-rw-r--r--src/core/hle/service/mii/mii.cpp563
-rw-r--r--src/core/hle/service/mii/mii.h15
-rw-r--r--src/core/hle/service/set/setting_formats/system_settings.cpp14
-rw-r--r--src/core/hle/service/set/setting_formats/system_settings.h12
-rw-r--r--src/core/hle/service/set/settings_types.h15
-rw-r--r--src/core/hle/service/set/system_settings_server.cpp249
-rw-r--r--src/core/hle/service/set/system_settings_server.h20
-rw-r--r--src/core/memory.cpp6
-rw-r--r--src/frontend_common/config.cpp26
-rw-r--r--src/frontend_common/config.h6
-rw-r--r--src/hid_core/resource_manager.cpp2
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp2
-rw-r--r--src/hid_core/resources/hid_firmware_settings.cpp3
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp5
-rw-r--r--src/video_core/vulkan_common/vk_enum_string_helper.h8
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp107
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h3
-rw-r--r--src/yuzu/CMakeLists.txt3
-rw-r--r--src/yuzu/configuration/configure_audio.h2
-rw-r--r--src/yuzu/configuration/configure_cpu.h2
-rw-r--r--src/yuzu/configuration/configure_general.h2
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp5
-rw-r--r--src/yuzu/configuration/configure_graphics.h2
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.h2
-rw-r--r--src/yuzu/configuration/configure_linux_tab.cpp75
-rw-r--r--src/yuzu/configuration/configure_linux_tab.h44
-rw-r--r--src/yuzu/configuration/configure_linux_tab.ui53
-rw-r--r--src/yuzu/configuration/configure_motion_touch.h1
-rw-r--r--src/yuzu/configuration/configure_mouse_panning.h1
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp6
-rw-r--r--src/yuzu/configuration/configure_per_game.h2
-rw-r--r--src/yuzu/configuration/configure_system.h2
66 files changed, 1052 insertions, 697 deletions
diff --git a/.gitmodules b/.gitmodules
index e65997afc..52256d86f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -64,3 +64,6 @@
64[submodule "oaknut"] 64[submodule "oaknut"]
65 path = externals/oaknut 65 path = externals/oaknut
66 url = https://github.com/merryhime/oaknut 66 url = https://github.com/merryhime/oaknut
67[submodule "Vulkan-Utility-Libraries"]
68 path = externals/Vulkan-Utility-Libraries
69 url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7cd6b2108..eb26fbfd8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,6 +36,8 @@ option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
36 36
37option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON) 37option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
38 38
39option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
40
39option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) 41option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
40 42
41option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) 43option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
@@ -308,6 +310,10 @@ if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
308 find_package(Vulkan 1.3.274 REQUIRED) 310 find_package(Vulkan 1.3.274 REQUIRED)
309endif() 311endif()
310 312
313if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
314 find_package(VulkanUtilityLibraries REQUIRED)
315endif()
316
311if (ENABLE_LIBUSB) 317if (ENABLE_LIBUSB)
312 find_package(libusb 1.0.24 MODULE) 318 find_package(libusb 1.0.24 MODULE)
313endif() 319endif()
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index 15b444338..42355716c 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -154,6 +154,11 @@ if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
154 add_subdirectory(Vulkan-Headers) 154 add_subdirectory(Vulkan-Headers)
155endif() 155endif()
156 156
157# Vulkan-Utility-Libraries
158if (YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
159 add_subdirectory(Vulkan-Utility-Libraries)
160endif()
161
157# TZDB (Time Zone Database) 162# TZDB (Time Zone Database)
158add_subdirectory(nx_tzdb) 163add_subdirectory(nx_tzdb)
159 164
diff --git a/externals/Vulkan-Utility-Libraries b/externals/Vulkan-Utility-Libraries
new file mode 160000
Subproject 524f8910d0e4a5f2ec5961996b23e5b74b95cb1
diff --git a/externals/nx_tzdb/CMakeLists.txt b/externals/nx_tzdb/CMakeLists.txt
index 0fad24642..13723f175 100644
--- a/externals/nx_tzdb/CMakeLists.txt
+++ b/externals/nx_tzdb/CMakeLists.txt
@@ -32,7 +32,7 @@ set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip")
32 32
33set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb") 33set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb")
34 34
35if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ARCHIVE}) 35if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR})
36 set(NX_TZDB_DOWNLOAD_URL "https://github.com/lat9nq/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip") 36 set(NX_TZDB_DOWNLOAD_URL "https://github.com/lat9nq/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
37 37
38 message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...") 38 message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...")
diff --git a/externals/nx_tzdb/NxTzdbCreateHeader.cmake b/externals/nx_tzdb/NxTzdbCreateHeader.cmake
index 8c29e1167..95606d862 100644
--- a/externals/nx_tzdb/NxTzdbCreateHeader.cmake
+++ b/externals/nx_tzdb/NxTzdbCreateHeader.cmake
@@ -11,6 +11,10 @@ execute_process(
11 WORKING_DIRECTORY ${ZONE_PATH} 11 WORKING_DIRECTORY ${ZONE_PATH}
12 OUTPUT_VARIABLE FILE_LIST) 12 OUTPUT_VARIABLE FILE_LIST)
13 13
14if (NOT FILE_LIST)
15 message(FATAL_ERROR "No timezone files found in directory ${ZONE_PATH}, did the download fail?")
16endif()
17
14set(DIRECTORY_NAME ${HEADER_NAME}) 18set(DIRECTORY_NAME ${HEADER_NAME})
15 19
16set(FILE_DATA "") 20set(FILE_DATA "")
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 55abba093..53137b2e2 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
@@ -261,7 +261,7 @@ object NativeLibrary {
261 /** 261 /**
262 * Begins emulation. 262 * Begins emulation.
263 */ 263 */
264 external fun run(path: String?) 264 external fun run(path: String?, programIndex: Int = 0)
265 265
266 // Surface Handling 266 // Surface Handling
267 external fun surfaceChanged(surf: Surface?) 267 external fun surfaceChanged(surf: Surface?)
@@ -489,6 +489,12 @@ object NativeLibrary {
489 sEmulationActivity.get()!!.onEmulationStopped(status) 489 sEmulationActivity.get()!!.onEmulationStopped(status)
490 } 490 }
491 491
492 @Keep
493 @JvmStatic
494 fun onProgramChanged(programIndex: Int) {
495 sEmulationActivity.get()!!.onProgramChanged(programIndex)
496 }
497
492 /** 498 /**
493 * Logs the Yuzu version, Android version and, CPU. 499 * Logs the Yuzu version, Android version and, CPU.
494 */ 500 */
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
index 26cddecf4..564aaf305 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
@@ -76,7 +76,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
76 76
77 override fun onDestroy() { 77 override fun onDestroy() {
78 stopForegroundService(this) 78 stopForegroundService(this)
79 emulationViewModel.clear()
80 super.onDestroy() 79 super.onDestroy()
81 } 80 }
82 81
@@ -446,9 +445,14 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
446 } 445 }
447 446
448 fun onEmulationStopped(status: Int) { 447 fun onEmulationStopped(status: Int) {
449 if (status == 0) { 448 if (status == 0 && emulationViewModel.programChanged.value == -1) {
450 finish() 449 finish()
451 } 450 }
451 emulationViewModel.setEmulationStopped(true)
452 }
453
454 fun onProgramChanged(programIndex: Int) {
455 emulationViewModel.setProgramChanged(programIndex)
452 } 456 }
453 457
454 private fun startMotionSensorListener() { 458 private fun startMotionSensorListener() {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 22da1d0e5..1f591ced1 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -301,6 +301,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
301 301
302 R.id.menu_exit -> { 302 R.id.menu_exit -> {
303 emulationState.stop() 303 emulationState.stop()
304 NativeConfig.reloadGlobalConfig()
304 emulationViewModel.setIsEmulationStopping(true) 305 emulationViewModel.setIsEmulationStopping(true)
305 binding.drawerLayout.close() 306 binding.drawerLayout.close()
306 binding.inGameMenu.requestFocus() 307 binding.inGameMenu.requestFocus()
@@ -423,10 +424,38 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
423 } 424 }
424 } 425 }
425 } 426 }
427 launch {
428 repeatOnLifecycle(Lifecycle.State.CREATED) {
429 emulationViewModel.programChanged.collect {
430 if (it != 0) {
431 emulationViewModel.setEmulationStarted(false)
432 binding.drawerLayout.close()
433 binding.drawerLayout
434 .setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
435 ViewUtils.hideView(binding.surfaceInputOverlay)
436 ViewUtils.showView(binding.loadingIndicator)
437 }
438 }
439 }
440 }
441 launch {
442 repeatOnLifecycle(Lifecycle.State.CREATED) {
443 emulationViewModel.emulationStopped.collect {
444 if (it && emulationViewModel.programChanged.value != -1) {
445 if (perfStatsUpdater != null) {
446 perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!)
447 }
448 emulationState.changeProgram(emulationViewModel.programChanged.value)
449 emulationViewModel.setProgramChanged(-1)
450 emulationViewModel.setEmulationStopped(false)
451 }
452 }
453 }
454 }
426 } 455 }
427 } 456 }
428 457
429 private fun startEmulation() { 458 private fun startEmulation(programIndex: Int = 0) {
430 if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) { 459 if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
431 if (!DirectoryInitialization.areDirectoriesReady) { 460 if (!DirectoryInitialization.areDirectoriesReady) {
432 DirectoryInitialization.start() 461 DirectoryInitialization.start()
@@ -434,7 +463,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
434 463
435 updateScreenLayout() 464 updateScreenLayout()
436 465
437 emulationState.run(emulationActivity!!.isActivityRecreated) 466 emulationState.run(emulationActivity!!.isActivityRecreated, programIndex)
438 } 467 }
439 } 468 }
440 469
@@ -832,6 +861,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
832 ) { 861 ) {
833 private var state: State 862 private var state: State
834 private var surface: Surface? = null 863 private var surface: Surface? = null
864 lateinit var emulationThread: Thread
835 865
836 init { 866 init {
837 // Starting state is stopped. 867 // Starting state is stopped.
@@ -877,7 +907,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
877 } 907 }
878 908
879 @Synchronized 909 @Synchronized
880 fun run(isActivityRecreated: Boolean) { 910 fun run(isActivityRecreated: Boolean, programIndex: Int = 0) {
881 if (isActivityRecreated) { 911 if (isActivityRecreated) {
882 if (NativeLibrary.isRunning()) { 912 if (NativeLibrary.isRunning()) {
883 state = State.PAUSED 913 state = State.PAUSED
@@ -888,10 +918,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
888 918
889 // If the surface is set, run now. Otherwise, wait for it to get set. 919 // If the surface is set, run now. Otherwise, wait for it to get set.
890 if (surface != null) { 920 if (surface != null) {
891 runWithValidSurface() 921 runWithValidSurface(programIndex)
892 } 922 }
893 } 923 }
894 924
925 @Synchronized
926 fun changeProgram(programIndex: Int) {
927 emulationThread.join()
928 emulationThread = Thread({
929 Log.debug("[EmulationFragment] Starting emulation thread.")
930 NativeLibrary.run(gamePath, programIndex)
931 }, "NativeEmulation")
932 emulationThread.start()
933 }
934
895 // Surface callbacks 935 // Surface callbacks
896 @Synchronized 936 @Synchronized
897 fun newSurface(surface: Surface?) { 937 fun newSurface(surface: Surface?) {
@@ -931,7 +971,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
931 } 971 }
932 } 972 }
933 973
934 private fun runWithValidSurface() { 974 private fun runWithValidSurface(programIndex: Int = 0) {
935 NativeLibrary.surfaceChanged(surface) 975 NativeLibrary.surfaceChanged(surface)
936 if (!emulationCanStart.invoke()) { 976 if (!emulationCanStart.invoke()) {
937 return 977 return
@@ -939,9 +979,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
939 979
940 when (state) { 980 when (state) {
941 State.STOPPED -> { 981 State.STOPPED -> {
942 val emulationThread = Thread({ 982 emulationThread = Thread({
943 Log.debug("[EmulationFragment] Starting emulation thread.") 983 Log.debug("[EmulationFragment] Starting emulation thread.")
944 NativeLibrary.run(gamePath) 984 NativeLibrary.run(gamePath, programIndex)
945 }, "NativeEmulation") 985 }, "NativeEmulation")
946 emulationThread.start() 986 emulationThread.start()
947 } 987 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt
index 5ed754c96..a49c887a1 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt
@@ -66,10 +66,13 @@ class DriverViewModel : ViewModel() {
66 66
67 fun updateDriverList() { 67 fun updateDriverList() {
68 val selectedDriver = GpuDriverHelper.customDriverSettingData 68 val selectedDriver = GpuDriverHelper.customDriverSettingData
69 val systemDriverData = GpuDriverHelper.getSystemDriverInfo()
69 val newDriverList = mutableListOf( 70 val newDriverList = mutableListOf(
70 Driver( 71 Driver(
71 selectedDriver == GpuDriverMetadata(), 72 selectedDriver == GpuDriverMetadata(),
72 YuzuApplication.appContext.getString(R.string.system_gpu_driver) 73 YuzuApplication.appContext.getString(R.string.system_gpu_driver),
74 systemDriverData?.get(0) ?: "",
75 systemDriverData?.get(1) ?: ""
73 ) 76 )
74 ) 77 )
75 driverData.forEach { 78 driverData.forEach {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt
index b66f47fe7..d024493cd 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt
@@ -15,6 +15,12 @@ class EmulationViewModel : ViewModel() {
15 val isEmulationStopping: StateFlow<Boolean> get() = _isEmulationStopping 15 val isEmulationStopping: StateFlow<Boolean> get() = _isEmulationStopping
16 private val _isEmulationStopping = MutableStateFlow(false) 16 private val _isEmulationStopping = MutableStateFlow(false)
17 17
18 private val _emulationStopped = MutableStateFlow(false)
19 val emulationStopped = _emulationStopped.asStateFlow()
20
21 private val _programChanged = MutableStateFlow(-1)
22 val programChanged = _programChanged.asStateFlow()
23
18 val shaderProgress: StateFlow<Int> get() = _shaderProgress 24 val shaderProgress: StateFlow<Int> get() = _shaderProgress
19 private val _shaderProgress = MutableStateFlow(0) 25 private val _shaderProgress = MutableStateFlow(0)
20 26
@@ -35,6 +41,17 @@ class EmulationViewModel : ViewModel() {
35 _isEmulationStopping.value = value 41 _isEmulationStopping.value = value
36 } 42 }
37 43
44 fun setEmulationStopped(value: Boolean) {
45 if (value) {
46 _emulationStarted.value = false
47 }
48 _emulationStopped.value = value
49 }
50
51 fun setProgramChanged(programIndex: Int) {
52 _programChanged.value = programIndex
53 }
54
38 fun setShaderProgress(progress: Int) { 55 fun setShaderProgress(progress: Int) {
39 _shaderProgress.value = progress 56 _shaderProgress.value = progress
40 } 57 }
@@ -56,20 +73,4 @@ class EmulationViewModel : ViewModel() {
56 fun setDrawerOpen(value: Boolean) { 73 fun setDrawerOpen(value: Boolean) {
57 _drawerOpen.value = value 74 _drawerOpen.value = value
58 } 75 }
59
60 fun clear() {
61 setEmulationStarted(false)
62 setIsEmulationStopping(false)
63 setShaderProgress(0)
64 setTotalShaders(0)
65 setShaderMessage("")
66 }
67
68 companion object {
69 const val KEY_EMULATION_STARTED = "EmulationStarted"
70 const val KEY_IS_EMULATION_STOPPING = "IsEmulationStarting"
71 const val KEY_SHADER_PROGRESS = "ShaderProgress"
72 const val KEY_TOTAL_SHADERS = "TotalShaders"
73 const val KEY_SHADER_MESSAGE = "ShaderMessage"
74 }
75} 76}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt
index 81212cbee..a72dea8f1 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt
@@ -3,8 +3,10 @@
3 3
4package org.yuzu.yuzu_emu.utils 4package org.yuzu.yuzu_emu.utils
5 5
6import android.graphics.SurfaceTexture
6import android.net.Uri 7import android.net.Uri
7import android.os.Build 8import android.os.Build
9import android.view.Surface
8import java.io.File 10import java.io.File
9import java.io.IOException 11import java.io.IOException
10import org.yuzu.yuzu_emu.NativeLibrary 12import org.yuzu.yuzu_emu.NativeLibrary
@@ -195,6 +197,11 @@ object GpuDriverHelper {
195 197
196 external fun supportsCustomDriverLoading(): Boolean 198 external fun supportsCustomDriverLoading(): Boolean
197 199
200 external fun getSystemDriverInfo(
201 surface: Surface = Surface(SurfaceTexture(true)),
202 hookLibPath: String = GpuDriverHelper.hookLibPath!!
203 ): Array<String>?
204
198 // Parse the custom driver metadata to retrieve the name. 205 // Parse the custom driver metadata to retrieve the name.
199 val installedCustomDriverData: GpuDriverMetadata 206 val installedCustomDriverData: GpuDriverMetadata
200 get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME)) 207 get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME))
diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt
index 2acc93da8..abc6055ab 100644
--- a/src/android/app/src/main/jni/CMakeLists.txt
+++ b/src/android/app/src/main/jni/CMakeLists.txt
@@ -22,7 +22,7 @@ add_library(yuzu-android SHARED
22 22
23set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) 23set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
24 24
25target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common) 25target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers)
26target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log) 26target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
27if (ARCHITECTURE_arm64) 27if (ARCHITECTURE_arm64)
28 target_link_libraries(yuzu-android PRIVATE adrenotools) 28 target_link_libraries(yuzu-android PRIVATE adrenotools)
diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp
index 96f2ad3d4..f30100bd8 100644
--- a/src/android/app/src/main/jni/id_cache.cpp
+++ b/src/android/app/src/main/jni/id_cache.cpp
@@ -19,6 +19,7 @@ static jmethodID s_exit_emulation_activity;
19static jmethodID s_disk_cache_load_progress; 19static jmethodID s_disk_cache_load_progress;
20static jmethodID s_on_emulation_started; 20static jmethodID s_on_emulation_started;
21static jmethodID s_on_emulation_stopped; 21static jmethodID s_on_emulation_stopped;
22static jmethodID s_on_program_changed;
22 23
23static jclass s_game_class; 24static jclass s_game_class;
24static jmethodID s_game_constructor; 25static jmethodID s_game_constructor;
@@ -123,6 +124,10 @@ jmethodID GetOnEmulationStopped() {
123 return s_on_emulation_stopped; 124 return s_on_emulation_stopped;
124} 125}
125 126
127jmethodID GetOnProgramChanged() {
128 return s_on_program_changed;
129}
130
126jclass GetGameClass() { 131jclass GetGameClass() {
127 return s_game_class; 132 return s_game_class;
128} 133}
@@ -306,6 +311,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
306 env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V"); 311 env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V");
307 s_on_emulation_stopped = 312 s_on_emulation_stopped =
308 env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V"); 313 env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V");
314 s_on_program_changed =
315 env->GetStaticMethodID(s_native_library_class, "onProgramChanged", "(I)V");
309 316
310 const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game"); 317 const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game");
311 s_game_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_class)); 318 s_game_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_class));
diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h
index a002e705d..00e48afc0 100644
--- a/src/android/app/src/main/jni/id_cache.h
+++ b/src/android/app/src/main/jni/id_cache.h
@@ -19,6 +19,7 @@ jmethodID GetExitEmulationActivity();
19jmethodID GetDiskCacheLoadProgress(); 19jmethodID GetDiskCacheLoadProgress();
20jmethodID GetOnEmulationStarted(); 20jmethodID GetOnEmulationStarted();
21jmethodID GetOnEmulationStopped(); 21jmethodID GetOnEmulationStopped();
22jmethodID GetOnProgramChanged();
22 23
23jclass GetGameClass(); 24jclass GetGameClass();
24jmethodID GetGameConstructor(); 25jmethodID GetGameConstructor();
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 3fd9a500c..64627db88 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -60,6 +60,9 @@
60#include "jni/id_cache.h" 60#include "jni/id_cache.h"
61#include "jni/native.h" 61#include "jni/native.h"
62#include "video_core/renderer_base.h" 62#include "video_core/renderer_base.h"
63#include "video_core/renderer_vulkan/renderer_vulkan.h"
64#include "video_core/vulkan_common/vulkan_instance.h"
65#include "video_core/vulkan_common/vulkan_surface.h"
63 66
64#define jconst [[maybe_unused]] const auto 67#define jconst [[maybe_unused]] const auto
65#define jauto [[maybe_unused]] auto 68#define jauto [[maybe_unused]] auto
@@ -208,7 +211,8 @@ void EmulationSession::InitializeSystem(bool reload) {
208 m_system.GetFileSystemController().CreateFactories(*m_vfs); 211 m_system.GetFileSystemController().CreateFactories(*m_vfs);
209} 212}
210 213
211Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) { 214Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
215 const std::size_t program_index) {
212 std::scoped_lock lock(m_mutex); 216 std::scoped_lock lock(m_mutex);
213 217
214 // Create the render window. 218 // Create the render window.
@@ -238,7 +242,8 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
238 ConfigureFilesystemProvider(filepath); 242 ConfigureFilesystemProvider(filepath);
239 243
240 // Load the ROM. 244 // Load the ROM.
241 m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath); 245 m_load_result =
246 m_system.Load(EmulationSession::GetInstance().Window(), filepath, 0, program_index);
242 if (m_load_result != Core::SystemResultStatus::Success) { 247 if (m_load_result != Core::SystemResultStatus::Success) {
243 return m_load_result; 248 return m_load_result;
244 } 249 }
@@ -248,6 +253,12 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
248 m_system.GetCpuManager().OnGpuReady(); 253 m_system.GetCpuManager().OnGpuReady();
249 m_system.RegisterExitCallback([&] { HaltEmulation(); }); 254 m_system.RegisterExitCallback([&] { HaltEmulation(); });
250 255
256 // Register an ExecuteProgram callback such that Core can execute a sub-program
257 m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) {
258 m_next_program_index = program_index_;
259 EmulationSession::GetInstance().HaltEmulation();
260 });
261
251 OnEmulationStarted(); 262 OnEmulationStarted();
252 return Core::SystemResultStatus::Success; 263 return Core::SystemResultStatus::Success;
253} 264}
@@ -255,6 +266,11 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
255void EmulationSession::ShutdownEmulation() { 266void EmulationSession::ShutdownEmulation() {
256 std::scoped_lock lock(m_mutex); 267 std::scoped_lock lock(m_mutex);
257 268
269 if (m_next_program_index != -1) {
270 ChangeProgram(m_next_program_index);
271 m_next_program_index = -1;
272 }
273
258 m_is_running = false; 274 m_is_running = false;
259 275
260 // Unload user input. 276 // Unload user input.
@@ -402,6 +418,12 @@ void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) {
402 static_cast<jint>(result)); 418 static_cast<jint>(result));
403} 419}
404 420
421void EmulationSession::ChangeProgram(std::size_t program_index) {
422 JNIEnv* env = IDCache::GetEnvForThread();
423 env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnProgramChanged(),
424 static_cast<jint>(program_index));
425}
426
405u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) { 427u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
406 auto program_id_string = GetJString(env, jprogramId); 428 auto program_id_string = GetJString(env, jprogramId);
407 try { 429 try {
@@ -411,7 +433,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
411 } 433 }
412} 434}
413 435
414static Core::SystemResultStatus RunEmulation(const std::string& filepath) { 436static Core::SystemResultStatus RunEmulation(const std::string& filepath,
437 const size_t program_index = 0) {
415 MicroProfileOnThreadCreate("EmuThread"); 438 MicroProfileOnThreadCreate("EmuThread");
416 SCOPE_EXIT({ MicroProfileShutdown(); }); 439 SCOPE_EXIT({ MicroProfileShutdown(); });
417 440
@@ -424,7 +447,7 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
424 447
425 SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); }); 448 SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
426 449
427 jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath); 450 jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index);
428 if (result != Core::SystemResultStatus::Success) { 451 if (result != Core::SystemResultStatus::Success) {
429 return result; 452 return result;
430 } 453 }
@@ -521,6 +544,37 @@ jboolean JNICALL Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_supportsCustomDri
521#endif 544#endif
522} 545}
523 546
547jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
548 JNIEnv* env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
549 const char* file_redirect_dir_{};
550 int featureFlags{};
551 std::string hook_lib_dir = GetJString(env, j_hook_lib_dir);
552 auto handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(),
553 nullptr, nullptr, file_redirect_dir_, nullptr);
554 auto driver_library = std::make_shared<Common::DynamicLibrary>(handle);
555 InputCommon::InputSubsystem input_subsystem;
556 auto m_window = std::make_unique<EmuWindow_Android>(
557 &input_subsystem, ANativeWindow_fromSurface(env, j_surf), driver_library);
558
559 Vulkan::vk::InstanceDispatch dld;
560 Vulkan::vk::Instance vk_instance = Vulkan::CreateInstance(
561 *driver_library, dld, VK_API_VERSION_1_1, Core::Frontend::WindowSystemType::Android);
562
563 auto surface = Vulkan::CreateSurface(vk_instance, m_window->GetWindowInfo());
564
565 auto device = Vulkan::CreateDevice(vk_instance, dld, *surface);
566
567 auto driver_version = device.GetDriverVersion();
568 auto version_string =
569 fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(driver_version),
570 VK_API_VERSION_MINOR(driver_version), VK_API_VERSION_PATCH(driver_version));
571
572 jobjectArray j_driver_info =
573 env->NewObjectArray(2, IDCache::GetStringClass(), ToJString(env, version_string));
574 env->SetObjectArrayElement(j_driver_info, 1, ToJString(env, device.GetDriverName()));
575 return j_driver_info;
576}
577
524jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) { 578jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
525 Core::Crypto::KeyManager::Instance().ReloadKeys(); 579 Core::Crypto::KeyManager::Instance().ReloadKeys();
526 return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded()); 580 return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded());
@@ -689,11 +743,11 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
689 Settings::LogSettings(); 743 Settings::LogSettings();
690} 744}
691 745
692void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2(JNIEnv* env, jclass clazz, 746void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
693 jstring j_path) { 747 jint j_program_index) {
694 const std::string path = GetJString(env, j_path); 748 const std::string path = GetJString(env, j_path);
695 749
696 const Core::SystemResultStatus result{RunEmulation(path)}; 750 const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
697 if (result != Core::SystemResultStatus::Success) { 751 if (result != Core::SystemResultStatus::Success) {
698 env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), 752 env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
699 IDCache::GetExitEmulationActivity(), static_cast<int>(result)); 753 IDCache::GetExitEmulationActivity(), static_cast<int>(result));
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h
index dadb138ad..bfe3fccca 100644
--- a/src/android/app/src/main/jni/native.h
+++ b/src/android/app/src/main/jni/native.h
@@ -45,7 +45,8 @@ public:
45 const Core::PerfStatsResults& PerfStats(); 45 const Core::PerfStatsResults& PerfStats();
46 void ConfigureFilesystemProvider(const std::string& filepath); 46 void ConfigureFilesystemProvider(const std::string& filepath);
47 void InitializeSystem(bool reload); 47 void InitializeSystem(bool reload);
48 Core::SystemResultStatus InitializeEmulation(const std::string& filepath); 48 Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
49 const std::size_t program_index = 0);
49 50
50 bool IsHandheldOnly(); 51 bool IsHandheldOnly();
51 void SetDeviceType([[maybe_unused]] int index, int type); 52 void SetDeviceType([[maybe_unused]] int index, int type);
@@ -60,6 +61,7 @@ public:
60private: 61private:
61 static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max); 62 static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
62 static void OnEmulationStopped(Core::SystemResultStatus result); 63 static void OnEmulationStopped(Core::SystemResultStatus result);
64 static void ChangeProgram(std::size_t program_index);
63 65
64private: 66private:
65 // Window management 67 // Window management
@@ -84,4 +86,7 @@ private:
84 // Synchronization 86 // Synchronization
85 std::condition_variable_any m_cv; 87 std::condition_variable_any m_cv;
86 mutable std::mutex m_mutex; 88 mutable std::mutex m_mutex;
89
90 // Program index for next boot
91 std::atomic<s32> m_next_program_index = -1;
87}; 92};
diff --git a/src/android/app/src/main/res/layout/fragment_emulation.xml b/src/android/app/src/main/res/layout/fragment_emulation.xml
index c01117d14..0d2bfe8d6 100644
--- a/src/android/app/src/main/res/layout/fragment_emulation.xml
+++ b/src/android/app/src/main/res/layout/fragment_emulation.xml
@@ -34,8 +34,10 @@
34 android:layout_width="wrap_content" 34 android:layout_width="wrap_content"
35 android:layout_height="wrap_content" 35 android:layout_height="wrap_content"
36 android:layout_gravity="center" 36 android:layout_gravity="center"
37 android:focusable="false"
37 android:defaultFocusHighlightEnabled="false" 38 android:defaultFocusHighlightEnabled="false"
38 android:clickable="false"> 39 android:clickable="false"
40 app:rippleColor="@android:color/transparent">
39 41
40 <androidx.constraintlayout.widget.ConstraintLayout 42 <androidx.constraintlayout.widget.ConstraintLayout
41 android:id="@+id/loading_layout" 43 android:id="@+id/loading_layout"
diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp
index ef301d8b4..7a76c3d0b 100644
--- a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp
+++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp
@@ -89,11 +89,13 @@ u32 AudioRenderer::Receive(Direction dir) {
89} 89}
90 90
91void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit, 91void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
92 u64 applet_resource_user_id, bool reset) noexcept { 92 u64 applet_resource_user_id, Kernel::KProcess* process,
93 bool reset) noexcept {
93 command_buffers[session_id].buffer = buffer; 94 command_buffers[session_id].buffer = buffer;
94 command_buffers[session_id].size = size; 95 command_buffers[session_id].size = size;
95 command_buffers[session_id].time_limit = time_limit; 96 command_buffers[session_id].time_limit = time_limit;
96 command_buffers[session_id].applet_resource_user_id = applet_resource_user_id; 97 command_buffers[session_id].applet_resource_user_id = applet_resource_user_id;
98 command_buffers[session_id].process = process;
97 command_buffers[session_id].reset_buffer = reset; 99 command_buffers[session_id].reset_buffer = reset;
98} 100}
99 101
@@ -173,7 +175,8 @@ void AudioRenderer::Main(std::stop_token stop_token) {
173 // If there are no remaining commands (from the previous list), 175 // If there are no remaining commands (from the previous list),
174 // this is a new command list, initialize it. 176 // this is a new command list, initialize it.
175 if (command_buffer.remaining_command_count == 0) { 177 if (command_buffer.remaining_command_count == 0) {
176 command_list_processor.Initialize(system, command_buffer.buffer, 178 command_list_processor.Initialize(system, *command_buffer.process,
179 command_buffer.buffer,
177 command_buffer.size, streams[index]); 180 command_buffer.size, streams[index]);
178 } 181 }
179 182
diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h
index 57b89d9fe..875266f27 100644
--- a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h
+++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h
@@ -19,6 +19,10 @@ namespace Core {
19class System; 19class System;
20} // namespace Core 20} // namespace Core
21 21
22namespace Kernel {
23class KProcess;
24}
25
22namespace AudioCore { 26namespace AudioCore {
23namespace Sink { 27namespace Sink {
24class Sink; 28class Sink;
@@ -69,7 +73,8 @@ public:
69 u32 Receive(Direction dir); 73 u32 Receive(Direction dir);
70 74
71 void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit, 75 void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
72 u64 applet_resource_user_id, bool reset) noexcept; 76 u64 applet_resource_user_id, Kernel::KProcess* process,
77 bool reset) noexcept;
73 u32 GetRemainCommandCount(s32 session_id) const noexcept; 78 u32 GetRemainCommandCount(s32 session_id) const noexcept;
74 void ClearRemainCommandCount(s32 session_id) noexcept; 79 void ClearRemainCommandCount(s32 session_id) noexcept;
75 u64 GetRenderingStartTick(s32 session_id) const noexcept; 80 u64 GetRenderingStartTick(s32 session_id) const noexcept;
diff --git a/src/audio_core/adsp/apps/audio_renderer/command_buffer.h b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h
index 3fd1b09dc..d6a721f34 100644
--- a/src/audio_core/adsp/apps/audio_renderer/command_buffer.h
+++ b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h
@@ -6,6 +6,10 @@
6#include "audio_core/common/common.h" 6#include "audio_core/common/common.h"
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9namespace Kernel {
10class KProcess;
11}
12
9namespace AudioCore::ADSP::AudioRenderer { 13namespace AudioCore::ADSP::AudioRenderer {
10 14
11struct CommandBuffer { 15struct CommandBuffer {
@@ -14,6 +18,7 @@ struct CommandBuffer {
14 u64 size{}; 18 u64 size{};
15 u64 time_limit{}; 19 u64 time_limit{};
16 u64 applet_resource_user_id{}; 20 u64 applet_resource_user_id{};
21 Kernel::KProcess* process{};
17 bool reset_buffer{}; 22 bool reset_buffer{};
18 // Set by the DSP 23 // Set by the DSP
19 u32 remaining_command_count{}; 24 u32 remaining_command_count{};
diff --git a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp
index 24e4d0496..eef2c0b89 100644
--- a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp
+++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp
@@ -9,14 +9,15 @@
9#include "common/settings.h" 9#include "common/settings.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/core_timing.h" 11#include "core/core_timing.h"
12#include "core/hle/kernel/k_process.h"
12#include "core/memory.h" 13#include "core/memory.h"
13 14
14namespace AudioCore::ADSP::AudioRenderer { 15namespace AudioCore::ADSP::AudioRenderer {
15 16
16void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size, 17void CommandListProcessor::Initialize(Core::System& system_, Kernel::KProcess& process,
17 Sink::SinkStream* stream_) { 18 CpuAddr buffer, u64 size, Sink::SinkStream* stream_) {
18 system = &system_; 19 system = &system_;
19 memory = &system->ApplicationMemory(); 20 memory = &process.GetMemory();
20 stream = stream_; 21 stream = stream_;
21 header = reinterpret_cast<Renderer::CommandListHeader*>(buffer); 22 header = reinterpret_cast<Renderer::CommandListHeader*>(buffer);
22 commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader)); 23 commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader));
diff --git a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h
index 4e5fb793e..944e82505 100644
--- a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h
+++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h
@@ -16,6 +16,10 @@ class Memory;
16class System; 16class System;
17} // namespace Core 17} // namespace Core
18 18
19namespace Kernel {
20class KProcess;
21}
22
19namespace AudioCore { 23namespace AudioCore {
20namespace Sink { 24namespace Sink {
21class SinkStream; 25class SinkStream;
@@ -40,7 +44,8 @@ public:
40 * @param size - The size of the buffer. 44 * @param size - The size of the buffer.
41 * @param stream - The stream to be used for sending the samples. 45 * @param stream - The stream to be used for sending the samples.
42 */ 46 */
43 void Initialize(Core::System& system, CpuAddr buffer, u64 size, Sink::SinkStream* stream); 47 void Initialize(Core::System& system, Kernel::KProcess& process, CpuAddr buffer, u64 size,
48 Sink::SinkStream* stream);
44 49
45 /** 50 /**
46 * Set the maximum processing time for this command list. 51 * Set the maximum processing time for this command list.
diff --git a/src/audio_core/renderer/audio_renderer.cpp b/src/audio_core/renderer/audio_renderer.cpp
index 09efe9be9..df03d03aa 100644
--- a/src/audio_core/renderer/audio_renderer.cpp
+++ b/src/audio_core/renderer/audio_renderer.cpp
@@ -6,6 +6,7 @@
6#include "audio_core/renderer/audio_renderer.h" 6#include "audio_core/renderer/audio_renderer.h"
7#include "audio_core/renderer/system_manager.h" 7#include "audio_core/renderer/system_manager.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/kernel/k_process.h"
9#include "core/hle/kernel/k_transfer_memory.h" 10#include "core/hle/kernel/k_transfer_memory.h"
10#include "core/hle/service/audio/errors.h" 11#include "core/hle/service/audio/errors.h"
11 12
@@ -17,7 +18,8 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren
17Result Renderer::Initialize(const AudioRendererParameterInternal& params, 18Result Renderer::Initialize(const AudioRendererParameterInternal& params,
18 Kernel::KTransferMemory* transfer_memory, 19 Kernel::KTransferMemory* transfer_memory,
19 const u64 transfer_memory_size, const u32 process_handle, 20 const u64 transfer_memory_size, const u32 process_handle,
20 const u64 applet_resource_user_id, const s32 session_id) { 21 Kernel::KProcess& process, const u64 applet_resource_user_id,
22 const s32 session_id) {
21 if (params.execution_mode == ExecutionMode::Auto) { 23 if (params.execution_mode == ExecutionMode::Auto) {
22 if (!manager.AddSystem(system)) { 24 if (!manager.AddSystem(system)) {
23 LOG_ERROR(Service_Audio, 25 LOG_ERROR(Service_Audio,
@@ -28,7 +30,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
28 } 30 }
29 31
30 initialized = true; 32 initialized = true;
31 system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, 33 system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
32 applet_resource_user_id, session_id); 34 applet_resource_user_id, session_id);
33 35
34 return ResultSuccess; 36 return ResultSuccess;
diff --git a/src/audio_core/renderer/audio_renderer.h b/src/audio_core/renderer/audio_renderer.h
index 24650278b..1219f74ca 100644
--- a/src/audio_core/renderer/audio_renderer.h
+++ b/src/audio_core/renderer/audio_renderer.h
@@ -14,7 +14,8 @@ class System;
14 14
15namespace Kernel { 15namespace Kernel {
16class KTransferMemory; 16class KTransferMemory;
17} 17class KProcess;
18} // namespace Kernel
18 19
19namespace AudioCore { 20namespace AudioCore {
20struct AudioRendererParameterInternal; 21struct AudioRendererParameterInternal;
@@ -44,7 +45,8 @@ public:
44 */ 45 */
45 Result Initialize(const AudioRendererParameterInternal& params, 46 Result Initialize(const AudioRendererParameterInternal& params,
46 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, 47 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
47 u32 process_handle, u64 applet_resource_user_id, s32 session_id); 48 u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
49 s32 session_id);
48 50
49 /** 51 /**
50 * Finalize the renderer for shutdown. 52 * Finalize the renderer for shutdown.
diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp
index 31f92087c..ca656edae 100644
--- a/src/audio_core/renderer/system.cpp
+++ b/src/audio_core/renderer/system.cpp
@@ -32,6 +32,7 @@
32#include "core/core.h" 32#include "core/core.h"
33#include "core/core_timing.h" 33#include "core/core_timing.h"
34#include "core/hle/kernel/k_event.h" 34#include "core/hle/kernel/k_event.h"
35#include "core/hle/kernel/k_process.h"
35#include "core/hle/kernel/k_transfer_memory.h" 36#include "core/hle/kernel/k_transfer_memory.h"
36#include "core/memory.h" 37#include "core/memory.h"
37 38
@@ -101,7 +102,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
101 102
102Result System::Initialize(const AudioRendererParameterInternal& params, 103Result System::Initialize(const AudioRendererParameterInternal& params,
103 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, 104 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
104 u32 process_handle_, u64 applet_resource_user_id_, s32 session_id_) { 105 u32 process_handle_, Kernel::KProcess& process_,
106 u64 applet_resource_user_id_, s32 session_id_) {
105 if (!CheckValidRevision(params.revision)) { 107 if (!CheckValidRevision(params.revision)) {
106 return Service::Audio::ResultInvalidRevision; 108 return Service::Audio::ResultInvalidRevision;
107 } 109 }
@@ -117,6 +119,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
117 behavior.SetUserLibRevision(params.revision); 119 behavior.SetUserLibRevision(params.revision);
118 120
119 process_handle = process_handle_; 121 process_handle = process_handle_;
122 process = &process_;
120 applet_resource_user_id = applet_resource_user_id_; 123 applet_resource_user_id = applet_resource_user_id_;
121 session_id = session_id_; 124 session_id = session_id_;
122 125
@@ -129,7 +132,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
129 render_device = params.rendering_device; 132 render_device = params.rendering_device;
130 execution_mode = params.execution_mode; 133 execution_mode = params.execution_mode;
131 134
132 core.ApplicationMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size); 135 process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
133 136
134 // Note: We're not actually using the transfer memory because it's a pain to code for. 137 // Note: We're not actually using the transfer memory because it's a pain to code for.
135 // Allocate the memory normally instead and hope the game doesn't try to read anything back 138 // Allocate the memory normally instead and hope the game doesn't try to read anything back
@@ -613,7 +616,8 @@ void System::SendCommandToDsp() {
613 static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 * 616 static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
614 (static_cast<f32>(render_time_limit_percent) / 100.0f))}; 617 (static_cast<f32>(render_time_limit_percent) / 100.0f))};
615 audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit, 618 audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
616 applet_resource_user_id, reset_command_buffers); 619 applet_resource_user_id, process,
620 reset_command_buffers);
617 reset_command_buffers = false; 621 reset_command_buffers = false;
618 command_buffer_size = command_size; 622 command_buffer_size = command_size;
619 if (remaining_command_count == 0) { 623 if (remaining_command_count == 0) {
diff --git a/src/audio_core/renderer/system.h b/src/audio_core/renderer/system.h
index 8a8341710..753a0b796 100644
--- a/src/audio_core/renderer/system.h
+++ b/src/audio_core/renderer/system.h
@@ -29,6 +29,7 @@ class System;
29 29
30namespace Kernel { 30namespace Kernel {
31class KEvent; 31class KEvent;
32class KProcess;
32class KTransferMemory; 33class KTransferMemory;
33} // namespace Kernel 34} // namespace Kernel
34 35
@@ -80,7 +81,8 @@ public:
80 */ 81 */
81 Result Initialize(const AudioRendererParameterInternal& params, 82 Result Initialize(const AudioRendererParameterInternal& params,
82 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, 83 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
83 u32 process_handle, u64 applet_resource_user_id, s32 session_id); 84 u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
85 s32 session_id);
84 86
85 /** 87 /**
86 * Finalize the system. 88 * Finalize the system.
@@ -275,6 +277,8 @@ private:
275 Common::Event terminate_event{}; 277 Common::Event terminate_event{};
276 /// Does what locks do 278 /// Does what locks do
277 std::mutex lock{}; 279 std::mutex lock{};
280 /// Process this audio render is operating within, used for memory reads/writes.
281 Kernel::KProcess* process{};
278 /// Handle for the process for this system, unused 282 /// Handle for the process for this system, unused
279 u32 process_handle{}; 283 u32 process_handle{};
280 /// Applet resource id for this system, unused 284 /// Applet resource id for this system, unused
diff --git a/src/common/atomic_ops.h b/src/common/atomic_ops.h
index c18bb33c4..9bf6f2f81 100644
--- a/src/common/atomic_ops.h
+++ b/src/common/atomic_ops.h
@@ -15,25 +15,34 @@ namespace Common {
15 15
16#if _MSC_VER 16#if _MSC_VER
17 17
18[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) { 18template <typename T>
19[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected);
20template <typename T>
21[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual);
22
23template <>
24[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected) {
19 const u8 result = 25 const u8 result =
20 _InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected); 26 _InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
21 return result == expected; 27 return result == expected;
22} 28}
23 29
24[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) { 30template <>
31[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected) {
25 const u16 result = 32 const u16 result =
26 _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected); 33 _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
27 return result == expected; 34 return result == expected;
28} 35}
29 36
30[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) { 37template <>
38[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected) {
31 const u32 result = 39 const u32 result =
32 _InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected); 40 _InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
33 return result == expected; 41 return result == expected;
34} 42}
35 43
36[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) { 44template <>
45[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected) {
37 const u64 result = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), 46 const u64 result = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer),
38 value, expected); 47 value, expected);
39 return result == expected; 48 return result == expected;
@@ -45,29 +54,32 @@ namespace Common {
45 reinterpret_cast<__int64*>(expected.data())) != 0; 54 reinterpret_cast<__int64*>(expected.data())) != 0;
46} 55}
47 56
48[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected, 57template <>
49 u8& actual) { 58[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected, u8& actual) {
50 actual = 59 actual =
51 _InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected); 60 _InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
52 return actual == expected; 61 return actual == expected;
53} 62}
54 63
55[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected, 64template <>
56 u16& actual) { 65[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected,
66 u16& actual) {
57 actual = 67 actual =
58 _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected); 68 _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
59 return actual == expected; 69 return actual == expected;
60} 70}
61 71
62[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected, 72template <>
63 u32& actual) { 73[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected,
74 u32& actual) {
64 actual = 75 actual =
65 _InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected); 76 _InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
66 return actual == expected; 77 return actual == expected;
67} 78}
68 79
69[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected, 80template <>
70 u64& actual) { 81[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected,
82 u64& actual) {
71 actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value, 83 actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value,
72 expected); 84 expected);
73 return actual == expected; 85 return actual == expected;
@@ -91,23 +103,12 @@ namespace Common {
91 103
92#else 104#else
93 105
94[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) { 106template <typename T>
95 return __sync_bool_compare_and_swap(pointer, expected, value); 107[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected) {
96}
97
98[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
99 return __sync_bool_compare_and_swap(pointer, expected, value);
100}
101
102[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
103 return __sync_bool_compare_and_swap(pointer, expected, value); 108 return __sync_bool_compare_and_swap(pointer, expected, value);
104} 109}
105 110
106[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) { 111[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected) {
107 return __sync_bool_compare_and_swap(pointer, expected, value);
108}
109
110[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected) {
111 unsigned __int128 value_a; 112 unsigned __int128 value_a;
112 unsigned __int128 expected_a; 113 unsigned __int128 expected_a;
113 std::memcpy(&value_a, value.data(), sizeof(u128)); 114 std::memcpy(&value_a, value.data(), sizeof(u128));
@@ -115,31 +116,13 @@ namespace Common {
115 return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a); 116 return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
116} 117}
117 118
118[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected, 119template <typename T>
119 u8& actual) { 120[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual) {
120 actual = __sync_val_compare_and_swap(pointer, expected, value); 121 actual = __sync_val_compare_and_swap(pointer, expected, value);
121 return actual == expected; 122 return actual == expected;
122} 123}
123 124
124[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected, 125[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected,
125 u16& actual) {
126 actual = __sync_val_compare_and_swap(pointer, expected, value);
127 return actual == expected;
128}
129
130[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
131 u32& actual) {
132 actual = __sync_val_compare_and_swap(pointer, expected, value);
133 return actual == expected;
134}
135
136[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
137 u64& actual) {
138 actual = __sync_val_compare_and_swap(pointer, expected, value);
139 return actual == expected;
140}
141
142[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected,
143 u128& actual) { 126 u128& actual) {
144 unsigned __int128 value_a; 127 unsigned __int128 value_a;
145 unsigned __int128 expected_a; 128 unsigned __int128 expected_a;
@@ -151,7 +134,7 @@ namespace Common {
151 return actual_a == expected_a; 134 return actual_a == expected_a;
152} 135}
153 136
154[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) { 137[[nodiscard]] inline u128 AtomicLoad128(u64* pointer) {
155 unsigned __int128 zeros_a = 0; 138 unsigned __int128 zeros_a = 0;
156 unsigned __int128 result_a = 139 unsigned __int128 result_a =
157 __sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a); 140 __sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a);
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 7d3421929..8a360a839 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -543,7 +543,8 @@ void KThread::Unpin() {
543 ASSERT(m_parent != nullptr); 543 ASSERT(m_parent != nullptr);
544 544
545 // Resume any threads that began waiting on us while we were pinned. 545 // Resume any threads that began waiting on us while we were pinned.
546 for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); ++it) { 546 for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end();
547 it = m_pinned_waiter_list.erase(it)) {
547 it->EndWait(ResultSuccess); 548 it->EndWait(ResultSuccess);
548 } 549 }
549} 550}
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp
index 50adc7c02..e83e931c5 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit.cpp
+++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp
@@ -59,7 +59,7 @@ void MiiEdit::Initialize() {
59 break; 59 break;
60 } 60 }
61 61
62 manager = system.ServiceManager().GetService<Mii::MiiDBModule>("mii:e")->GetMiiManager(); 62 manager = system.ServiceManager().GetService<Mii::IStaticService>("mii:e")->GetMiiManager();
63 if (manager == nullptr) { 63 if (manager == nullptr) {
64 manager = std::make_shared<Mii::MiiManager>(); 64 manager = std::make_shared<Mii::MiiManager>();
65 } 65 }
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp
index 66dd64fd1..3101cf447 100644
--- a/src/core/hle/service/audio/audctl.cpp
+++ b/src/core/hle/service/audio/audctl.cpp
@@ -4,6 +4,8 @@
4#include "common/logging/log.h" 4#include "common/logging/log.h"
5#include "core/hle/service/audio/audctl.h" 5#include "core/hle/service/audio/audctl.h"
6#include "core/hle/service/ipc_helpers.h" 6#include "core/hle/service/ipc_helpers.h"
7#include "core/hle/service/set/system_settings_server.h"
8#include "core/hle/service/sm/sm.h"
7 9
8namespace Service::Audio { 10namespace Service::Audio {
9 11
@@ -19,15 +21,15 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
19 {6, nullptr, "IsTargetConnected"}, 21 {6, nullptr, "IsTargetConnected"},
20 {7, nullptr, "SetDefaultTarget"}, 22 {7, nullptr, "SetDefaultTarget"},
21 {8, nullptr, "GetDefaultTarget"}, 23 {8, nullptr, "GetDefaultTarget"},
22 {9, nullptr, "GetAudioOutputMode"}, 24 {9, &AudCtl::GetAudioOutputMode, "GetAudioOutputMode"},
23 {10, nullptr, "SetAudioOutputMode"}, 25 {10, &AudCtl::SetAudioOutputMode, "SetAudioOutputMode"},
24 {11, nullptr, "SetForceMutePolicy"}, 26 {11, nullptr, "SetForceMutePolicy"},
25 {12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"}, 27 {12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"},
26 {13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"}, 28 {13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"},
27 {14, nullptr, "SetOutputModeSetting"}, 29 {14, &AudCtl::SetOutputModeSetting, "SetOutputModeSetting"},
28 {15, nullptr, "SetOutputTarget"}, 30 {15, nullptr, "SetOutputTarget"},
29 {16, nullptr, "SetInputTargetForceEnabled"}, 31 {16, nullptr, "SetInputTargetForceEnabled"},
30 {17, nullptr, "SetHeadphoneOutputLevelMode"}, 32 {17, &AudCtl::SetHeadphoneOutputLevelMode, "SetHeadphoneOutputLevelMode"},
31 {18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"}, 33 {18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"},
32 {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, 34 {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
33 {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, 35 {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
@@ -40,7 +42,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
40 {27, nullptr, "SetVolumeMappingTableForDev"}, 42 {27, nullptr, "SetVolumeMappingTableForDev"},
41 {28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, 43 {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
42 {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, 44 {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
43 {30, nullptr, "SetSpeakerAutoMuteEnabled"}, 45 {30, &AudCtl::SetSpeakerAutoMuteEnabled, "SetSpeakerAutoMuteEnabled"},
44 {31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"}, 46 {31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
45 {32, nullptr, "GetActiveOutputTarget"}, 47 {32, nullptr, "GetActiveOutputTarget"},
46 {33, nullptr, "GetTargetDeviceInfo"}, 48 {33, nullptr, "GetTargetDeviceInfo"},
@@ -68,6 +70,9 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
68 // clang-format on 70 // clang-format on
69 71
70 RegisterHandlers(functions); 72 RegisterHandlers(functions);
73
74 m_set_sys =
75 system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
71} 76}
72 77
73AudCtl::~AudCtl() = default; 78AudCtl::~AudCtl() = default;
@@ -96,6 +101,33 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
96 rb.Push(target_max_volume); 101 rb.Push(target_max_volume);
97} 102}
98 103
104void AudCtl::GetAudioOutputMode(HLERequestContext& ctx) {
105 IPC::RequestParser rp{ctx};
106 const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
107
108 Set::AudioOutputMode output_mode{};
109 const auto result = m_set_sys->GetAudioOutputMode(output_mode, target);
110
111 LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
112
113 IPC::ResponseBuilder rb{ctx, 3};
114 rb.Push(result);
115 rb.PushEnum(output_mode);
116}
117
118void AudCtl::SetAudioOutputMode(HLERequestContext& ctx) {
119 IPC::RequestParser rp{ctx};
120 const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
121 const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
122
123 const auto result = m_set_sys->SetAudioOutputMode(target, output_mode);
124
125 LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
126
127 IPC::ResponseBuilder rb{ctx, 2};
128 rb.Push(result);
129}
130
99void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) { 131void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
100 LOG_WARNING(Audio, "(STUBBED) called"); 132 LOG_WARNING(Audio, "(STUBBED) called");
101 133
@@ -106,13 +138,31 @@ void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
106 138
107void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) { 139void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) {
108 IPC::RequestParser rp{ctx}; 140 IPC::RequestParser rp{ctx};
109 const auto value = rp.Pop<u32>(); 141 const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
110 142
111 LOG_WARNING(Audio, "(STUBBED) called, value={}", value); 143 LOG_WARNING(Audio, "(STUBBED) called, target={}", target);
112 144
113 IPC::ResponseBuilder rb{ctx, 3}; 145 IPC::ResponseBuilder rb{ctx, 3};
114 rb.Push(ResultSuccess); 146 rb.Push(ResultSuccess);
115 rb.PushEnum(AudioOutputMode::PcmAuto); 147 rb.PushEnum(Set::AudioOutputMode::ch_7_1);
148}
149
150void AudCtl::SetOutputModeSetting(HLERequestContext& ctx) {
151 IPC::RequestParser rp{ctx};
152 const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
153 const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
154
155 LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
156
157 IPC::ResponseBuilder rb{ctx, 2};
158 rb.Push(ResultSuccess);
159}
160
161void AudCtl::SetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
162 LOG_WARNING(Audio, "(STUBBED) called");
163
164 IPC::ResponseBuilder rb{ctx, 2};
165 rb.Push(ResultSuccess);
116} 166}
117 167
118void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) { 168void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
@@ -123,14 +173,28 @@ void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
123 rb.PushEnum(HeadphoneOutputLevelMode::Normal); 173 rb.PushEnum(HeadphoneOutputLevelMode::Normal);
124} 174}
125 175
176void AudCtl::SetSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
177 IPC::RequestParser rp{ctx};
178 const auto is_speaker_auto_mute_enabled{rp.Pop<bool>()};
179
180 LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
181 is_speaker_auto_mute_enabled);
182
183 const auto result = m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
184
185 IPC::ResponseBuilder rb{ctx, 2};
186 rb.Push(result);
187}
188
126void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) { 189void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
127 const bool is_speaker_auto_mute_enabled = false; 190 bool is_speaker_auto_mute_enabled{};
191 const auto result = m_set_sys->GetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
128 192
129 LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}", 193 LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
130 is_speaker_auto_mute_enabled); 194 is_speaker_auto_mute_enabled);
131 195
132 IPC::ResponseBuilder rb{ctx, 3}; 196 IPC::ResponseBuilder rb{ctx, 3};
133 rb.Push(ResultSuccess); 197 rb.Push(result);
134 rb.Push<u8>(is_speaker_auto_mute_enabled); 198 rb.Push<u8>(is_speaker_auto_mute_enabled);
135} 199}
136 200
diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h
index d57abb383..4c90ead70 100644
--- a/src/core/hle/service/audio/audctl.h
+++ b/src/core/hle/service/audio/audctl.h
@@ -9,6 +9,10 @@ namespace Core {
9class System; 9class System;
10} 10}
11 11
12namespace Service::Set {
13class ISystemSettingsServer;
14}
15
12namespace Service::Audio { 16namespace Service::Audio {
13 17
14class AudCtl final : public ServiceFramework<AudCtl> { 18class AudCtl final : public ServiceFramework<AudCtl> {
@@ -17,14 +21,6 @@ public:
17 ~AudCtl() override; 21 ~AudCtl() override;
18 22
19private: 23private:
20 enum class AudioOutputMode {
21 Invalid,
22 Pcm1ch,
23 Pcm2ch,
24 Pcm6ch,
25 PcmAuto,
26 };
27
28 enum class ForceMutePolicy { 24 enum class ForceMutePolicy {
29 Disable, 25 Disable,
30 SpeakerMuteOnHeadphoneUnplugged, 26 SpeakerMuteOnHeadphoneUnplugged,
@@ -37,10 +33,18 @@ private:
37 33
38 void GetTargetVolumeMin(HLERequestContext& ctx); 34 void GetTargetVolumeMin(HLERequestContext& ctx);
39 void GetTargetVolumeMax(HLERequestContext& ctx); 35 void GetTargetVolumeMax(HLERequestContext& ctx);
36 void GetAudioOutputMode(HLERequestContext& ctx);
37 void SetAudioOutputMode(HLERequestContext& ctx);
40 void GetForceMutePolicy(HLERequestContext& ctx); 38 void GetForceMutePolicy(HLERequestContext& ctx);
41 void GetOutputModeSetting(HLERequestContext& ctx); 39 void GetOutputModeSetting(HLERequestContext& ctx);
40 void SetOutputModeSetting(HLERequestContext& ctx);
41 void SetHeadphoneOutputLevelMode(HLERequestContext& ctx);
42 void GetHeadphoneOutputLevelMode(HLERequestContext& ctx); 42 void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
43 void SetSpeakerAutoMuteEnabled(HLERequestContext& ctx);
43 void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx); 44 void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
45 void AcquireTargetNotification(HLERequestContext& ctx);
46
47 std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
44}; 48};
45 49
46} // namespace Service::Audio 50} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 05581e6e0..10108abc0 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -35,10 +35,11 @@ public:
35 explicit IAudioRenderer(Core::System& system_, Manager& manager_, 35 explicit IAudioRenderer(Core::System& system_, Manager& manager_,
36 AudioCore::AudioRendererParameterInternal& params, 36 AudioCore::AudioRendererParameterInternal& params,
37 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, 37 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
38 u32 process_handle, u64 applet_resource_user_id, s32 session_id) 38 u32 process_handle, Kernel::KProcess& process_,
39 u64 applet_resource_user_id, s32 session_id)
39 : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"}, 40 : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
40 rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_}, 41 rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
41 impl{std::make_unique<Renderer>(system_, manager, rendered_event)} { 42 impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
42 // clang-format off 43 // clang-format off
43 static const FunctionInfo functions[] = { 44 static const FunctionInfo functions[] = {
44 {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, 45 {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
@@ -59,13 +60,15 @@ public:
59 // clang-format on 60 // clang-format on
60 RegisterHandlers(functions); 61 RegisterHandlers(functions);
61 62
62 impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, 63 process.Open();
64 impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
63 applet_resource_user_id, session_id); 65 applet_resource_user_id, session_id);
64 } 66 }
65 67
66 ~IAudioRenderer() override { 68 ~IAudioRenderer() override {
67 impl->Finalize(); 69 impl->Finalize();
68 service_context.CloseEvent(rendered_event); 70 service_context.CloseEvent(rendered_event);
71 process.Close();
69 } 72 }
70 73
71private: 74private:
@@ -235,6 +238,7 @@ private:
235 Kernel::KEvent* rendered_event; 238 Kernel::KEvent* rendered_event;
236 Manager& manager; 239 Manager& manager;
237 std::unique_ptr<Renderer> impl; 240 std::unique_ptr<Renderer> impl;
241 Kernel::KProcess& process;
238 Common::ScratchBuffer<u8> output_buffer; 242 Common::ScratchBuffer<u8> output_buffer;
239 Common::ScratchBuffer<u8> performance_buffer; 243 Common::ScratchBuffer<u8> performance_buffer;
240}; 244};
@@ -455,7 +459,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
455 return; 459 return;
456 } 460 }
457 461
458 auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)}; 462 auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
459 auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)}; 463 auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
460 464
461 const auto session_id{impl->GetSessionId()}; 465 const auto session_id{impl->GetSessionId()};
@@ -472,7 +476,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
472 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 476 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
473 rb.Push(ResultSuccess); 477 rb.Push(ResultSuccess);
474 rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(), 478 rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
475 transfer_memory_size, process_handle, 479 transfer_memory_size, process_handle, *process,
476 applet_resource_user_id, session_id); 480 applet_resource_user_id, session_id);
477} 481}
478 482
@@ -522,7 +526,7 @@ void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) {
522} 526}
523 527
524void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) { 528void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
525 LOG_DEBUG(Service_Audio, "called"); 529 LOG_ERROR(Service_Audio, "called. Implement me!");
526} 530}
527 531
528void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) { 532void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index c28eed926..b4d16fed5 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -4,15 +4,18 @@
4#include <memory> 4#include <memory>
5 5
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/hle/service/cmif_serialization.h"
7#include "core/hle/service/ipc_helpers.h" 8#include "core/hle/service/ipc_helpers.h"
8#include "core/hle/service/mii/mii.h" 9#include "core/hle/service/mii/mii.h"
9#include "core/hle/service/mii/mii_manager.h" 10#include "core/hle/service/mii/mii_manager.h"
10#include "core/hle/service/mii/mii_result.h" 11#include "core/hle/service/mii/mii_result.h"
11#include "core/hle/service/mii/types/char_info.h" 12#include "core/hle/service/mii/types/char_info.h"
13#include "core/hle/service/mii/types/raw_data.h"
12#include "core/hle/service/mii/types/store_data.h" 14#include "core/hle/service/mii/types/store_data.h"
13#include "core/hle/service/mii/types/ver3_store_data.h" 15#include "core/hle/service/mii/types/ver3_store_data.h"
14#include "core/hle/service/server_manager.h" 16#include "core/hle/service/server_manager.h"
15#include "core/hle/service/service.h" 17#include "core/hle/service/set/system_settings_server.h"
18#include "core/hle/service/sm/sm.h"
16 19
17namespace Service::Mii { 20namespace Service::Mii {
18 21
@@ -24,549 +27,302 @@ public:
24 is_system_} { 27 is_system_} {
25 // clang-format off 28 // clang-format off
26 static const FunctionInfo functions[] = { 29 static const FunctionInfo functions[] = {
27 {0, &IDatabaseService::IsUpdated, "IsUpdated"}, 30 {0, D<&IDatabaseService::IsUpdated>, "IsUpdated"},
28 {1, &IDatabaseService::IsFullDatabase, "IsFullDatabase"}, 31 {1, D<&IDatabaseService::IsFullDatabase>, "IsFullDatabase"},
29 {2, &IDatabaseService::GetCount, "GetCount"}, 32 {2, D<&IDatabaseService::GetCount>, "GetCount"},
30 {3, &IDatabaseService::Get, "Get"}, 33 {3, D<&IDatabaseService::Get>, "Get"},
31 {4, &IDatabaseService::Get1, "Get1"}, 34 {4, D<&IDatabaseService::Get1>, "Get1"},
32 {5, &IDatabaseService::UpdateLatest, "UpdateLatest"}, 35 {5, D<&IDatabaseService::UpdateLatest>, "UpdateLatest"},
33 {6, &IDatabaseService::BuildRandom, "BuildRandom"}, 36 {6, D<&IDatabaseService::BuildRandom>, "BuildRandom"},
34 {7, &IDatabaseService::BuildDefault, "BuildDefault"}, 37 {7, D<&IDatabaseService::BuildDefault>, "BuildDefault"},
35 {8, &IDatabaseService::Get2, "Get2"}, 38 {8, D<&IDatabaseService::Get2>, "Get2"},
36 {9, &IDatabaseService::Get3, "Get3"}, 39 {9, D<&IDatabaseService::Get3>, "Get3"},
37 {10, &IDatabaseService::UpdateLatest1, "UpdateLatest1"}, 40 {10, D<&IDatabaseService::UpdateLatest1>, "UpdateLatest1"},
38 {11, &IDatabaseService::FindIndex, "FindIndex"}, 41 {11, D<&IDatabaseService::FindIndex>, "FindIndex"},
39 {12, &IDatabaseService::Move, "Move"}, 42 {12, D<&IDatabaseService::Move>, "Move"},
40 {13, &IDatabaseService::AddOrReplace, "AddOrReplace"}, 43 {13, D<&IDatabaseService::AddOrReplace>, "AddOrReplace"},
41 {14, &IDatabaseService::Delete, "Delete"}, 44 {14, D<&IDatabaseService::Delete>, "Delete"},
42 {15, &IDatabaseService::DestroyFile, "DestroyFile"}, 45 {15, D<&IDatabaseService::DestroyFile>, "DestroyFile"},
43 {16, &IDatabaseService::DeleteFile, "DeleteFile"}, 46 {16, D<&IDatabaseService::DeleteFile>, "DeleteFile"},
44 {17, &IDatabaseService::Format, "Format"}, 47 {17, D<&IDatabaseService::Format>, "Format"},
45 {18, nullptr, "Import"}, 48 {18, nullptr, "Import"},
46 {19, nullptr, "Export"}, 49 {19, nullptr, "Export"},
47 {20, &IDatabaseService::IsBrokenDatabaseWithClearFlag, "IsBrokenDatabaseWithClearFlag"}, 50 {20, D<&IDatabaseService::IsBrokenDatabaseWithClearFlag>, "IsBrokenDatabaseWithClearFlag"},
48 {21, &IDatabaseService::GetIndex, "GetIndex"}, 51 {21, D<&IDatabaseService::GetIndex>, "GetIndex"},
49 {22, &IDatabaseService::SetInterfaceVersion, "SetInterfaceVersion"}, 52 {22, D<&IDatabaseService::SetInterfaceVersion>, "SetInterfaceVersion"},
50 {23, &IDatabaseService::Convert, "Convert"}, 53 {23, D<&IDatabaseService::Convert>, "Convert"},
51 {24, &IDatabaseService::ConvertCoreDataToCharInfo, "ConvertCoreDataToCharInfo"}, 54 {24, D<&IDatabaseService::ConvertCoreDataToCharInfo>, "ConvertCoreDataToCharInfo"},
52 {25, &IDatabaseService::ConvertCharInfoToCoreData, "ConvertCharInfoToCoreData"}, 55 {25, D<&IDatabaseService::ConvertCharInfoToCoreData>, "ConvertCharInfoToCoreData"},
53 {26, &IDatabaseService::Append, "Append"}, 56 {26, D<&IDatabaseService::Append>, "Append"},
54 }; 57 };
55 // clang-format on 58 // clang-format on
56 59
57 RegisterHandlers(functions); 60 RegisterHandlers(functions);
58 61
62 m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>(
63 "set:sys", true);
59 manager->Initialize(metadata); 64 manager->Initialize(metadata);
60 } 65 }
61 66
62private: 67private:
63 void IsUpdated(HLERequestContext& ctx) { 68 Result IsUpdated(Out<bool> out_is_updated, SourceFlag source_flag) {
64 IPC::RequestParser rp{ctx};
65 const auto source_flag{rp.PopRaw<SourceFlag>()};
66
67 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); 69 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
68 70
69 const bool is_updated = manager->IsUpdated(metadata, source_flag); 71 *out_is_updated = manager->IsUpdated(metadata, source_flag);
70 72
71 IPC::ResponseBuilder rb{ctx, 3}; 73 R_SUCCEED();
72 rb.Push(ResultSuccess);
73 rb.Push<u8>(is_updated);
74 } 74 }
75 75
76 void IsFullDatabase(HLERequestContext& ctx) { 76 Result IsFullDatabase(Out<bool> out_is_full_database) {
77 LOG_DEBUG(Service_Mii, "called"); 77 LOG_DEBUG(Service_Mii, "called");
78 78
79 const bool is_full_database = manager->IsFullDatabase(); 79 *out_is_full_database = manager->IsFullDatabase();
80 80
81 IPC::ResponseBuilder rb{ctx, 3}; 81 R_SUCCEED();
82 rb.Push(ResultSuccess);
83 rb.Push<u8>(is_full_database);
84 } 82 }
85 83
86 void GetCount(HLERequestContext& ctx) { 84 Result GetCount(Out<u32> out_mii_count, SourceFlag source_flag) {
87 IPC::RequestParser rp{ctx}; 85 *out_mii_count = manager->GetCount(metadata, source_flag);
88 const auto source_flag{rp.PopRaw<SourceFlag>()};
89
90 const u32 mii_count = manager->GetCount(metadata, source_flag);
91 86
92 LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, mii_count); 87 LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
88 *out_mii_count);
93 89
94 IPC::ResponseBuilder rb{ctx, 3}; 90 R_SUCCEED();
95 rb.Push(ResultSuccess);
96 rb.Push(mii_count);
97 } 91 }
98 92
99 void Get(HLERequestContext& ctx) { 93 Result Get(Out<u32> out_mii_count, SourceFlag source_flag,
100 IPC::RequestParser rp{ctx}; 94 OutArray<CharInfoElement, BufferAttr_HipcMapAlias> char_info_element_buffer) {
101 const auto source_flag{rp.PopRaw<SourceFlag>()}; 95 const auto result =
102 const auto output_size{ctx.GetWriteBufferNumElements<CharInfoElement>()}; 96 manager->Get(metadata, char_info_element_buffer, *out_mii_count, source_flag);
103
104 u32 mii_count{};
105 std::vector<CharInfoElement> char_info_elements(output_size);
106 const auto result = manager->Get(metadata, char_info_elements, mii_count, source_flag);
107
108 if (mii_count != 0) {
109 ctx.WriteBuffer(char_info_elements);
110 }
111 97
112 LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag, 98 LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
113 output_size, mii_count); 99 *out_mii_count);
114 100
115 IPC::ResponseBuilder rb{ctx, 3}; 101 R_RETURN(result);
116 rb.Push(result);
117 rb.Push(mii_count);
118 } 102 }
119 103
120 void Get1(HLERequestContext& ctx) { 104 Result Get1(Out<u32> out_mii_count, SourceFlag source_flag,
121 IPC::RequestParser rp{ctx}; 105 OutArray<CharInfo, BufferAttr_HipcMapAlias> char_info_buffer) {
122 const auto source_flag{rp.PopRaw<SourceFlag>()}; 106 const auto result = manager->Get(metadata, char_info_buffer, *out_mii_count, source_flag);
123 const auto output_size{ctx.GetWriteBufferNumElements<CharInfo>()};
124 107
125 u32 mii_count{}; 108 LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
126 std::vector<CharInfo> char_info(output_size); 109 *out_mii_count);
127 const auto result = manager->Get(metadata, char_info, mii_count, source_flag);
128 110
129 if (mii_count != 0) { 111 R_RETURN(result);
130 ctx.WriteBuffer(char_info);
131 }
132
133 LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
134 output_size, mii_count);
135
136 IPC::ResponseBuilder rb{ctx, 3};
137 rb.Push(result);
138 rb.Push(mii_count);
139 } 112 }
140 113
141 void UpdateLatest(HLERequestContext& ctx) { 114 Result UpdateLatest(Out<CharInfo> out_char_info, CharInfo& char_info, SourceFlag source_flag) {
142 IPC::RequestParser rp{ctx};
143 const auto char_info{rp.PopRaw<CharInfo>()};
144 const auto source_flag{rp.PopRaw<SourceFlag>()};
145
146 LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); 115 LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
147 116
148 CharInfo new_char_info{}; 117 R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag));
149 const auto result = manager->UpdateLatest(metadata, new_char_info, char_info, source_flag);
150 if (result.IsFailure()) {
151 IPC::ResponseBuilder rb{ctx, 2};
152 rb.Push(result);
153 return;
154 }
155
156 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
157 rb.Push(ResultSuccess);
158 rb.PushRaw(new_char_info);
159 } 118 }
160 119
161 void BuildRandom(HLERequestContext& ctx) { 120 Result BuildRandom(Out<CharInfo> out_char_info, Age age, Gender gender, Race race) {
162 IPC::RequestParser rp{ctx};
163 const auto age{rp.PopRaw<Age>()};
164 const auto gender{rp.PopRaw<Gender>()};
165 const auto race{rp.PopRaw<Race>()};
166
167 LOG_DEBUG(Service_Mii, "called with age={}, gender={}, race={}", age, gender, race); 121 LOG_DEBUG(Service_Mii, "called with age={}, gender={}, race={}", age, gender, race);
168 122
169 if (age > Age::All) { 123 R_UNLESS(age <= Age::All, ResultInvalidArgument);
170 IPC::ResponseBuilder rb{ctx, 2}; 124 R_UNLESS(gender <= Gender::All, ResultInvalidArgument);
171 rb.Push(ResultInvalidArgument); 125 R_UNLESS(race <= Race::All, ResultInvalidArgument);
172 return;
173 }
174
175 if (gender > Gender::All) {
176 IPC::ResponseBuilder rb{ctx, 2};
177 rb.Push(ResultInvalidArgument);
178 return;
179 }
180
181 if (race > Race::All) {
182 IPC::ResponseBuilder rb{ctx, 2};
183 rb.Push(ResultInvalidArgument);
184 return;
185 }
186
187 CharInfo char_info{};
188 manager->BuildRandom(char_info, age, gender, race);
189
190 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
191 rb.Push(ResultSuccess);
192 rb.PushRaw(char_info);
193 }
194 126
195 void BuildDefault(HLERequestContext& ctx) { 127 manager->BuildRandom(*out_char_info, age, gender, race);
196 IPC::RequestParser rp{ctx};
197 const auto index{rp.Pop<u32>()};
198 128
199 LOG_DEBUG(Service_Mii, "called with index={}", index); 129 R_SUCCEED();
130 }
200 131
201 if (index > 5) { 132 Result BuildDefault(Out<CharInfo> out_char_info, s32 index) {
202 IPC::ResponseBuilder rb{ctx, 2}; 133 LOG_DEBUG(Service_Mii, "called with index={}", index);
203 rb.Push(ResultInvalidArgument); 134 R_UNLESS(index < static_cast<s32>(RawData::DefaultMii.size()), ResultInvalidArgument);
204 return;
205 }
206 135
207 CharInfo char_info{}; 136 manager->BuildDefault(*out_char_info, index);
208 manager->BuildDefault(char_info, index);
209 137
210 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; 138 R_SUCCEED();
211 rb.Push(ResultSuccess);
212 rb.PushRaw(char_info);
213 } 139 }
214 140
215 void Get2(HLERequestContext& ctx) { 141 Result Get2(Out<u32> out_mii_count, SourceFlag source_flag,
216 IPC::RequestParser rp{ctx}; 142 OutArray<StoreDataElement, BufferAttr_HipcMapAlias> store_data_element_buffer) {
217 const auto source_flag{rp.PopRaw<SourceFlag>()}; 143 const auto result =
218 const auto output_size{ctx.GetWriteBufferNumElements<StoreDataElement>()}; 144 manager->Get(metadata, store_data_element_buffer, *out_mii_count, source_flag);
219 145
220 u32 mii_count{}; 146 LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
221 std::vector<StoreDataElement> store_data_elements(output_size); 147 *out_mii_count);
222 const auto result = manager->Get(metadata, store_data_elements, mii_count, source_flag);
223 148
224 if (mii_count != 0) { 149 R_RETURN(result);
225 ctx.WriteBuffer(store_data_elements);
226 }
227
228 LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
229 output_size, mii_count);
230
231 IPC::ResponseBuilder rb{ctx, 3};
232 rb.Push(result);
233 rb.Push(mii_count);
234 } 150 }
235 151
236 void Get3(HLERequestContext& ctx) { 152 Result Get3(Out<u32> out_mii_count, SourceFlag source_flag,
237 IPC::RequestParser rp{ctx}; 153 OutArray<StoreData, BufferAttr_HipcMapAlias> store_data_buffer) {
238 const auto source_flag{rp.PopRaw<SourceFlag>()}; 154 const auto result = manager->Get(metadata, store_data_buffer, *out_mii_count, source_flag);
239 const auto output_size{ctx.GetWriteBufferNumElements<StoreData>()};
240
241 u32 mii_count{};
242 std::vector<StoreData> store_data(output_size);
243 const auto result = manager->Get(metadata, store_data, mii_count, source_flag);
244 155
245 if (mii_count != 0) { 156 LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
246 ctx.WriteBuffer(store_data); 157 *out_mii_count);
247 }
248 158
249 LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag, 159 R_RETURN(result);
250 output_size, mii_count);
251
252 IPC::ResponseBuilder rb{ctx, 3};
253 rb.Push(result);
254 rb.Push(mii_count);
255 } 160 }
256 161
257 void UpdateLatest1(HLERequestContext& ctx) { 162 Result UpdateLatest1(Out<StoreData> out_store_data, StoreData& store_data,
258 IPC::RequestParser rp{ctx}; 163 SourceFlag source_flag) {
259 const auto store_data{rp.PopRaw<StoreData>()};
260 const auto source_flag{rp.PopRaw<SourceFlag>()};
261
262 LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); 164 LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
165 R_UNLESS(is_system, ResultPermissionDenied);
263 166
264 Result result = ResultSuccess; 167 R_RETURN(manager->UpdateLatest(metadata, *out_store_data, store_data, source_flag));
265 if (!is_system) {
266 result = ResultPermissionDenied;
267 }
268
269 StoreData new_store_data{};
270 if (result.IsSuccess()) {
271 result = manager->UpdateLatest(metadata, new_store_data, store_data, source_flag);
272 }
273
274 if (result.IsFailure()) {
275 IPC::ResponseBuilder rb{ctx, 2};
276 rb.Push(result);
277 return;
278 }
279
280 IPC::ResponseBuilder rb{ctx, 2 + sizeof(StoreData) / sizeof(u32)};
281 rb.Push(ResultSuccess);
282 rb.PushRaw<StoreData>(new_store_data);
283 } 168 }
284 169
285 void FindIndex(HLERequestContext& ctx) { 170 Result FindIndex(Out<s32> out_index, Common::UUID create_id, bool is_special) {
286 IPC::RequestParser rp{ctx};
287 const auto create_id{rp.PopRaw<Common::UUID>()};
288 const auto is_special{rp.PopRaw<bool>()};
289
290 LOG_INFO(Service_Mii, "called with create_id={}, is_special={}", 171 LOG_INFO(Service_Mii, "called with create_id={}, is_special={}",
291 create_id.FormattedString(), is_special); 172 create_id.FormattedString(), is_special);
292 173
293 const s32 index = manager->FindIndex(create_id, is_special); 174 *out_index = manager->FindIndex(create_id, is_special);
294 175
295 IPC::ResponseBuilder rb{ctx, 3}; 176 R_SUCCEED();
296 rb.Push(ResultSuccess);
297 rb.Push(index);
298 } 177 }
299 178
300 void Move(HLERequestContext& ctx) { 179 Result Move(Common::UUID create_id, s32 new_index) {
301 IPC::RequestParser rp{ctx};
302 const auto create_id{rp.PopRaw<Common::UUID>()};
303 const auto new_index{rp.PopRaw<s32>()};
304
305 LOG_INFO(Service_Mii, "called with create_id={}, new_index={}", create_id.FormattedString(), 180 LOG_INFO(Service_Mii, "called with create_id={}, new_index={}", create_id.FormattedString(),
306 new_index); 181 new_index);
182 R_UNLESS(is_system, ResultPermissionDenied);
307 183
308 Result result = ResultSuccess; 184 const u32 count = manager->GetCount(metadata, SourceFlag::Database);
309 if (!is_system) {
310 result = ResultPermissionDenied;
311 }
312 185
313 if (result.IsSuccess()) { 186 R_UNLESS(new_index >= 0 && new_index < static_cast<s32>(count), ResultInvalidArgument);
314 const u32 count = manager->GetCount(metadata, SourceFlag::Database);
315 if (new_index < 0 || new_index >= static_cast<s32>(count)) {
316 result = ResultInvalidArgument;
317 }
318 }
319 187
320 if (result.IsSuccess()) { 188 R_RETURN(manager->Move(metadata, new_index, create_id));
321 result = manager->Move(metadata, new_index, create_id);
322 }
323
324 IPC::ResponseBuilder rb{ctx, 2};
325 rb.Push(result);
326 } 189 }
327 190
328 void AddOrReplace(HLERequestContext& ctx) { 191 Result AddOrReplace(StoreData& store_data) {
329 IPC::RequestParser rp{ctx};
330 const auto store_data{rp.PopRaw<StoreData>()};
331
332 LOG_INFO(Service_Mii, "called"); 192 LOG_INFO(Service_Mii, "called");
193 R_UNLESS(is_system, ResultPermissionDenied);
333 194
334 Result result = ResultSuccess; 195 const auto result = manager->AddOrReplace(metadata, store_data);
335
336 if (!is_system) {
337 result = ResultPermissionDenied;
338 }
339 196
340 if (result.IsSuccess()) { 197 R_RETURN(result);
341 result = manager->AddOrReplace(metadata, store_data);
342 }
343
344 IPC::ResponseBuilder rb{ctx, 2};
345 rb.Push(result);
346 } 198 }
347 199
348 void Delete(HLERequestContext& ctx) { 200 Result Delete(Common::UUID create_id) {
349 IPC::RequestParser rp{ctx};
350 const auto create_id{rp.PopRaw<Common::UUID>()};
351
352 LOG_INFO(Service_Mii, "called, create_id={}", create_id.FormattedString()); 201 LOG_INFO(Service_Mii, "called, create_id={}", create_id.FormattedString());
202 R_UNLESS(is_system, ResultPermissionDenied);
353 203
354 Result result = ResultSuccess; 204 R_RETURN(manager->Delete(metadata, create_id));
355
356 if (!is_system) {
357 result = ResultPermissionDenied;
358 }
359
360 if (result.IsSuccess()) {
361 result = manager->Delete(metadata, create_id);
362 }
363
364 IPC::ResponseBuilder rb{ctx, 2};
365 rb.Push(result);
366 } 205 }
367 206
368 void DestroyFile(HLERequestContext& ctx) { 207 Result DestroyFile() {
369 // This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled"); 208 bool is_db_test_mode_enabled{};
370 const bool is_db_test_mode_enabled = false; 209 m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
371 210
372 LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); 211 LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
212 R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
373 213
374 Result result = ResultSuccess; 214 R_RETURN(manager->DestroyFile(metadata));
375
376 if (!is_db_test_mode_enabled) {
377 result = ResultTestModeOnly;
378 }
379
380 if (result.IsSuccess()) {
381 result = manager->DestroyFile(metadata);
382 }
383
384 IPC::ResponseBuilder rb{ctx, 2};
385 rb.Push(result);
386 } 215 }
387 216
388 void DeleteFile(HLERequestContext& ctx) { 217 Result DeleteFile() {
389 // This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled"); 218 bool is_db_test_mode_enabled{};
390 const bool is_db_test_mode_enabled = false; 219 m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
391 220
392 LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); 221 LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
222 R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
393 223
394 Result result = ResultSuccess; 224 R_RETURN(manager->DeleteFile());
395
396 if (!is_db_test_mode_enabled) {
397 result = ResultTestModeOnly;
398 }
399
400 if (result.IsSuccess()) {
401 result = manager->DeleteFile();
402 }
403
404 IPC::ResponseBuilder rb{ctx, 2};
405 rb.Push(result);
406 } 225 }
407 226
408 void Format(HLERequestContext& ctx) { 227 Result Format() {
409 // This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled"); 228 bool is_db_test_mode_enabled{};
410 const bool is_db_test_mode_enabled = false; 229 m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
411 230
412 LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); 231 LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
232 R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
413 233
414 Result result = ResultSuccess; 234 R_RETURN(manager->Format(metadata));
415
416 if (!is_db_test_mode_enabled) {
417 result = ResultTestModeOnly;
418 }
419
420 if (result.IsSuccess()) {
421 result = manager->Format(metadata);
422 }
423
424 IPC::ResponseBuilder rb{ctx, 2};
425 rb.Push(result);
426 } 235 }
427 236
428 void IsBrokenDatabaseWithClearFlag(HLERequestContext& ctx) { 237 Result IsBrokenDatabaseWithClearFlag(Out<bool> out_is_broken_with_clear_flag) {
429 LOG_DEBUG(Service_Mii, "called"); 238 LOG_DEBUG(Service_Mii, "called");
239 R_UNLESS(is_system, ResultPermissionDenied);
430 240
431 bool is_broken_with_clear_flag = false; 241 *out_is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata);
432 Result result = ResultSuccess;
433 242
434 if (!is_system) { 243 R_SUCCEED();
435 result = ResultPermissionDenied;
436 }
437
438 if (result.IsSuccess()) {
439 is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata);
440 }
441
442 IPC::ResponseBuilder rb{ctx, 3};
443 rb.Push(result);
444 rb.Push<u8>(is_broken_with_clear_flag);
445 } 244 }
446 245
447 void GetIndex(HLERequestContext& ctx) { 246 Result GetIndex(Out<s32> out_index, CharInfo& char_info) {
448 IPC::RequestParser rp{ctx};
449 const auto info{rp.PopRaw<CharInfo>()};
450
451 LOG_DEBUG(Service_Mii, "called"); 247 LOG_DEBUG(Service_Mii, "called");
452 248
453 s32 index{}; 249 R_RETURN(manager->GetIndex(metadata, char_info, *out_index));
454 const auto result = manager->GetIndex(metadata, info, index);
455
456 IPC::ResponseBuilder rb{ctx, 3};
457 rb.Push(result);
458 rb.Push(index);
459 } 250 }
460 251
461 void SetInterfaceVersion(HLERequestContext& ctx) { 252 Result SetInterfaceVersion(u32 interface_version) {
462 IPC::RequestParser rp{ctx};
463 const auto interface_version{rp.PopRaw<u32>()};
464
465 LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version); 253 LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version);
466 254
467 manager->SetInterfaceVersion(metadata, interface_version); 255 manager->SetInterfaceVersion(metadata, interface_version);
468 256
469 IPC::ResponseBuilder rb{ctx, 2}; 257 R_SUCCEED();
470 rb.Push(ResultSuccess);
471 } 258 }
472 259
473 void Convert(HLERequestContext& ctx) { 260 Result Convert(Out<CharInfo> out_char_info, Ver3StoreData& mii_v3) {
474 IPC::RequestParser rp{ctx};
475 const auto mii_v3{rp.PopRaw<Ver3StoreData>()};
476
477 LOG_INFO(Service_Mii, "called"); 261 LOG_INFO(Service_Mii, "called");
478 262
479 CharInfo char_info{}; 263 R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3));
480 const auto result = manager->ConvertV3ToCharInfo(char_info, mii_v3);
481
482 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
483 rb.Push(result);
484 rb.PushRaw<CharInfo>(char_info);
485 } 264 }
486 265
487 void ConvertCoreDataToCharInfo(HLERequestContext& ctx) { 266 Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, CoreData& core_data) {
488 IPC::RequestParser rp{ctx};
489 const auto core_data{rp.PopRaw<CoreData>()};
490
491 LOG_INFO(Service_Mii, "called"); 267 LOG_INFO(Service_Mii, "called");
492 268
493 CharInfo char_info{}; 269 R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data));
494 const auto result = manager->ConvertCoreDataToCharInfo(char_info, core_data);
495
496 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
497 rb.Push(result);
498 rb.PushRaw<CharInfo>(char_info);
499 } 270 }
500 271
501 void ConvertCharInfoToCoreData(HLERequestContext& ctx) { 272 Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, CharInfo& char_info) {
502 IPC::RequestParser rp{ctx};
503 const auto char_info{rp.PopRaw<CharInfo>()};
504
505 LOG_INFO(Service_Mii, "called"); 273 LOG_INFO(Service_Mii, "called");
506 274
507 CoreData core_data{}; 275 R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info));
508 const auto result = manager->ConvertCharInfoToCoreData(core_data, char_info);
509
510 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CoreData) / sizeof(u32)};
511 rb.Push(result);
512 rb.PushRaw<CoreData>(core_data);
513 } 276 }
514 277
515 void Append(HLERequestContext& ctx) { 278 Result Append(CharInfo& char_info) {
516 IPC::RequestParser rp{ctx};
517 const auto char_info{rp.PopRaw<CharInfo>()};
518
519 LOG_INFO(Service_Mii, "called"); 279 LOG_INFO(Service_Mii, "called");
520 280
521 const auto result = manager->Append(metadata, char_info); 281 R_RETURN(manager->Append(metadata, char_info));
522
523 IPC::ResponseBuilder rb{ctx, 2};
524 rb.Push(result);
525 } 282 }
526 283
527 std::shared_ptr<MiiManager> manager = nullptr; 284 std::shared_ptr<MiiManager> manager = nullptr;
528 DatabaseSessionMetadata metadata{}; 285 DatabaseSessionMetadata metadata{};
529 bool is_system{}; 286 bool is_system{};
287
288 std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
530}; 289};
531 290
532MiiDBModule::MiiDBModule(Core::System& system_, const char* name_, 291IStaticService::IStaticService(Core::System& system_, const char* name_,
533 std::shared_ptr<MiiManager> mii_manager, bool is_system_) 292 std::shared_ptr<MiiManager> mii_manager, bool is_system_)
534 : ServiceFramework{system_, name_}, manager{mii_manager}, is_system{is_system_} { 293 : ServiceFramework{system_, name_}, manager{mii_manager}, is_system{is_system_} {
535 // clang-format off 294 // clang-format off
536 static const FunctionInfo functions[] = { 295 static const FunctionInfo functions[] = {
537 {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, 296 {0, D<&IStaticService::GetDatabaseService>, "GetDatabaseService"},
538 }; 297 };
539 // clang-format on 298 // clang-format on
540 299
541 RegisterHandlers(functions); 300 RegisterHandlers(functions);
542
543 if (manager == nullptr) {
544 manager = std::make_shared<MiiManager>();
545 }
546} 301}
547 302
548MiiDBModule::~MiiDBModule() = default; 303IStaticService::~IStaticService() = default;
549
550void MiiDBModule::GetDatabaseService(HLERequestContext& ctx) {
551 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
552 rb.Push(ResultSuccess);
553 rb.PushIpcInterface<IDatabaseService>(system, manager, is_system);
554 304
305Result IStaticService::GetDatabaseService(
306 Out<SharedPointer<IDatabaseService>> out_database_service) {
555 LOG_DEBUG(Service_Mii, "called"); 307 LOG_DEBUG(Service_Mii, "called");
308
309 *out_database_service = std::make_shared<IDatabaseService>(system, manager, is_system);
310
311 R_SUCCEED();
556} 312}
557 313
558std::shared_ptr<MiiManager> MiiDBModule::GetMiiManager() { 314std::shared_ptr<MiiManager> IStaticService::GetMiiManager() {
559 return manager; 315 return manager;
560} 316}
561 317
562class MiiImg final : public ServiceFramework<MiiImg> { 318class IImageDatabaseService final : public ServiceFramework<IImageDatabaseService> {
563public: 319public:
564 explicit MiiImg(Core::System& system_) : ServiceFramework{system_, "miiimg"} { 320 explicit IImageDatabaseService(Core::System& system_) : ServiceFramework{system_, "miiimg"} {
565 // clang-format off 321 // clang-format off
566 static const FunctionInfo functions[] = { 322 static const FunctionInfo functions[] = {
567 {0, &MiiImg::Initialize, "Initialize"}, 323 {0, D<&IImageDatabaseService::Initialize>, "Initialize"},
568 {10, nullptr, "Reload"}, 324 {10, nullptr, "Reload"},
569 {11, &MiiImg::GetCount, "GetCount"}, 325 {11, D<&IImageDatabaseService::GetCount>, "GetCount"},
570 {12, nullptr, "IsEmpty"}, 326 {12, nullptr, "IsEmpty"},
571 {13, nullptr, "IsFull"}, 327 {13, nullptr, "IsFull"},
572 {14, nullptr, "GetAttribute"}, 328 {14, nullptr, "GetAttribute"},
@@ -585,31 +341,30 @@ public:
585 } 341 }
586 342
587private: 343private:
588 void Initialize(HLERequestContext& ctx) { 344 Result Initialize() {
589 LOG_INFO(Service_Mii, "called"); 345 LOG_INFO(Service_Mii, "called");
590 346
591 IPC::ResponseBuilder rb{ctx, 2}; 347 R_SUCCEED();
592 rb.Push(ResultSuccess);
593 } 348 }
594 349
595 void GetCount(HLERequestContext& ctx) { 350 Result GetCount(Out<u32> out_count) {
596 LOG_DEBUG(Service_Mii, "called"); 351 LOG_DEBUG(Service_Mii, "called");
597 352
598 IPC::ResponseBuilder rb{ctx, 3}; 353 *out_count = 0;
599 rb.Push(ResultSuccess); 354
600 rb.Push(0); 355 R_SUCCEED();
601 } 356 }
602}; 357};
603 358
604void LoopProcess(Core::System& system) { 359void LoopProcess(Core::System& system) {
605 auto server_manager = std::make_unique<ServerManager>(system); 360 auto server_manager = std::make_unique<ServerManager>(system);
606 std::shared_ptr<MiiManager> manager = nullptr; 361 std::shared_ptr<MiiManager> manager = std::make_shared<MiiManager>();
607 362
608 server_manager->RegisterNamedService( 363 server_manager->RegisterNamedService(
609 "mii:e", std::make_shared<MiiDBModule>(system, "mii:e", manager, true)); 364 "mii:e", std::make_shared<IStaticService>(system, "mii:e", manager, true));
610 server_manager->RegisterNamedService( 365 server_manager->RegisterNamedService(
611 "mii:u", std::make_shared<MiiDBModule>(system, "mii:u", manager, false)); 366 "mii:u", std::make_shared<IStaticService>(system, "mii:u", manager, false));
612 server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system)); 367 server_manager->RegisterNamedService("miiimg", std::make_shared<IImageDatabaseService>(system));
613 ServerManager::RunServer(std::move(server_manager)); 368 ServerManager::RunServer(std::move(server_manager));
614} 369}
615 370
diff --git a/src/core/hle/service/mii/mii.h b/src/core/hle/service/mii/mii.h
index 9aa4426f6..8683ac1a5 100644
--- a/src/core/hle/service/mii/mii.h
+++ b/src/core/hle/service/mii/mii.h
@@ -3,7 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/service.h" 6#include "core/hle/service/cmif_types.h"
7 7
8namespace Core { 8namespace Core {
9class System; 9class System;
@@ -11,19 +11,20 @@ class System;
11 11
12namespace Service::Mii { 12namespace Service::Mii {
13class MiiManager; 13class MiiManager;
14class IDatabaseService;
14 15
15class MiiDBModule final : public ServiceFramework<MiiDBModule> { 16class IStaticService final : public ServiceFramework<IStaticService> {
16public: 17public:
17 explicit MiiDBModule(Core::System& system_, const char* name_, 18 explicit IStaticService(Core::System& system_, const char* name_,
18 std::shared_ptr<MiiManager> mii_manager, bool is_system_); 19 std::shared_ptr<MiiManager> mii_manager, bool is_system_);
19 ~MiiDBModule() override; 20 ~IStaticService() override;
20 21
21 std::shared_ptr<MiiManager> GetMiiManager(); 22 std::shared_ptr<MiiManager> GetMiiManager();
22 23
23private: 24private:
24 void GetDatabaseService(HLERequestContext& ctx); 25 Result GetDatabaseService(Out<SharedPointer<IDatabaseService>> out_database_service);
25 26
26 std::shared_ptr<MiiManager> manager = nullptr; 27 std::shared_ptr<MiiManager> manager{nullptr};
27 bool is_system{}; 28 bool is_system{};
28}; 29};
29 30
diff --git a/src/core/hle/service/set/setting_formats/system_settings.cpp b/src/core/hle/service/set/setting_formats/system_settings.cpp
index 88a305f03..7231ff78e 100644
--- a/src/core/hle/service/set/setting_formats/system_settings.cpp
+++ b/src/core/hle/service/set/setting_formats/system_settings.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/settings.h"
4#include "core/hle/service/set/setting_formats/system_settings.h" 5#include "core/hle/service/set/setting_formats/system_settings.h"
5 6
6namespace Service::Set { 7namespace Service::Set {
@@ -44,7 +45,7 @@ SystemSettings DefaultSystemSettings() {
44 .console_sleep_plan = ConsoleSleepPlan::Sleep1Hour, 45 .console_sleep_plan = ConsoleSleepPlan::Sleep1Hour,
45 }; 46 };
46 47
47 settings.device_time_zone_location_name = {"UTC"}; 48 settings.device_time_zone_location_name = Service::PSC::Time::LocationName{"UTC"};
48 settings.user_system_clock_automatic_correction_enabled = true; 49 settings.user_system_clock_automatic_correction_enabled = true;
49 50
50 settings.primary_album_storage = PrimaryAlbumStorage::SdCard; 51 settings.primary_album_storage = PrimaryAlbumStorage::SdCard;
@@ -52,6 +53,17 @@ SystemSettings DefaultSystemSettings() {
52 settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0; 53 settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0;
53 settings.vibration_master_volume = 1.0f; 54 settings.vibration_master_volume = 1.0f;
54 55
56 const auto language_code =
57 available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
58 const auto key_code =
59 std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
60 [=](const auto& element) { return element.first == language_code; });
61
62 settings.keyboard_layout = KeyboardLayout::EnglishUs;
63 if (key_code != language_to_layout.end()) {
64 settings.keyboard_layout = key_code->second;
65 }
66
55 return settings; 67 return settings;
56} 68}
57 69
diff --git a/src/core/hle/service/set/setting_formats/system_settings.h b/src/core/hle/service/set/setting_formats/system_settings.h
index af5929fa9..ebc373da5 100644
--- a/src/core/hle/service/set/setting_formats/system_settings.h
+++ b/src/core/hle/service/set/setting_formats/system_settings.h
@@ -213,10 +213,9 @@ struct SystemSettings {
213 // nn::settings::system::AudioVolume 213 // nn::settings::system::AudioVolume
214 std::array<u8, 0x8> audio_volume_type0; 214 std::array<u8, 0x8> audio_volume_type0;
215 std::array<u8, 0x8> audio_volume_type1; 215 std::array<u8, 0x8> audio_volume_type1;
216 // nn::settings::system::AudioOutputMode 216 AudioOutputMode audio_output_mode_hdmi;
217 s32 audio_output_mode_type0; 217 AudioOutputMode audio_output_mode_speaker;
218 s32 audio_output_mode_type1; 218 AudioOutputMode audio_output_mode_headphone;
219 s32 audio_output_mode_type2;
220 bool force_mute_on_headphone_removed; 219 bool force_mute_on_headphone_removed;
221 INSERT_PADDING_BYTES(0x3); 220 INSERT_PADDING_BYTES(0x3);
222 s32 headphone_volume_warning_count; 221 s32 headphone_volume_warning_count;
@@ -224,9 +223,8 @@ struct SystemSettings {
224 INSERT_PADDING_BYTES(0x3); 223 INSERT_PADDING_BYTES(0x3);
225 // nn::settings::system::AudioVolume 224 // nn::settings::system::AudioVolume
226 std::array<u8, 0x8> audio_volume_type2; 225 std::array<u8, 0x8> audio_volume_type2;
227 // nn::settings::system::AudioOutputMode 226 AudioOutputMode audio_output_mode_type3;
228 s32 audio_output_mode_type3; 227 AudioOutputMode audio_output_mode_type4;
229 s32 audio_output_mode_type4;
230 bool hearing_protection_safeguard_flag; 228 bool hearing_protection_safeguard_flag;
231 INSERT_PADDING_BYTES(0x3); 229 INSERT_PADDING_BYTES(0x3);
232 INSERT_PADDING_BYTES(0x4); // Reserved 230 INSERT_PADDING_BYTES(0x4); // Reserved
diff --git a/src/core/hle/service/set/settings_types.h b/src/core/hle/service/set/settings_types.h
index 968425319..ceb85b82a 100644
--- a/src/core/hle/service/set/settings_types.h
+++ b/src/core/hle/service/set/settings_types.h
@@ -23,9 +23,12 @@ enum class AudioOutputMode : u32 {
23 23
24/// This is nn::settings::system::AudioOutputModeTarget 24/// This is nn::settings::system::AudioOutputModeTarget
25enum class AudioOutputModeTarget : u32 { 25enum class AudioOutputModeTarget : u32 {
26 None,
26 Hdmi, 27 Hdmi,
27 Speaker, 28 Speaker,
28 Headphone, 29 Headphone,
30 Type3,
31 Type4,
29}; 32};
30 33
31/// This is nn::settings::system::AudioVolumeTarget 34/// This is nn::settings::system::AudioVolumeTarget
@@ -367,6 +370,12 @@ struct AccountNotificationSettings {
367static_assert(sizeof(AccountNotificationSettings) == 0x18, 370static_assert(sizeof(AccountNotificationSettings) == 0x18,
368 "AccountNotificationSettings is an invalid size"); 371 "AccountNotificationSettings is an invalid size");
369 372
373/// This is nn::settings::factory::BatteryLot
374struct BatteryLot {
375 std::array<char, 0x18> lot_number;
376};
377static_assert(sizeof(BatteryLot) == 0x18, "BatteryLot is an invalid size");
378
370/// This is nn::settings::system::EulaVersion 379/// This is nn::settings::system::EulaVersion
371struct EulaVersion { 380struct EulaVersion {
372 u32 version; 381 u32 version;
@@ -436,6 +445,12 @@ struct NotificationSettings {
436}; 445};
437static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size"); 446static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size");
438 447
448/// This is nn::settings::factory::SerialNumber
449struct SerialNumber {
450 std::array<char, 0x18> serial_number;
451};
452static_assert(sizeof(SerialNumber) == 0x18, "SerialNumber is an invalid size");
453
439/// This is nn::settings::system::SleepSettings 454/// This is nn::settings::system::SleepSettings
440struct SleepSettings { 455struct SleepSettings {
441 SleepFlag flags; 456 SleepFlag flags;
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp
index e907b57b6..100cb2db4 100644
--- a/src/core/hle/service/set/system_settings_server.cpp
+++ b/src/core/hle/service/set/system_settings_server.cpp
@@ -25,7 +25,7 @@
25namespace Service::Set { 25namespace Service::Set {
26 26
27namespace { 27namespace {
28constexpr u32 SETTINGS_VERSION{1u}; 28constexpr u32 SETTINGS_VERSION{2u};
29constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); 29constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't');
30struct SettingsHeader { 30struct SettingsHeader {
31 u64 magic; 31 u64 magic;
@@ -131,10 +131,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
131 {40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"}, 131 {40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"},
132 {41, nullptr, "GetEdid"}, 132 {41, nullptr, "GetEdid"},
133 {42, nullptr, "SetEdid"}, 133 {42, nullptr, "SetEdid"},
134 {43, nullptr, "GetAudioOutputMode"}, 134 {43, &ISystemSettingsServer::GetAudioOutputMode, "GetAudioOutputMode"},
135 {44, nullptr, "SetAudioOutputMode"}, 135 {44, &ISystemSettingsServer::SetAudioOutputMode, "SetAudioOutputMode"},
136 {45, &ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved, "IsForceMuteOnHeadphoneRemoved"}, 136 {45, &ISystemSettingsServer::GetSpeakerAutoMuteFlag , "GetSpeakerAutoMuteFlag"},
137 {46, &ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved, "SetForceMuteOnHeadphoneRemoved"}, 137 {46, &ISystemSettingsServer::SetSpeakerAutoMuteFlag , "SetSpeakerAutoMuteFlag"},
138 {47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"}, 138 {47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"},
139 {48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"}, 139 {48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"},
140 {49, nullptr, "GetDataDeletionSettings"}, 140 {49, nullptr, "GetDataDeletionSettings"},
@@ -155,8 +155,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
155 {64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"}, 155 {64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"},
156 {65, nullptr, "GetUsb30EnableFlag"}, 156 {65, nullptr, "GetUsb30EnableFlag"},
157 {66, nullptr, "SetUsb30EnableFlag"}, 157 {66, nullptr, "SetUsb30EnableFlag"},
158 {67, nullptr, "GetBatteryLot"}, 158 {67, &ISystemSettingsServer::GetBatteryLot, "GetBatteryLot"},
159 {68, nullptr, "GetSerialNumber"}, 159 {68, &ISystemSettingsServer::GetSerialNumber, "GetSerialNumber"},
160 {69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"}, 160 {69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"},
161 {70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"}, 161 {70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"},
162 {71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"}, 162 {71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"},
@@ -184,11 +184,11 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
184 {93, nullptr, "AcquireFatalDirtyFlagEventHandle"}, 184 {93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
185 {94, nullptr, "GetFatalDirtyFlags"}, 185 {94, nullptr, "GetFatalDirtyFlags"},
186 {95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"}, 186 {95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
187 {96, nullptr, "SetAutoUpdateEnableFlag"}, 187 {96, &ISystemSettingsServer::SetAutoUpdateEnableFlag, "SetAutoUpdateEnableFlag"},
188 {97, nullptr, "GetNxControllerSettings"}, 188 {97, nullptr, "GetNxControllerSettings"},
189 {98, nullptr, "SetNxControllerSettings"}, 189 {98, nullptr, "SetNxControllerSettings"},
190 {99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"}, 190 {99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
191 {100, nullptr, "SetBatteryPercentageFlag"}, 191 {100, &ISystemSettingsServer::SetBatteryPercentageFlag, "SetBatteryPercentageFlag"},
192 {101, nullptr, "GetExternalRtcResetFlag"}, 192 {101, nullptr, "GetExternalRtcResetFlag"},
193 {102, nullptr, "SetExternalRtcResetFlag"}, 193 {102, nullptr, "SetExternalRtcResetFlag"},
194 {103, nullptr, "GetUsbFullKeyEnableFlag"}, 194 {103, nullptr, "GetUsbFullKeyEnableFlag"},
@@ -208,12 +208,12 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
208 {117, nullptr, "GetHeadphoneVolumeUpdateFlag"}, 208 {117, nullptr, "GetHeadphoneVolumeUpdateFlag"},
209 {118, nullptr, "SetHeadphoneVolumeUpdateFlag"}, 209 {118, nullptr, "SetHeadphoneVolumeUpdateFlag"},
210 {119, nullptr, "NeedsToUpdateHeadphoneVolume"}, 210 {119, nullptr, "NeedsToUpdateHeadphoneVolume"},
211 {120, nullptr, "GetPushNotificationActivityModeOnSleep"}, 211 {120, &ISystemSettingsServer::GetPushNotificationActivityModeOnSleep, "GetPushNotificationActivityModeOnSleep"},
212 {121, nullptr, "SetPushNotificationActivityModeOnSleep"}, 212 {121, &ISystemSettingsServer::SetPushNotificationActivityModeOnSleep, "SetPushNotificationActivityModeOnSleep"},
213 {122, nullptr, "GetServiceDiscoveryControlSettings"}, 213 {122, nullptr, "GetServiceDiscoveryControlSettings"},
214 {123, nullptr, "SetServiceDiscoveryControlSettings"}, 214 {123, nullptr, "SetServiceDiscoveryControlSettings"},
215 {124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"}, 215 {124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
216 {125, nullptr, "SetErrorReportSharePermission"}, 216 {125, &ISystemSettingsServer::SetErrorReportSharePermission, "SetErrorReportSharePermission"},
217 {126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"}, 217 {126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
218 {127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"}, 218 {127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
219 {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"}, 219 {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
@@ -225,7 +225,7 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
225 {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"}, 225 {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
226 {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"}, 226 {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
227 {136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"}, 227 {136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"},
228 {137, nullptr, "SetKeyboardLayout"}, 228 {137, &ISystemSettingsServer::SetKeyboardLayout, "SetKeyboardLayout"},
229 {138, nullptr, "GetWebInspectorFlag"}, 229 {138, nullptr, "GetWebInspectorFlag"},
230 {139, nullptr, "GetAllowedSslHosts"}, 230 {139, nullptr, "GetAllowedSslHosts"},
231 {140, nullptr, "GetHostFsMountPoint"}, 231 {140, nullptr, "GetHostFsMountPoint"},
@@ -291,8 +291,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
291 {200, nullptr, "SetButtonConfigRegisteredSettings"}, 291 {200, nullptr, "SetButtonConfigRegisteredSettings"},
292 {201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"}, 292 {201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"},
293 {202, nullptr, "SetFieldTestingFlag"}, 293 {202, nullptr, "SetFieldTestingFlag"},
294 {203, nullptr, "GetPanelCrcMode"}, 294 {203, &ISystemSettingsServer::GetPanelCrcMode, "GetPanelCrcMode"},
295 {204, nullptr, "SetPanelCrcMode"}, 295 {204, &ISystemSettingsServer::SetPanelCrcMode, "SetPanelCrcMode"},
296 {205, nullptr, "GetNxControllerSettingsEx"}, 296 {205, nullptr, "GetNxControllerSettingsEx"},
297 {206, nullptr, "SetNxControllerSettingsEx"}, 297 {206, nullptr, "SetNxControllerSettingsEx"},
298 {207, nullptr, "GetHearingProtectionSafeguardFlag"}, 298 {207, nullptr, "GetHearingProtectionSafeguardFlag"},
@@ -349,7 +349,7 @@ bool ISystemSettingsServer::LoadSettingsFile(std::filesystem::path& path, auto&&
349 } 349 }
350 SettingsHeader hdr{}; 350 SettingsHeader hdr{};
351 file.read(reinterpret_cast<char*>(&hdr), sizeof(hdr)); 351 file.read(reinterpret_cast<char*>(&hdr), sizeof(hdr));
352 return hdr.magic == SETTINGS_MAGIC && hdr.version == SETTINGS_VERSION; 352 return hdr.magic == SETTINGS_MAGIC && hdr.version >= SETTINGS_VERSION;
353 }; 353 };
354 354
355 if (!exists || !file_size_ok) { 355 if (!exists || !file_size_ok) {
@@ -390,7 +390,7 @@ bool ISystemSettingsServer::StoreSettingsFile(std::filesystem::path& path, auto&
390 } 390 }
391 391
392 auto settings_base = path / "settings"; 392 auto settings_base = path / "settings";
393 auto settings_tmp_file = settings_base; 393 std::filesystem::path settings_tmp_file = settings_base;
394 settings_tmp_file = settings_tmp_file.replace_extension("tmp"); 394 settings_tmp_file = settings_tmp_file.replace_extension("tmp");
395 std::ofstream file(settings_tmp_file, std::ios::binary | std::ios::out); 395 std::ofstream file(settings_tmp_file, std::ios::binary | std::ios::out);
396 if (!file.is_open()) { 396 if (!file.is_open()) {
@@ -722,6 +722,9 @@ static Settings GetSettings() {
722 ret["hid_debug"]["disabled_features_per_id"] = std::vector<u8>(0xa8); 722 ret["hid_debug"]["disabled_features_per_id"] = std::vector<u8>(0xa8);
723 ret["hid_debug"]["touch_firmware_auto_update_disabled"] = ToBytes(bool{false}); 723 ret["hid_debug"]["touch_firmware_auto_update_disabled"] = ToBytes(bool{false});
724 724
725 // Mii
726 ret["mii"]["is_db_test_mode_enabled"] = ToBytes(bool{false});
727
725 // Settings 728 // Settings
726 ret["settings_debug"]["is_debug_mode_enabled"] = ToBytes(bool{false}); 729 ret["settings_debug"]["is_debug_mode_enabled"] = ToBytes(bool{false});
727 730
@@ -814,7 +817,34 @@ void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) {
814 rb.Push(ResultSuccess); 817 rb.Push(ResultSuccess);
815} 818}
816 819
817void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) { 820void ISystemSettingsServer::GetAudioOutputMode(HLERequestContext& ctx) {
821 IPC::RequestParser rp{ctx};
822 const auto target{rp.PopEnum<AudioOutputModeTarget>()};
823
824 AudioOutputMode output_mode{};
825 const auto result = GetAudioOutputMode(output_mode, target);
826
827 LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
828
829 IPC::ResponseBuilder rb{ctx, 3};
830 rb.Push(result);
831 rb.PushEnum(output_mode);
832}
833
834void ISystemSettingsServer::SetAudioOutputMode(HLERequestContext& ctx) {
835 IPC::RequestParser rp{ctx};
836 const auto target{rp.PopEnum<AudioOutputModeTarget>()};
837 const auto output_mode{rp.PopEnum<AudioOutputMode>()};
838
839 const auto result = SetAudioOutputMode(target, output_mode);
840
841 LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
842
843 IPC::ResponseBuilder rb{ctx, 2};
844 rb.Push(result);
845}
846
847void ISystemSettingsServer::GetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
818 LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}", 848 LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}",
819 m_system_settings.force_mute_on_headphone_removed); 849 m_system_settings.force_mute_on_headphone_removed);
820 850
@@ -823,7 +853,7 @@ void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx
823 rb.PushRaw(m_system_settings.force_mute_on_headphone_removed); 853 rb.PushRaw(m_system_settings.force_mute_on_headphone_removed);
824} 854}
825 855
826void ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) { 856void ISystemSettingsServer::SetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
827 IPC::RequestParser rp{ctx}; 857 IPC::RequestParser rp{ctx};
828 m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>(); 858 m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>();
829 SetSaveNeeded(); 859 SetSaveNeeded();
@@ -966,6 +996,26 @@ void ISystemSettingsServer::SetPrimaryAlbumStorage(HLERequestContext& ctx) {
966 rb.Push(ResultSuccess); 996 rb.Push(ResultSuccess);
967} 997}
968 998
999void ISystemSettingsServer::GetBatteryLot(HLERequestContext& ctx) {
1000 BatteryLot battery_lot = {"YUZUEMULATOR123456789"};
1001
1002 LOG_INFO(Service_SET, "called");
1003
1004 IPC::ResponseBuilder rb{ctx, 8};
1005 rb.Push(ResultSuccess);
1006 rb.PushRaw(battery_lot);
1007}
1008
1009void ISystemSettingsServer::GetSerialNumber(HLERequestContext& ctx) {
1010 SerialNumber console_serial = {"YUZ10012345678"};
1011
1012 LOG_INFO(Service_SET, "called");
1013
1014 IPC::ResponseBuilder rb{ctx, 8};
1015 rb.Push(ResultSuccess);
1016 rb.PushRaw(console_serial);
1017}
1018
969void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) { 1019void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) {
970 LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag); 1020 LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag);
971 1021
@@ -1129,6 +1179,17 @@ void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
1129 rb.Push(m_system_settings.auto_update_enable_flag); 1179 rb.Push(m_system_settings.auto_update_enable_flag);
1130} 1180}
1131 1181
1182void ISystemSettingsServer::SetAutoUpdateEnableFlag(HLERequestContext& ctx) {
1183 IPC::RequestParser rp{ctx};
1184 m_system_settings.auto_update_enable_flag = rp.Pop<bool>();
1185 SetSaveNeeded();
1186
1187 LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag);
1188
1189 IPC::ResponseBuilder rb{ctx, 2};
1190 rb.Push(ResultSuccess);
1191}
1192
1132void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) { 1193void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
1133 LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}", 1194 LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}",
1134 m_system_settings.battery_percentage_flag); 1195 m_system_settings.battery_percentage_flag);
@@ -1138,6 +1199,18 @@ void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
1138 rb.Push(m_system_settings.battery_percentage_flag); 1199 rb.Push(m_system_settings.battery_percentage_flag);
1139} 1200}
1140 1201
1202void ISystemSettingsServer::SetBatteryPercentageFlag(HLERequestContext& ctx) {
1203 IPC::RequestParser rp{ctx};
1204 m_system_settings.battery_percentage_flag = rp.Pop<bool>();
1205 SetSaveNeeded();
1206
1207 LOG_INFO(Service_SET, "called, battery_percentage_flag={}",
1208 m_system_settings.battery_percentage_flag);
1209
1210 IPC::ResponseBuilder rb{ctx, 2};
1211 rb.Push(ResultSuccess);
1212}
1213
1141void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) { 1214void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) {
1142 LOG_DEBUG(Service_SET, "called."); 1215 LOG_DEBUG(Service_SET, "called.");
1143 1216
@@ -1161,6 +1234,27 @@ void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestConte
1161 rb.Push(offset); 1234 rb.Push(offset);
1162} 1235}
1163 1236
1237void ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
1238 LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
1239 m_system_settings.push_notification_activity_mode_on_sleep);
1240
1241 IPC::ResponseBuilder rb{ctx, 3};
1242 rb.Push(ResultSuccess);
1243 rb.Push(m_system_settings.push_notification_activity_mode_on_sleep);
1244}
1245
1246void ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
1247 IPC::RequestParser rp{ctx};
1248 m_system_settings.push_notification_activity_mode_on_sleep = rp.Pop<s32>();
1249 SetSaveNeeded();
1250
1251 LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
1252 m_system_settings.push_notification_activity_mode_on_sleep);
1253
1254 IPC::ResponseBuilder rb{ctx, 2};
1255 rb.Push(ResultSuccess);
1256}
1257
1164void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) { 1258void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) {
1165 LOG_INFO(Service_SET, "called, error_report_share_permission={}", 1259 LOG_INFO(Service_SET, "called, error_report_share_permission={}",
1166 m_system_settings.error_report_share_permission); 1260 m_system_settings.error_report_share_permission);
@@ -1170,6 +1264,18 @@ void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx
1170 rb.PushEnum(m_system_settings.error_report_share_permission); 1264 rb.PushEnum(m_system_settings.error_report_share_permission);
1171} 1265}
1172 1266
1267void ISystemSettingsServer::SetErrorReportSharePermission(HLERequestContext& ctx) {
1268 IPC::RequestParser rp{ctx};
1269 m_system_settings.error_report_share_permission = rp.PopEnum<ErrorReportSharePermission>();
1270 SetSaveNeeded();
1271
1272 LOG_INFO(Service_SET, "called, error_report_share_permission={}",
1273 m_system_settings.error_report_share_permission);
1274
1275 IPC::ResponseBuilder rb{ctx, 2};
1276 rb.Push(ResultSuccess);
1277}
1278
1173void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) { 1279void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) {
1174 LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag); 1280 LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag);
1175 1281
@@ -1190,22 +1296,22 @@ void ISystemSettingsServer::SetAppletLaunchFlags(HLERequestContext& ctx) {
1190} 1296}
1191 1297
1192void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) { 1298void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) {
1193 const auto language_code = 1299 LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
1194 available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
1195 const auto key_code =
1196 std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
1197 [=](const auto& element) { return element.first == language_code; });
1198
1199 KeyboardLayout selected_keyboard_layout = KeyboardLayout::EnglishUs;
1200 if (key_code != language_to_layout.end()) {
1201 selected_keyboard_layout = key_code->second;
1202 }
1203
1204 LOG_INFO(Service_SET, "called, selected_keyboard_layout={}", selected_keyboard_layout);
1205 1300
1206 IPC::ResponseBuilder rb{ctx, 3}; 1301 IPC::ResponseBuilder rb{ctx, 3};
1207 rb.Push(ResultSuccess); 1302 rb.Push(ResultSuccess);
1208 rb.Push(static_cast<u32>(selected_keyboard_layout)); 1303 rb.Push(static_cast<u32>(m_system_settings.keyboard_layout));
1304}
1305
1306void ISystemSettingsServer::SetKeyboardLayout(HLERequestContext& ctx) {
1307 IPC::RequestParser rp{ctx};
1308 m_system_settings.keyboard_layout = rp.PopRaw<KeyboardLayout>();
1309 SetSaveNeeded();
1310
1311 LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
1312
1313 IPC::ResponseBuilder rb{ctx, 2};
1314 rb.Push(ResultSuccess);
1209} 1315}
1210 1316
1211void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) { 1317void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
@@ -1297,6 +1403,25 @@ void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) {
1297 rb.Push(m_system_settings.field_testing_flag); 1403 rb.Push(m_system_settings.field_testing_flag);
1298} 1404}
1299 1405
1406void ISystemSettingsServer::GetPanelCrcMode(HLERequestContext& ctx) {
1407 LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
1408
1409 IPC::ResponseBuilder rb{ctx, 3};
1410 rb.Push(ResultSuccess);
1411 rb.Push(m_system_settings.panel_crc_mode);
1412}
1413
1414void ISystemSettingsServer::SetPanelCrcMode(HLERequestContext& ctx) {
1415 IPC::RequestParser rp{ctx};
1416 m_system_settings.panel_crc_mode = rp.PopRaw<s32>();
1417 SetSaveNeeded();
1418
1419 LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
1420
1421 IPC::ResponseBuilder rb{ctx, 2};
1422 rb.Push(ResultSuccess);
1423}
1424
1300void ISystemSettingsServer::SetupSettings() { 1425void ISystemSettingsServer::SetupSettings() {
1301 auto system_dir = 1426 auto system_dir =
1302 Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050"; 1427 Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050";
@@ -1387,6 +1512,66 @@ Result ISystemSettingsServer::SetVibrationMasterVolume(f32 volume) {
1387 R_SUCCEED(); 1512 R_SUCCEED();
1388} 1513}
1389 1514
1515Result ISystemSettingsServer::GetAudioOutputMode(AudioOutputMode& out_output_mode,
1516 AudioOutputModeTarget target) const {
1517 switch (target) {
1518 case AudioOutputModeTarget::Hdmi:
1519 out_output_mode = m_system_settings.audio_output_mode_hdmi;
1520 break;
1521 case AudioOutputModeTarget::Speaker:
1522 out_output_mode = m_system_settings.audio_output_mode_speaker;
1523 break;
1524 case AudioOutputModeTarget::Headphone:
1525 out_output_mode = m_system_settings.audio_output_mode_headphone;
1526 break;
1527 case AudioOutputModeTarget::Type3:
1528 out_output_mode = m_system_settings.audio_output_mode_type3;
1529 break;
1530 case AudioOutputModeTarget::Type4:
1531 out_output_mode = m_system_settings.audio_output_mode_type4;
1532 break;
1533 default:
1534 LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
1535 }
1536 R_SUCCEED();
1537}
1538
1539Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target,
1540 AudioOutputMode output_mode) {
1541 switch (target) {
1542 case AudioOutputModeTarget::Hdmi:
1543 m_system_settings.audio_output_mode_hdmi = output_mode;
1544 break;
1545 case AudioOutputModeTarget::Speaker:
1546 m_system_settings.audio_output_mode_speaker = output_mode;
1547 break;
1548 case AudioOutputModeTarget::Headphone:
1549 m_system_settings.audio_output_mode_headphone = output_mode;
1550 break;
1551 case AudioOutputModeTarget::Type3:
1552 m_system_settings.audio_output_mode_type3 = output_mode;
1553 break;
1554 case AudioOutputModeTarget::Type4:
1555 m_system_settings.audio_output_mode_type4 = output_mode;
1556 break;
1557 default:
1558 LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
1559 }
1560 SetSaveNeeded();
1561 R_SUCCEED();
1562}
1563
1564Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(bool& is_auto_mute) const {
1565 is_auto_mute = m_system_settings.force_mute_on_headphone_removed;
1566 R_SUCCEED();
1567}
1568
1569Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool is_auto_mute) {
1570 m_system_settings.force_mute_on_headphone_removed = is_auto_mute;
1571 SetSaveNeeded();
1572 R_SUCCEED();
1573}
1574
1390Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const { 1575Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const {
1391 out_id = m_private_settings.external_clock_source_id; 1576 out_id = m_private_settings.external_clock_source_id;
1392 R_SUCCEED(); 1577 R_SUCCEED();
diff --git a/src/core/hle/service/set/system_settings_server.h b/src/core/hle/service/set/system_settings_server.h
index acbda8b8c..1982b9723 100644
--- a/src/core/hle/service/set/system_settings_server.h
+++ b/src/core/hle/service/set/system_settings_server.h
@@ -50,6 +50,10 @@ public:
50 50
51 Result GetVibrationMasterVolume(f32& out_volume) const; 51 Result GetVibrationMasterVolume(f32& out_volume) const;
52 Result SetVibrationMasterVolume(f32 volume); 52 Result SetVibrationMasterVolume(f32 volume);
53 Result GetAudioOutputMode(AudioOutputMode& out_output_mode, AudioOutputModeTarget target) const;
54 Result SetAudioOutputMode(AudioOutputModeTarget target, AudioOutputMode output_mode);
55 Result GetSpeakerAutoMuteFlag(bool& is_auto_mute) const;
56 Result SetSpeakerAutoMuteFlag(bool auto_mute);
53 Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const; 57 Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const;
54 Result SetExternalSteadyClockSourceId(const Common::UUID& id); 58 Result SetExternalSteadyClockSourceId(const Common::UUID& id);
55 Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const; 59 Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const;
@@ -97,8 +101,10 @@ private:
97 void GetSettingsItemValue(HLERequestContext& ctx); 101 void GetSettingsItemValue(HLERequestContext& ctx);
98 void GetTvSettings(HLERequestContext& ctx); 102 void GetTvSettings(HLERequestContext& ctx);
99 void SetTvSettings(HLERequestContext& ctx); 103 void SetTvSettings(HLERequestContext& ctx);
100 void IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx); 104 void GetAudioOutputMode(HLERequestContext& ctx);
101 void SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx); 105 void SetAudioOutputMode(HLERequestContext& ctx);
106 void GetSpeakerAutoMuteFlag(HLERequestContext& ctx);
107 void SetSpeakerAutoMuteFlag(HLERequestContext& ctx);
102 void GetDebugModeFlag(HLERequestContext& ctx); 108 void GetDebugModeFlag(HLERequestContext& ctx);
103 void GetQuestFlag(HLERequestContext& ctx); 109 void GetQuestFlag(HLERequestContext& ctx);
104 void SetQuestFlag(HLERequestContext& ctx); 110 void SetQuestFlag(HLERequestContext& ctx);
@@ -111,6 +117,8 @@ private:
111 void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); 117 void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
112 void GetPrimaryAlbumStorage(HLERequestContext& ctx); 118 void GetPrimaryAlbumStorage(HLERequestContext& ctx);
113 void SetPrimaryAlbumStorage(HLERequestContext& ctx); 119 void SetPrimaryAlbumStorage(HLERequestContext& ctx);
120 void GetBatteryLot(HLERequestContext& ctx);
121 void GetSerialNumber(HLERequestContext& ctx);
114 void GetNfcEnableFlag(HLERequestContext& ctx); 122 void GetNfcEnableFlag(HLERequestContext& ctx);
115 void SetNfcEnableFlag(HLERequestContext& ctx); 123 void SetNfcEnableFlag(HLERequestContext& ctx);
116 void GetSleepSettings(HLERequestContext& ctx); 124 void GetSleepSettings(HLERequestContext& ctx);
@@ -126,13 +134,19 @@ private:
126 void SetBluetoothEnableFlag(HLERequestContext& ctx); 134 void SetBluetoothEnableFlag(HLERequestContext& ctx);
127 void GetMiiAuthorId(HLERequestContext& ctx); 135 void GetMiiAuthorId(HLERequestContext& ctx);
128 void GetAutoUpdateEnableFlag(HLERequestContext& ctx); 136 void GetAutoUpdateEnableFlag(HLERequestContext& ctx);
137 void SetAutoUpdateEnableFlag(HLERequestContext& ctx);
129 void GetBatteryPercentageFlag(HLERequestContext& ctx); 138 void GetBatteryPercentageFlag(HLERequestContext& ctx);
139 void SetBatteryPercentageFlag(HLERequestContext& ctx);
130 void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx); 140 void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
131 void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx); 141 void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
142 void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
143 void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
132 void GetErrorReportSharePermission(HLERequestContext& ctx); 144 void GetErrorReportSharePermission(HLERequestContext& ctx);
145 void SetErrorReportSharePermission(HLERequestContext& ctx);
133 void GetAppletLaunchFlags(HLERequestContext& ctx); 146 void GetAppletLaunchFlags(HLERequestContext& ctx);
134 void SetAppletLaunchFlags(HLERequestContext& ctx); 147 void SetAppletLaunchFlags(HLERequestContext& ctx);
135 void GetKeyboardLayout(HLERequestContext& ctx); 148 void GetKeyboardLayout(HLERequestContext& ctx);
149 void SetKeyboardLayout(HLERequestContext& ctx);
136 void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); 150 void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
137 void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); 151 void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
138 void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); 152 void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
@@ -141,6 +155,8 @@ private:
141 void GetHomeMenuScheme(HLERequestContext& ctx); 155 void GetHomeMenuScheme(HLERequestContext& ctx);
142 void GetHomeMenuSchemeModel(HLERequestContext& ctx); 156 void GetHomeMenuSchemeModel(HLERequestContext& ctx);
143 void GetFieldTestingFlag(HLERequestContext& ctx); 157 void GetFieldTestingFlag(HLERequestContext& ctx);
158 void GetPanelCrcMode(HLERequestContext& ctx);
159 void SetPanelCrcMode(HLERequestContext& ctx);
144 160
145 bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func); 161 bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func);
146 bool StoreSettingsFile(std::filesystem::path& path, auto& settings); 162 bool StoreSettingsFile(std::filesystem::path& path, auto& settings);
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 1c218566f..e10a4601e 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -781,8 +781,7 @@ struct Memory::Impl {
781 }, 781 },
782 [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); }); 782 [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); });
783 if (ptr) { 783 if (ptr) {
784 const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr); 784 return Common::AtomicCompareAndSwap(reinterpret_cast<T*>(ptr), data, expected);
785 return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
786 } 785 }
787 return true; 786 return true;
788 } 787 }
@@ -796,8 +795,7 @@ struct Memory::Impl {
796 }, 795 },
797 [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); }); 796 [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); });
798 if (ptr) { 797 if (ptr) {
799 const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr); 798 return Common::AtomicCompareAndSwap(reinterpret_cast<u64*>(ptr), data, expected);
800 return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
801 } 799 }
802 return true; 800 return true;
803 } 801 }
diff --git a/src/frontend_common/config.cpp b/src/frontend_common/config.cpp
index 46277e288..905f35118 100644
--- a/src/frontend_common/config.cpp
+++ b/src/frontend_common/config.cpp
@@ -298,6 +298,16 @@ void Config::ReadDebuggingValues() {
298 EndGroup(); 298 EndGroup();
299} 299}
300 300
301#ifdef __unix__
302void Config::ReadLinuxValues() {
303 BeginGroup(Settings::TranslateCategory(Settings::Category::Linux));
304
305 ReadCategory(Settings::Category::Linux);
306
307 EndGroup();
308}
309#endif
310
301void Config::ReadServiceValues() { 311void Config::ReadServiceValues() {
302 BeginGroup(Settings::TranslateCategory(Settings::Category::Services)); 312 BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
303 313
@@ -404,6 +414,9 @@ void Config::ReadValues() {
404 ReadControlValues(); 414 ReadControlValues();
405 ReadCoreValues(); 415 ReadCoreValues();
406 ReadCpuValues(); 416 ReadCpuValues();
417#ifdef __unix__
418 ReadLinuxValues();
419#endif
407 ReadRendererValues(); 420 ReadRendererValues();
408 ReadAudioValues(); 421 ReadAudioValues();
409 ReadSystemValues(); 422 ReadSystemValues();
@@ -504,6 +517,9 @@ void Config::SaveValues() {
504 SaveControlValues(); 517 SaveControlValues();
505 SaveCoreValues(); 518 SaveCoreValues();
506 SaveCpuValues(); 519 SaveCpuValues();
520#ifdef __unix__
521 SaveLinuxValues();
522#endif
507 SaveRendererValues(); 523 SaveRendererValues();
508 SaveAudioValues(); 524 SaveAudioValues();
509 SaveSystemValues(); 525 SaveSystemValues();
@@ -578,6 +594,16 @@ void Config::SaveDebuggingValues() {
578 EndGroup(); 594 EndGroup();
579} 595}
580 596
597#ifdef __unix__
598void Config::SaveLinuxValues() {
599 BeginGroup(Settings::TranslateCategory(Settings::Category::Linux));
600
601 WriteCategory(Settings::Category::Linux);
602
603 EndGroup();
604}
605#endif
606
581void Config::SaveNetworkValues() { 607void Config::SaveNetworkValues() {
582 BeginGroup(Settings::TranslateCategory(Settings::Category::Services)); 608 BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
583 609
diff --git a/src/frontend_common/config.h b/src/frontend_common/config.h
index 4798d6432..4ecb97044 100644
--- a/src/frontend_common/config.h
+++ b/src/frontend_common/config.h
@@ -76,6 +76,9 @@ protected:
76 void ReadCoreValues(); 76 void ReadCoreValues();
77 void ReadDataStorageValues(); 77 void ReadDataStorageValues();
78 void ReadDebuggingValues(); 78 void ReadDebuggingValues();
79#ifdef __unix__
80 void ReadLinuxValues();
81#endif
79 void ReadServiceValues(); 82 void ReadServiceValues();
80 void ReadDisabledAddOnValues(); 83 void ReadDisabledAddOnValues();
81 void ReadMiscellaneousValues(); 84 void ReadMiscellaneousValues();
@@ -107,6 +110,9 @@ protected:
107 void SaveCoreValues(); 110 void SaveCoreValues();
108 void SaveDataStorageValues(); 111 void SaveDataStorageValues();
109 void SaveDebuggingValues(); 112 void SaveDebuggingValues();
113#ifdef __unix__
114 void SaveLinuxValues();
115#endif
110 void SaveNetworkValues(); 116 void SaveNetworkValues();
111 void SaveDisabledAddOnValues(); 117 void SaveDisabledAddOnValues();
112 void SaveMiscellaneousValues(); 118 void SaveMiscellaneousValues();
diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp
index a2295219a..e78665d31 100644
--- a/src/hid_core/resource_manager.cpp
+++ b/src/hid_core/resource_manager.cpp
@@ -184,7 +184,7 @@ void ResourceManager::InitializeHidCommonSampler() {
184 keyboard->SetAppletResource(applet_resource, &shared_mutex); 184 keyboard->SetAppletResource(applet_resource, &shared_mutex);
185 185
186 const auto settings = 186 const auto settings =
187 system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys"); 187 system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
188 npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, settings); 188 npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, settings);
189 189
190 six_axis->SetAppletResource(applet_resource, &shared_mutex); 190 six_axis->SetAppletResource(applet_resource, &shared_mutex);
diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp
index 4897a2784..36b630c7f 100644
--- a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp
+++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp
@@ -137,7 +137,7 @@ void NpadAbstractPropertiesHandler::UpdateAllDeviceProperties() {
137 const auto npad_index = NpadIdTypeToIndex(npad_id_type); 137 const auto npad_index = NpadIdTypeToIndex(npad_id_type);
138 for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { 138 for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
139 auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index); 139 auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index);
140 if (!data->flag.is_assigned) { 140 if (data == nullptr || !data->flag.is_assigned) {
141 continue; 141 continue;
142 } 142 }
143 auto& npad_entry = data->shared_memory_format->npad.npad_entry[npad_index]; 143 auto& npad_entry = data->shared_memory_format->npad.npad_entry[npad_index];
diff --git a/src/hid_core/resources/hid_firmware_settings.cpp b/src/hid_core/resources/hid_firmware_settings.cpp
index 9c9019e8f..b32c0660a 100644
--- a/src/hid_core/resources/hid_firmware_settings.cpp
+++ b/src/hid_core/resources/hid_firmware_settings.cpp
@@ -8,7 +8,8 @@
8namespace Service::HID { 8namespace Service::HID {
9 9
10HidFirmwareSettings::HidFirmwareSettings(Core::System& system) { 10HidFirmwareSettings::HidFirmwareSettings(Core::System& system) {
11 m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys"); 11 m_set_sys =
12 system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
12 LoadSettings(true); 13 LoadSettings(true);
13} 14}
14 15
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 521a0e253..0755ba772 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -302,7 +302,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS})
302 302
303add_dependencies(video_core host_shaders) 303add_dependencies(video_core host_shaders)
304target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) 304target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE})
305target_link_libraries(video_core PRIVATE sirit Vulkan::Headers GPUOpen::VulkanMemoryAllocator) 305target_link_libraries(video_core PRIVATE sirit Vulkan::Headers Vulkan::UtilityHeaders GPUOpen::VulkanMemoryAllocator)
306 306
307if (ENABLE_NSIGHT_AFTERMATH) 307if (ENABLE_NSIGHT_AFTERMATH)
308 if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) 308 if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK})
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 86a30dcd1..4f1d3b4e3 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -12,6 +12,7 @@
12#include "core/core.h" 12#include "core/core.h"
13#include "video_core/renderer_vulkan/vk_scheduler.h" 13#include "video_core/renderer_vulkan/vk_scheduler.h"
14#include "video_core/renderer_vulkan/vk_swapchain.h" 14#include "video_core/renderer_vulkan/vk_swapchain.h"
15#include "video_core/vulkan_common/vk_enum_string_helper.h"
15#include "video_core/vulkan_common/vulkan_device.h" 16#include "video_core/vulkan_common/vulkan_device.h"
16#include "video_core/vulkan_common/vulkan_wrapper.h" 17#include "video_core/vulkan_common/vulkan_wrapper.h"
17#include "vulkan/vulkan_core.h" 18#include "vulkan/vulkan_core.h"
@@ -151,7 +152,7 @@ bool Swapchain::AcquireNextImage() {
151 vk::Check(result); 152 vk::Check(result);
152 break; 153 break;
153 default: 154 default:
154 LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", vk::ToString(result)); 155 LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", string_VkResult(result));
155 break; 156 break;
156 } 157 }
157 158
@@ -187,7 +188,7 @@ void Swapchain::Present(VkSemaphore render_semaphore) {
187 vk::Check(result); 188 vk::Check(result);
188 break; 189 break;
189 default: 190 default:
190 LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", vk::ToString(result)); 191 LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", string_VkResult(result));
191 break; 192 break;
192 } 193 }
193 ++frame_index; 194 ++frame_index;
diff --git a/src/video_core/vulkan_common/vk_enum_string_helper.h b/src/video_core/vulkan_common/vk_enum_string_helper.h
new file mode 100644
index 000000000..a1515814c
--- /dev/null
+++ b/src/video_core/vulkan_common/vk_enum_string_helper.h
@@ -0,0 +1,8 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "video_core/vulkan_common/vulkan.h"
7
8#include <vulkan/vk_enum_string_helper.h>
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index 3966bd61e..f1aa45551 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -9,6 +9,7 @@
9 9
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "video_core/vulkan_common/vk_enum_string_helper.h"
12#include "video_core/vulkan_common/vma.h" 13#include "video_core/vulkan_common/vma.h"
13#include "video_core/vulkan_common/vulkan_wrapper.h" 14#include "video_core/vulkan_common/vulkan_wrapper.h"
14 15
@@ -298,109 +299,7 @@ bool Load(VkInstance instance, InstanceDispatch& dld) noexcept {
298} 299}
299 300
300const char* Exception::what() const noexcept { 301const char* Exception::what() const noexcept {
301 return ToString(result); 302 return string_VkResult(result);
302}
303
304const char* ToString(VkResult result) noexcept {
305 switch (result) {
306 case VkResult::VK_SUCCESS:
307 return "VK_SUCCESS";
308 case VkResult::VK_NOT_READY:
309 return "VK_NOT_READY";
310 case VkResult::VK_TIMEOUT:
311 return "VK_TIMEOUT";
312 case VkResult::VK_EVENT_SET:
313 return "VK_EVENT_SET";
314 case VkResult::VK_EVENT_RESET:
315 return "VK_EVENT_RESET";
316 case VkResult::VK_INCOMPLETE:
317 return "VK_INCOMPLETE";
318 case VkResult::VK_ERROR_OUT_OF_HOST_MEMORY:
319 return "VK_ERROR_OUT_OF_HOST_MEMORY";
320 case VkResult::VK_ERROR_OUT_OF_DEVICE_MEMORY:
321 return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
322 case VkResult::VK_ERROR_INITIALIZATION_FAILED:
323 return "VK_ERROR_INITIALIZATION_FAILED";
324 case VkResult::VK_ERROR_DEVICE_LOST:
325 return "VK_ERROR_DEVICE_LOST";
326 case VkResult::VK_ERROR_MEMORY_MAP_FAILED:
327 return "VK_ERROR_MEMORY_MAP_FAILED";
328 case VkResult::VK_ERROR_LAYER_NOT_PRESENT:
329 return "VK_ERROR_LAYER_NOT_PRESENT";
330 case VkResult::VK_ERROR_EXTENSION_NOT_PRESENT:
331 return "VK_ERROR_EXTENSION_NOT_PRESENT";
332 case VkResult::VK_ERROR_FEATURE_NOT_PRESENT:
333 return "VK_ERROR_FEATURE_NOT_PRESENT";
334 case VkResult::VK_ERROR_INCOMPATIBLE_DRIVER:
335 return "VK_ERROR_INCOMPATIBLE_DRIVER";
336 case VkResult::VK_ERROR_TOO_MANY_OBJECTS:
337 return "VK_ERROR_TOO_MANY_OBJECTS";
338 case VkResult::VK_ERROR_FORMAT_NOT_SUPPORTED:
339 return "VK_ERROR_FORMAT_NOT_SUPPORTED";
340 case VkResult::VK_ERROR_FRAGMENTED_POOL:
341 return "VK_ERROR_FRAGMENTED_POOL";
342 case VkResult::VK_ERROR_OUT_OF_POOL_MEMORY:
343 return "VK_ERROR_OUT_OF_POOL_MEMORY";
344 case VkResult::VK_ERROR_INVALID_EXTERNAL_HANDLE:
345 return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
346 case VkResult::VK_ERROR_SURFACE_LOST_KHR:
347 return "VK_ERROR_SURFACE_LOST_KHR";
348 case VkResult::VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
349 return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
350 case VkResult::VK_SUBOPTIMAL_KHR:
351 return "VK_SUBOPTIMAL_KHR";
352 case VkResult::VK_ERROR_OUT_OF_DATE_KHR:
353 return "VK_ERROR_OUT_OF_DATE_KHR";
354 case VkResult::VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
355 return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
356 case VkResult::VK_ERROR_VALIDATION_FAILED_EXT:
357 return "VK_ERROR_VALIDATION_FAILED_EXT";
358 case VkResult::VK_ERROR_INVALID_SHADER_NV:
359 return "VK_ERROR_INVALID_SHADER_NV";
360 case VkResult::VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR:
361 return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR";
362 case VkResult::VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR:
363 return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR";
364 case VkResult::VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR:
365 return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR";
366 case VkResult::VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR:
367 return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR";
368 case VkResult::VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR:
369 return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR";
370 case VkResult::VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR:
371 return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR";
372 case VkResult::VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
373 return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
374 case VkResult::VK_ERROR_FRAGMENTATION_EXT:
375 return "VK_ERROR_FRAGMENTATION_EXT";
376 case VkResult::VK_ERROR_NOT_PERMITTED_EXT:
377 return "VK_ERROR_NOT_PERMITTED_EXT";
378 case VkResult::VK_ERROR_INVALID_DEVICE_ADDRESS_EXT:
379 return "VK_ERROR_INVALID_DEVICE_ADDRESS_EXT";
380 case VkResult::VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
381 return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
382 case VkResult::VK_ERROR_UNKNOWN:
383 return "VK_ERROR_UNKNOWN";
384 case VkResult::VK_THREAD_IDLE_KHR:
385 return "VK_THREAD_IDLE_KHR";
386 case VkResult::VK_THREAD_DONE_KHR:
387 return "VK_THREAD_DONE_KHR";
388 case VkResult::VK_OPERATION_DEFERRED_KHR:
389 return "VK_OPERATION_DEFERRED_KHR";
390 case VkResult::VK_OPERATION_NOT_DEFERRED_KHR:
391 return "VK_OPERATION_NOT_DEFERRED_KHR";
392 case VkResult::VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR:
393 return "VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR";
394 case VkResult::VK_PIPELINE_COMPILE_REQUIRED_EXT:
395 return "VK_PIPELINE_COMPILE_REQUIRED_EXT";
396 case VkResult::VK_RESULT_MAX_ENUM:
397 return "VK_RESULT_MAX_ENUM";
398 case VkResult::VK_ERROR_COMPRESSION_EXHAUSTED_EXT:
399 return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT";
400 case VkResult::VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT:
401 return "VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT";
402 }
403 return "Unknown";
404} 303}
405 304
406void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept { 305void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept {
@@ -1067,7 +966,7 @@ u32 AvailableVersion(const InstanceDispatch& dld) noexcept {
1067 u32 version; 966 u32 version;
1068 if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) { 967 if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) {
1069 LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1", 968 LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1",
1070 ToString(result)); 969 string_VkResult(result));
1071 return VK_API_VERSION_1_1; 970 return VK_API_VERSION_1_1;
1072 } 971 }
1073 return version; 972 return version;
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index a0c70797f..757f3c8af 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -125,9 +125,6 @@ private:
125 VkResult result; 125 VkResult result;
126}; 126};
127 127
128/// Converts a VkResult enum into a rodata string
129const char* ToString(VkResult) noexcept;
130
131/// Throws a Vulkan exception if result is not success. 128/// Throws a Vulkan exception if result is not success.
132inline void Check(VkResult result) { 129inline void Check(VkResult result) {
133 if (result != VK_SUCCESS) { 130 if (result != VK_SUCCESS) {
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index b058dba17..76f06da12 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -96,6 +96,9 @@ add_executable(yuzu
96 configuration/configure_input_profile_dialog.cpp 96 configuration/configure_input_profile_dialog.cpp
97 configuration/configure_input_profile_dialog.h 97 configuration/configure_input_profile_dialog.h
98 configuration/configure_input_profile_dialog.ui 98 configuration/configure_input_profile_dialog.ui
99 configuration/configure_linux_tab.cpp
100 configuration/configure_linux_tab.h
101 configuration/configure_linux_tab.ui
99 configuration/configure_mouse_panning.cpp 102 configuration/configure_mouse_panning.cpp
100 configuration/configure_mouse_panning.h 103 configuration/configure_mouse_panning.h
101 configuration/configure_mouse_panning.ui 104 configuration/configure_mouse_panning.ui
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h
index 79538e81c..82d7f6524 100644
--- a/src/yuzu/configuration/configure_audio.h
+++ b/src/yuzu/configuration/configure_audio.h
@@ -24,6 +24,8 @@ class Builder;
24} 24}
25 25
26class ConfigureAudio : public ConfigurationShared::Tab { 26class ConfigureAudio : public ConfigurationShared::Tab {
27 Q_OBJECT
28
27public: 29public:
28 explicit ConfigureAudio(const Core::System& system_, 30 explicit ConfigureAudio(const Core::System& system_,
29 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, 31 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h
index a102b4c1f..7bbeac496 100644
--- a/src/yuzu/configuration/configure_cpu.h
+++ b/src/yuzu/configuration/configure_cpu.h
@@ -24,6 +24,8 @@ class Builder;
24} 24}
25 25
26class ConfigureCpu : public ConfigurationShared::Tab { 26class ConfigureCpu : public ConfigurationShared::Tab {
27 Q_OBJECT
28
27public: 29public:
28 explicit ConfigureCpu(const Core::System& system_, 30 explicit ConfigureCpu(const Core::System& system_,
29 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, 31 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h
index 2d953f679..ada6526a6 100644
--- a/src/yuzu/configuration/configure_general.h
+++ b/src/yuzu/configuration/configure_general.h
@@ -25,6 +25,8 @@ class Builder;
25} 25}
26 26
27class ConfigureGeneral : public ConfigurationShared::Tab { 27class ConfigureGeneral : public ConfigurationShared::Tab {
28 Q_OBJECT
29
28public: 30public:
29 explicit ConfigureGeneral(const Core::System& system_, 31 explicit ConfigureGeneral(const Core::System& system_,
30 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, 32 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 0836bcb7e..54c931e56 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -224,6 +224,11 @@ void ConfigureGraphics::PopulateVSyncModeSelection(bool use_setting) {
224} 224}
225 225
226void ConfigureGraphics::UpdateVsyncSetting() const { 226void ConfigureGraphics::UpdateVsyncSetting() const {
227 const Settings::RendererBackend backend{GetCurrentGraphicsBackend()};
228 if (backend == Settings::RendererBackend::Null) {
229 return;
230 }
231
227 const auto mode = vsync_mode_combobox_enum_map[vsync_mode_combobox->currentIndex()]; 232 const auto mode = vsync_mode_combobox_enum_map[vsync_mode_combobox->currentIndex()];
228 const auto vsync_mode = PresentModeToSetting(mode); 233 const auto vsync_mode = PresentModeToSetting(mode);
229 Settings::values.vsync_mode.SetValue(vsync_mode); 234 Settings::values.vsync_mode.SetValue(vsync_mode);
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 5c8286836..b92b4496b 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -43,6 +43,8 @@ class Builder;
43} 43}
44 44
45class ConfigureGraphics : public ConfigurationShared::Tab { 45class ConfigureGraphics : public ConfigurationShared::Tab {
46 Q_OBJECT
47
46public: 48public:
47 explicit ConfigureGraphics( 49 explicit ConfigureGraphics(
48 const Core::System& system_, std::vector<VkDeviceInfo::Record>& records, 50 const Core::System& system_, std::vector<VkDeviceInfo::Record>& records,
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index 78b5389c3..82431987e 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -21,6 +21,8 @@ class Builder;
21} 21}
22 22
23class ConfigureGraphicsAdvanced : public ConfigurationShared::Tab { 23class ConfigureGraphicsAdvanced : public ConfigurationShared::Tab {
24 Q_OBJECT
25
24public: 26public:
25 explicit ConfigureGraphicsAdvanced( 27 explicit ConfigureGraphicsAdvanced(
26 const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, 28 const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
diff --git a/src/yuzu/configuration/configure_linux_tab.cpp b/src/yuzu/configuration/configure_linux_tab.cpp
new file mode 100644
index 000000000..ab3d18816
--- /dev/null
+++ b/src/yuzu/configuration/configure_linux_tab.cpp
@@ -0,0 +1,75 @@
1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/settings.h"
5#include "core/core.h"
6#include "ui_configure_linux_tab.h"
7#include "yuzu/configuration/configuration_shared.h"
8#include "yuzu/configuration/configure_linux_tab.h"
9#include "yuzu/configuration/shared_widget.h"
10
11ConfigureLinuxTab::ConfigureLinuxTab(const Core::System& system_,
12 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,
13 const ConfigurationShared::Builder& builder, QWidget* parent)
14 : Tab(group_, parent), ui(std::make_unique<Ui::ConfigureLinuxTab>()), system{system_} {
15 ui->setupUi(this);
16
17 Setup(builder);
18
19 SetConfiguration();
20}
21
22ConfigureLinuxTab::~ConfigureLinuxTab() = default;
23
24void ConfigureLinuxTab::SetConfiguration() {}
25void ConfigureLinuxTab::Setup(const ConfigurationShared::Builder& builder) {
26 QLayout& linux_layout = *ui->linux_widget->layout();
27
28 std::map<u32, QWidget*> linux_hold{};
29
30 std::vector<Settings::BasicSetting*> settings;
31 const auto push = [&](Settings::Category category) {
32 for (const auto setting : Settings::values.linkage.by_category[category]) {
33 settings.push_back(setting);
34 }
35 };
36
37 push(Settings::Category::Linux);
38
39 for (auto* setting : settings) {
40 auto* widget = builder.BuildWidget(setting, apply_funcs);
41
42 if (widget == nullptr) {
43 continue;
44 }
45 if (!widget->Valid()) {
46 widget->deleteLater();
47 continue;
48 }
49
50 linux_hold.insert({setting->Id(), widget});
51 }
52
53 for (const auto& [id, widget] : linux_hold) {
54 linux_layout.addWidget(widget);
55 }
56}
57
58void ConfigureLinuxTab::ApplyConfiguration() {
59 const bool is_powered_on = system.IsPoweredOn();
60 for (const auto& apply_func : apply_funcs) {
61 apply_func(is_powered_on);
62 }
63}
64
65void ConfigureLinuxTab::changeEvent(QEvent* event) {
66 if (event->type() == QEvent::LanguageChange) {
67 RetranslateUI();
68 }
69
70 QWidget::changeEvent(event);
71}
72
73void ConfigureLinuxTab::RetranslateUI() {
74 ui->retranslateUi(this);
75}
diff --git a/src/yuzu/configuration/configure_linux_tab.h b/src/yuzu/configuration/configure_linux_tab.h
new file mode 100644
index 000000000..2f402079c
--- /dev/null
+++ b/src/yuzu/configuration/configure_linux_tab.h
@@ -0,0 +1,44 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <QWidget>
7
8namespace Core {
9class System;
10}
11
12namespace Ui {
13class ConfigureLinuxTab;
14}
15
16namespace ConfigurationShared {
17class Builder;
18}
19
20class ConfigureLinuxTab : public ConfigurationShared::Tab {
21 Q_OBJECT
22
23public:
24 explicit ConfigureLinuxTab(const Core::System& system_,
25 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
26 const ConfigurationShared::Builder& builder,
27 QWidget* parent = nullptr);
28 ~ConfigureLinuxTab() override;
29
30 void ApplyConfiguration() override;
31 void SetConfiguration() override;
32
33private:
34 void changeEvent(QEvent* event) override;
35 void RetranslateUI();
36
37 void Setup(const ConfigurationShared::Builder& builder);
38
39 std::unique_ptr<Ui::ConfigureLinuxTab> ui;
40
41 const Core::System& system;
42
43 std::vector<std::function<void(bool)>> apply_funcs{};
44};
diff --git a/src/yuzu/configuration/configure_linux_tab.ui b/src/yuzu/configuration/configure_linux_tab.ui
new file mode 100644
index 000000000..f8e07f581
--- /dev/null
+++ b/src/yuzu/configuration/configure_linux_tab.ui
@@ -0,0 +1,53 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>ConfigureLinuxTab</class>
4 <widget class="QWidget" name="ConfigureLinuxTab">
5 <property name="accessibleName">
6 <string>Linux</string>
7 </property>
8 <layout class="QVBoxLayout">
9 <item>
10 <widget class="QGroupBox" name="LinuxGroupBox">
11 <property name="title">
12 <string>Linux</string>
13 </property>
14 <layout class="QVBoxLayout" name="LinuxVerticalLayout_1">
15 <item>
16 <widget class="QWidget" name="linux_widget" native="true">
17 <layout class="QVBoxLayout" name="LinuxVerticalLayout_2">
18 <property name="leftMargin">
19 <number>0</number>
20 </property>
21 <property name="topMargin">
22 <number>0</number>
23 </property>
24 <property name="rightMargin">
25 <number>0</number>
26 </property>
27 <property name="bottomMargin">
28 <number>0</number>
29 </property>
30 </layout>
31 </widget>
32 </item>
33 </layout>
34 </widget>
35 </item>
36 <item>
37 <spacer name="verticalSpacer">
38 <property name="orientation">
39 <enum>Qt::Vertical</enum>
40 </property>
41 <property name="sizeHint" stdset="0">
42 <size>
43 <width>20</width>
44 <height>40</height>
45 </size>
46 </property>
47 </spacer>
48 </item>
49 </layout>
50 </widget>
51 <resources/>
52 <connections/>
53</ui>
diff --git a/src/yuzu/configuration/configure_motion_touch.h b/src/yuzu/configuration/configure_motion_touch.h
index 7dcc9318e..a5db0de51 100644
--- a/src/yuzu/configuration/configure_motion_touch.h
+++ b/src/yuzu/configuration/configure_motion_touch.h
@@ -26,6 +26,7 @@ class ConfigureMotionTouch;
26/// A dialog for touchpad calibration configuration. 26/// A dialog for touchpad calibration configuration.
27class CalibrationConfigurationDialog : public QDialog { 27class CalibrationConfigurationDialog : public QDialog {
28 Q_OBJECT 28 Q_OBJECT
29
29public: 30public:
30 explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port); 31 explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port);
31 ~CalibrationConfigurationDialog() override; 32 ~CalibrationConfigurationDialog() override;
diff --git a/src/yuzu/configuration/configure_mouse_panning.h b/src/yuzu/configuration/configure_mouse_panning.h
index 08c6e1f62..f5e62ee13 100644
--- a/src/yuzu/configuration/configure_mouse_panning.h
+++ b/src/yuzu/configuration/configure_mouse_panning.h
@@ -16,6 +16,7 @@ class ConfigureMousePanning;
16 16
17class ConfigureMousePanning : public QDialog { 17class ConfigureMousePanning : public QDialog {
18 Q_OBJECT 18 Q_OBJECT
19
19public: 20public:
20 explicit ConfigureMousePanning(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_, 21 explicit ConfigureMousePanning(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_,
21 float right_stick_deadzone, float right_stick_range); 22 float right_stick_deadzone, float right_stick_range);
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index b274a3321..9d38ab812 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -33,6 +33,7 @@
33#include "yuzu/configuration/configure_graphics.h" 33#include "yuzu/configuration/configure_graphics.h"
34#include "yuzu/configuration/configure_graphics_advanced.h" 34#include "yuzu/configuration/configure_graphics_advanced.h"
35#include "yuzu/configuration/configure_input_per_game.h" 35#include "yuzu/configuration/configure_input_per_game.h"
36#include "yuzu/configuration/configure_linux_tab.h"
36#include "yuzu/configuration/configure_per_game.h" 37#include "yuzu/configuration/configure_per_game.h"
37#include "yuzu/configuration/configure_per_game_addons.h" 38#include "yuzu/configuration/configure_per_game_addons.h"
38#include "yuzu/configuration/configure_system.h" 39#include "yuzu/configuration/configure_system.h"
@@ -60,6 +61,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
60 system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, 61 system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); },
61 [](Settings::AspectRatio, Settings::ResolutionSetup) {}, tab_group, *builder, this); 62 [](Settings::AspectRatio, Settings::ResolutionSetup) {}, tab_group, *builder, this);
62 input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this); 63 input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);
64 linux_tab = std::make_unique<ConfigureLinuxTab>(system_, tab_group, *builder, this);
63 system_tab = std::make_unique<ConfigureSystem>(system_, tab_group, *builder, this); 65 system_tab = std::make_unique<ConfigureSystem>(system_, tab_group, *builder, this);
64 66
65 ui->setupUi(this); 67 ui->setupUi(this);
@@ -71,6 +73,10 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
71 ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics")); 73 ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics"));
72 ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); 74 ui->tabWidget->addTab(audio_tab.get(), tr("Audio"));
73 ui->tabWidget->addTab(input_tab.get(), tr("Input Profiles")); 75 ui->tabWidget->addTab(input_tab.get(), tr("Input Profiles"));
76 // Only show Linux tab on Unix
77#ifdef __unix__
78 ui->tabWidget->addTab(linux_tab.get(), tr("Linux"));
79#endif
74 80
75 setFocusPolicy(Qt::ClickFocus); 81 setFocusPolicy(Qt::ClickFocus);
76 setWindowTitle(tr("Properties")); 82 setWindowTitle(tr("Properties"));
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index 9daae772c..196cb32e6 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -32,6 +32,7 @@ class ConfigureCpu;
32class ConfigureGraphics; 32class ConfigureGraphics;
33class ConfigureGraphicsAdvanced; 33class ConfigureGraphicsAdvanced;
34class ConfigureInputPerGame; 34class ConfigureInputPerGame;
35class ConfigureLinuxTab;
35class ConfigureSystem; 36class ConfigureSystem;
36 37
37class QGraphicsScene; 38class QGraphicsScene;
@@ -85,5 +86,6 @@ private:
85 std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; 86 std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab;
86 std::unique_ptr<ConfigureGraphics> graphics_tab; 87 std::unique_ptr<ConfigureGraphics> graphics_tab;
87 std::unique_ptr<ConfigureInputPerGame> input_tab; 88 std::unique_ptr<ConfigureInputPerGame> input_tab;
89 std::unique_ptr<ConfigureLinuxTab> linux_tab;
88 std::unique_ptr<ConfigureSystem> system_tab; 90 std::unique_ptr<ConfigureSystem> system_tab;
89}; 91};
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h
index 4334211f9..a01c29dcf 100644
--- a/src/yuzu/configuration/configure_system.h
+++ b/src/yuzu/configuration/configure_system.h
@@ -27,6 +27,8 @@ class Builder;
27} 27}
28 28
29class ConfigureSystem : public ConfigurationShared::Tab { 29class ConfigureSystem : public ConfigurationShared::Tab {
30 Q_OBJECT
31
30public: 32public:
31 explicit ConfigureSystem(Core::System& system_, 33 explicit ConfigureSystem(Core::System& system_,
32 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, 34 std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,