diff options
Diffstat (limited to 'src')
27 files changed, 699 insertions, 512 deletions
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 | ||
| 4 | package org.yuzu.yuzu_emu.utils | 4 | package org.yuzu.yuzu_emu.utils |
| 5 | 5 | ||
| 6 | import android.graphics.SurfaceTexture | ||
| 6 | import android.net.Uri | 7 | import android.net.Uri |
| 7 | import android.os.Build | 8 | import android.os.Build |
| 9 | import android.view.Surface | ||
| 8 | import java.io.File | 10 | import java.io.File |
| 9 | import java.io.IOException | 11 | import java.io.IOException |
| 10 | import org.yuzu.yuzu_emu.NativeLibrary | 12 | import 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 | ||
| 23 | set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) | 23 | set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) |
| 24 | 24 | ||
| 25 | target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common) | 25 | target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers) |
| 26 | target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log) | 26 | target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log) |
| 27 | if (ARCHITECTURE_arm64) | 27 | if (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; | |||
| 19 | static jmethodID s_disk_cache_load_progress; | 19 | static jmethodID s_disk_cache_load_progress; |
| 20 | static jmethodID s_on_emulation_started; | 20 | static jmethodID s_on_emulation_started; |
| 21 | static jmethodID s_on_emulation_stopped; | 21 | static jmethodID s_on_emulation_stopped; |
| 22 | static jmethodID s_on_program_changed; | ||
| 22 | 23 | ||
| 23 | static jclass s_game_class; | 24 | static jclass s_game_class; |
| 24 | static jmethodID s_game_constructor; | 25 | static 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 | ||
| 127 | jmethodID GetOnProgramChanged() { | ||
| 128 | return s_on_program_changed; | ||
| 129 | } | ||
| 130 | |||
| 126 | jclass GetGameClass() { | 131 | jclass 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(); | |||
| 19 | jmethodID GetDiskCacheLoadProgress(); | 19 | jmethodID GetDiskCacheLoadProgress(); |
| 20 | jmethodID GetOnEmulationStarted(); | 20 | jmethodID GetOnEmulationStarted(); |
| 21 | jmethodID GetOnEmulationStopped(); | 21 | jmethodID GetOnEmulationStopped(); |
| 22 | jmethodID GetOnProgramChanged(); | ||
| 22 | 23 | ||
| 23 | jclass GetGameClass(); | 24 | jclass GetGameClass(); |
| 24 | jmethodID GetGameConstructor(); | 25 | jmethodID 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 | ||
| 211 | Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) { | 214 | Core::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 | |||
| 255 | void EmulationSession::ShutdownEmulation() { | 266 | void 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 | ||
| 421 | void 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 | |||
| 405 | u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) { | 427 | u64 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 | ||
| 414 | static Core::SystemResultStatus RunEmulation(const std::string& filepath) { | 436 | static 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 | ||
| 547 | jobjectArray 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 | |||
| 524 | jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) { | 578 | jboolean 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 | ||
| 692 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2(JNIEnv* env, jclass clazz, | 746 | void 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: | |||
| 60 | private: | 61 | private: |
| 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 | ||
| 64 | private: | 66 | private: |
| 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/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 | ||
| 8 | namespace Service::Audio { | 10 | namespace 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 | ||
| 73 | AudCtl::~AudCtl() = default; | 78 | AudCtl::~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 | ||
| 104 | void 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 | |||
| 118 | void 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 | |||
| 99 | void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) { | 131 | void 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 | ||
| 107 | void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) { | 139 | void 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 | |||
| 150 | void 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 | |||
| 161 | void 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 | ||
| 118 | void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) { | 168 | void 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 | ||
| 176 | void 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 | |||
| 126 | void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) { | 189 | void 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 { | |||
| 9 | class System; | 9 | class System; |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | namespace Service::Set { | ||
| 13 | class ISystemSettingsServer; | ||
| 14 | } | ||
| 15 | |||
| 12 | namespace Service::Audio { | 16 | namespace Service::Audio { |
| 13 | 17 | ||
| 14 | class AudCtl final : public ServiceFramework<AudCtl> { | 18 | class AudCtl final : public ServiceFramework<AudCtl> { |
| @@ -17,14 +21,6 @@ public: | |||
| 17 | ~AudCtl() override; | 21 | ~AudCtl() override; |
| 18 | 22 | ||
| 19 | private: | 23 | private: |
| 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/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 | ||
| 17 | namespace Service::Mii { | 20 | namespace 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 | ||
| 62 | private: | 67 | private: |
| 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 | ||
| 532 | MiiDBModule::MiiDBModule(Core::System& system_, const char* name_, | 291 | IStaticService::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 | ||
| 548 | MiiDBModule::~MiiDBModule() = default; | 303 | IStaticService::~IStaticService() = default; |
| 549 | |||
| 550 | void 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 | ||
| 305 | Result 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 | ||
| 558 | std::shared_ptr<MiiManager> MiiDBModule::GetMiiManager() { | 314 | std::shared_ptr<MiiManager> IStaticService::GetMiiManager() { |
| 559 | return manager; | 315 | return manager; |
| 560 | } | 316 | } |
| 561 | 317 | ||
| 562 | class MiiImg final : public ServiceFramework<MiiImg> { | 318 | class IImageDatabaseService final : public ServiceFramework<IImageDatabaseService> { |
| 563 | public: | 319 | public: |
| 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 | ||
| 587 | private: | 343 | private: |
| 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 | ||
| 604 | void LoopProcess(Core::System& system) { | 359 | void 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 | ||
| 8 | namespace Core { | 8 | namespace Core { |
| 9 | class System; | 9 | class System; |
| @@ -11,19 +11,20 @@ class System; | |||
| 11 | 11 | ||
| 12 | namespace Service::Mii { | 12 | namespace Service::Mii { |
| 13 | class MiiManager; | 13 | class MiiManager; |
| 14 | class IDatabaseService; | ||
| 14 | 15 | ||
| 15 | class MiiDBModule final : public ServiceFramework<MiiDBModule> { | 16 | class IStaticService final : public ServiceFramework<IStaticService> { |
| 16 | public: | 17 | public: |
| 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 | ||
| 23 | private: | 24 | private: |
| 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..16ded43bf 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 | ||
| 6 | namespace Service::Set { | 7 | namespace Service::Set { |
| @@ -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 |
| 25 | enum class AudioOutputModeTarget : u32 { | 25 | enum 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 { | |||
| 367 | static_assert(sizeof(AccountNotificationSettings) == 0x18, | 370 | static_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 | ||
| 374 | struct BatteryLot { | ||
| 375 | std::array<char, 0x18> lot_number; | ||
| 376 | }; | ||
| 377 | static_assert(sizeof(BatteryLot) == 0x18, "BatteryLot is an invalid size"); | ||
| 378 | |||
| 370 | /// This is nn::settings::system::EulaVersion | 379 | /// This is nn::settings::system::EulaVersion |
| 371 | struct EulaVersion { | 380 | struct EulaVersion { |
| 372 | u32 version; | 381 | u32 version; |
| @@ -436,6 +445,12 @@ struct NotificationSettings { | |||
| 436 | }; | 445 | }; |
| 437 | static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size"); | 446 | static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size"); |
| 438 | 447 | ||
| 448 | /// This is nn::settings::factory::SerialNumber | ||
| 449 | struct SerialNumber { | ||
| 450 | std::array<char, 0x18> serial_number; | ||
| 451 | }; | ||
| 452 | static_assert(sizeof(SerialNumber) == 0x18, "SerialNumber is an invalid size"); | ||
| 453 | |||
| 439 | /// This is nn::settings::system::SleepSettings | 454 | /// This is nn::settings::system::SleepSettings |
| 440 | struct SleepSettings { | 455 | struct 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 @@ | |||
| 25 | namespace Service::Set { | 25 | namespace Service::Set { |
| 26 | 26 | ||
| 27 | namespace { | 27 | namespace { |
| 28 | constexpr u32 SETTINGS_VERSION{1u}; | 28 | constexpr u32 SETTINGS_VERSION{2u}; |
| 29 | constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); | 29 | constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); |
| 30 | struct SettingsHeader { | 30 | struct 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 | ||
| 817 | void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) { | 820 | void 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 | |||
| 834 | void 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 | |||
| 847 | void 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 | ||
| 826 | void ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) { | 856 | void 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 | ||
| 999 | void 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 | |||
| 1009 | void 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 | |||
| 969 | void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) { | 1019 | void 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 | ||
| 1182 | void 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 | |||
| 1132 | void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) { | 1193 | void 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 | ||
| 1202 | void 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 | |||
| 1141 | void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) { | 1214 | void 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 | ||
| 1237 | void 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 | |||
| 1246 | void 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 | |||
| 1164 | void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) { | 1258 | void 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 | ||
| 1267 | void 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 | |||
| 1173 | void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) { | 1279 | void 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 | ||
| 1192 | void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) { | 1298 | void 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 | |||
| 1306 | void 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 | ||
| 1211 | void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) { | 1317 | void 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 | ||
| 1406 | void 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 | |||
| 1414 | void 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 | |||
| 1300 | void ISystemSettingsServer::SetupSettings() { | 1425 | void 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 | ||
| 1515 | Result 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 | |||
| 1539 | Result 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 | |||
| 1564 | Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(bool& is_auto_mute) const { | ||
| 1565 | is_auto_mute = m_system_settings.force_mute_on_headphone_removed; | ||
| 1566 | R_SUCCEED(); | ||
| 1567 | } | ||
| 1568 | |||
| 1569 | Result 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 | |||
| 1390 | Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const { | 1575 | Result 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/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 @@ | |||
| 8 | namespace Service::HID { | 8 | namespace Service::HID { |
| 9 | 9 | ||
| 10 | HidFirmwareSettings::HidFirmwareSettings(Core::System& system) { | 10 | HidFirmwareSettings::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/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 | ||
| 226 | void ConfigureGraphics::UpdateVsyncSetting() const { | 226 | void 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); |