summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt8
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt8
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt53
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt5
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt33
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt7
-rw-r--r--src/android/app/src/main/jni/CMakeLists.txt2
-rw-r--r--src/android/app/src/main/jni/id_cache.cpp7
-rw-r--r--src/android/app/src/main/jni/id_cache.h1
-rw-r--r--src/android/app/src/main/jni/native.cpp68
-rw-r--r--src/android/app/src/main/jni/native.h7
-rw-r--r--src/android/app/src/main/res/layout/fragment_emulation.xml4
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp7
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/audio_renderer.h7
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/command_buffer.h5
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp7
-rw-r--r--src/audio_core/adsp/apps/audio_renderer/command_list_processor.h7
-rw-r--r--src/audio_core/renderer/audio_renderer.cpp6
-rw-r--r--src/audio_core/renderer/audio_renderer.h6
-rw-r--r--src/audio_core/renderer/system.cpp10
-rw-r--r--src/audio_core/renderer/system.h6
-rw-r--r--src/core/hle/kernel/k_thread.cpp3
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.cpp2
-rw-r--r--src/core/hle/service/audio/audctl.cpp84
-rw-r--r--src/core/hle/service/audio/audctl.h20
-rw-r--r--src/core/hle/service/audio/audren_u.cpp16
-rw-r--r--src/core/hle/service/mii/mii.cpp563
-rw-r--r--src/core/hle/service/mii/mii.h15
-rw-r--r--src/core/hle/service/set/setting_formats/system_settings.cpp12
-rw-r--r--src/core/hle/service/set/setting_formats/system_settings.h12
-rw-r--r--src/core/hle/service/set/settings_types.h15
-rw-r--r--src/core/hle/service/set/system_settings_server.cpp249
-rw-r--r--src/core/hle/service/set/system_settings_server.h20
-rw-r--r--src/hid_core/resource_manager.cpp2
-rw-r--r--src/hid_core/resources/hid_firmware_settings.cpp3
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp5
36 files changed, 753 insertions, 532 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 {
/**
* Begins emulation.
*/
- external fun run(path: String?)
+ external fun run(path: String?, programIndex: Int = 0)
// Surface Handling
external fun surfaceChanged(surf: Surface?)
@@ -489,6 +489,12 @@ object NativeLibrary {
sEmulationActivity.get()!!.onEmulationStopped(status)
}
+ @Keep
+ @JvmStatic
+ fun onProgramChanged(programIndex: Int) {
+ sEmulationActivity.get()!!.onProgramChanged(programIndex)
+ }
+
/**
* Logs the Yuzu version, Android version and, CPU.
*/
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 {
override fun onDestroy() {
stopForegroundService(this)
- emulationViewModel.clear()
super.onDestroy()
}
@@ -446,9 +445,14 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
}
fun onEmulationStopped(status: Int) {
- if (status == 0) {
+ if (status == 0 && emulationViewModel.programChanged.value == -1) {
finish()
}
+ emulationViewModel.setEmulationStopped(true)
+ }
+
+ fun onProgramChanged(programIndex: Int) {
+ emulationViewModel.setProgramChanged(programIndex)
}
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 ef393c4be..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
@@ -424,10 +424,38 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
}
+ launch {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
+ emulationViewModel.programChanged.collect {
+ if (it != 0) {
+ emulationViewModel.setEmulationStarted(false)
+ binding.drawerLayout.close()
+ binding.drawerLayout
+ .setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
+ ViewUtils.hideView(binding.surfaceInputOverlay)
+ ViewUtils.showView(binding.loadingIndicator)
+ }
+ }
+ }
+ }
+ launch {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
+ emulationViewModel.emulationStopped.collect {
+ if (it && emulationViewModel.programChanged.value != -1) {
+ if (perfStatsUpdater != null) {
+ perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!)
+ }
+ emulationState.changeProgram(emulationViewModel.programChanged.value)
+ emulationViewModel.setProgramChanged(-1)
+ emulationViewModel.setEmulationStopped(false)
+ }
+ }
+ }
+ }
}
}
- private fun startEmulation() {
+ private fun startEmulation(programIndex: Int = 0) {
if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
if (!DirectoryInitialization.areDirectoriesReady) {
DirectoryInitialization.start()
@@ -435,7 +463,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
updateScreenLayout()
- emulationState.run(emulationActivity!!.isActivityRecreated)
+ emulationState.run(emulationActivity!!.isActivityRecreated, programIndex)
}
}
@@ -833,6 +861,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
) {
private var state: State
private var surface: Surface? = null
+ lateinit var emulationThread: Thread
init {
// Starting state is stopped.
@@ -878,7 +907,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
@Synchronized
- fun run(isActivityRecreated: Boolean) {
+ fun run(isActivityRecreated: Boolean, programIndex: Int = 0) {
if (isActivityRecreated) {
if (NativeLibrary.isRunning()) {
state = State.PAUSED
@@ -889,10 +918,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
// If the surface is set, run now. Otherwise, wait for it to get set.
if (surface != null) {
- runWithValidSurface()
+ runWithValidSurface(programIndex)
}
}
+ @Synchronized
+ fun changeProgram(programIndex: Int) {
+ emulationThread.join()
+ emulationThread = Thread({
+ Log.debug("[EmulationFragment] Starting emulation thread.")
+ NativeLibrary.run(gamePath, programIndex)
+ }, "NativeEmulation")
+ emulationThread.start()
+ }
+
// Surface callbacks
@Synchronized
fun newSurface(surface: Surface?) {
@@ -932,7 +971,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
- private fun runWithValidSurface() {
+ private fun runWithValidSurface(programIndex: Int = 0) {
NativeLibrary.surfaceChanged(surface)
if (!emulationCanStart.invoke()) {
return
@@ -940,9 +979,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
when (state) {
State.STOPPED -> {
- val emulationThread = Thread({
+ emulationThread = Thread({
Log.debug("[EmulationFragment] Starting emulation thread.")
- NativeLibrary.run(gamePath)
+ NativeLibrary.run(gamePath, programIndex)
}, "NativeEmulation")
emulationThread.start()
}
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() {
fun updateDriverList() {
val selectedDriver = GpuDriverHelper.customDriverSettingData
+ val systemDriverData = GpuDriverHelper.getSystemDriverInfo()
val newDriverList = mutableListOf(
Driver(
selectedDriver == GpuDriverMetadata(),
- YuzuApplication.appContext.getString(R.string.system_gpu_driver)
+ YuzuApplication.appContext.getString(R.string.system_gpu_driver),
+ systemDriverData?.get(0) ?: "",
+ systemDriverData?.get(1) ?: ""
)
)
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() {
val isEmulationStopping: StateFlow<Boolean> get() = _isEmulationStopping
private val _isEmulationStopping = MutableStateFlow(false)
+ private val _emulationStopped = MutableStateFlow(false)
+ val emulationStopped = _emulationStopped.asStateFlow()
+
+ private val _programChanged = MutableStateFlow(-1)
+ val programChanged = _programChanged.asStateFlow()
+
val shaderProgress: StateFlow<Int> get() = _shaderProgress
private val _shaderProgress = MutableStateFlow(0)
@@ -35,6 +41,17 @@ class EmulationViewModel : ViewModel() {
_isEmulationStopping.value = value
}
+ fun setEmulationStopped(value: Boolean) {
+ if (value) {
+ _emulationStarted.value = false
+ }
+ _emulationStopped.value = value
+ }
+
+ fun setProgramChanged(programIndex: Int) {
+ _programChanged.value = programIndex
+ }
+
fun setShaderProgress(progress: Int) {
_shaderProgress.value = progress
}
@@ -56,20 +73,4 @@ class EmulationViewModel : ViewModel() {
fun setDrawerOpen(value: Boolean) {
_drawerOpen.value = value
}
-
- fun clear() {
- setEmulationStarted(false)
- setIsEmulationStopping(false)
- setShaderProgress(0)
- setTotalShaders(0)
- setShaderMessage("")
- }
-
- companion object {
- const val KEY_EMULATION_STARTED = "EmulationStarted"
- const val KEY_IS_EMULATION_STOPPING = "IsEmulationStarting"
- const val KEY_SHADER_PROGRESS = "ShaderProgress"
- const val KEY_TOTAL_SHADERS = "TotalShaders"
- const val KEY_SHADER_MESSAGE = "ShaderMessage"
- }
}
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 @@
package org.yuzu.yuzu_emu.utils
+import android.graphics.SurfaceTexture
import android.net.Uri
import android.os.Build
+import android.view.Surface
import java.io.File
import java.io.IOException
import org.yuzu.yuzu_emu.NativeLibrary
@@ -195,6 +197,11 @@ object GpuDriverHelper {
external fun supportsCustomDriverLoading(): Boolean
+ external fun getSystemDriverInfo(
+ surface: Surface = Surface(SurfaceTexture(true)),
+ hookLibPath: String = GpuDriverHelper.hookLibPath!!
+ ): Array<String>?
+
// Parse the custom driver metadata to retrieve the name.
val installedCustomDriverData: GpuDriverMetadata
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
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
-target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common)
+target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers)
target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
if (ARCHITECTURE_arm64)
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;
static jmethodID s_disk_cache_load_progress;
static jmethodID s_on_emulation_started;
static jmethodID s_on_emulation_stopped;
+static jmethodID s_on_program_changed;
static jclass s_game_class;
static jmethodID s_game_constructor;
@@ -123,6 +124,10 @@ jmethodID GetOnEmulationStopped() {
return s_on_emulation_stopped;
}
+jmethodID GetOnProgramChanged() {
+ return s_on_program_changed;
+}
+
jclass GetGameClass() {
return s_game_class;
}
@@ -306,6 +311,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V");
s_on_emulation_stopped =
env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V");
+ s_on_program_changed =
+ env->GetStaticMethodID(s_native_library_class, "onProgramChanged", "(I)V");
const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game");
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();
jmethodID GetDiskCacheLoadProgress();
jmethodID GetOnEmulationStarted();
jmethodID GetOnEmulationStopped();
+jmethodID GetOnProgramChanged();
jclass GetGameClass();
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 @@
#include "jni/id_cache.h"
#include "jni/native.h"
#include "video_core/renderer_base.h"
+#include "video_core/renderer_vulkan/renderer_vulkan.h"
+#include "video_core/vulkan_common/vulkan_instance.h"
+#include "video_core/vulkan_common/vulkan_surface.h"
#define jconst [[maybe_unused]] const auto
#define jauto [[maybe_unused]] auto
@@ -208,7 +211,8 @@ void EmulationSession::InitializeSystem(bool reload) {
m_system.GetFileSystemController().CreateFactories(*m_vfs);
}
-Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) {
+Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
+ const std::size_t program_index) {
std::scoped_lock lock(m_mutex);
// Create the render window.
@@ -238,7 +242,8 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
ConfigureFilesystemProvider(filepath);
// Load the ROM.
- m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath);
+ m_load_result =
+ m_system.Load(EmulationSession::GetInstance().Window(), filepath, 0, program_index);
if (m_load_result != Core::SystemResultStatus::Success) {
return m_load_result;
}
@@ -248,6 +253,12 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
m_system.GetCpuManager().OnGpuReady();
m_system.RegisterExitCallback([&] { HaltEmulation(); });
+ // Register an ExecuteProgram callback such that Core can execute a sub-program
+ m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) {
+ m_next_program_index = program_index_;
+ EmulationSession::GetInstance().HaltEmulation();
+ });
+
OnEmulationStarted();
return Core::SystemResultStatus::Success;
}
@@ -255,6 +266,11 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
void EmulationSession::ShutdownEmulation() {
std::scoped_lock lock(m_mutex);
+ if (m_next_program_index != -1) {
+ ChangeProgram(m_next_program_index);
+ m_next_program_index = -1;
+ }
+
m_is_running = false;
// Unload user input.
@@ -402,6 +418,12 @@ void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) {
static_cast<jint>(result));
}
+void EmulationSession::ChangeProgram(std::size_t program_index) {
+ JNIEnv* env = IDCache::GetEnvForThread();
+ env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnProgramChanged(),
+ static_cast<jint>(program_index));
+}
+
u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
auto program_id_string = GetJString(env, jprogramId);
try {
@@ -411,7 +433,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
}
}
-static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
+static Core::SystemResultStatus RunEmulation(const std::string& filepath,
+ const size_t program_index = 0) {
MicroProfileOnThreadCreate("EmuThread");
SCOPE_EXIT({ MicroProfileShutdown(); });
@@ -424,7 +447,7 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
- jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath);
+ jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index);
if (result != Core::SystemResultStatus::Success) {
return result;
}
@@ -521,6 +544,37 @@ jboolean JNICALL Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_supportsCustomDri
#endif
}
+jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
+ JNIEnv* env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
+ const char* file_redirect_dir_{};
+ int featureFlags{};
+ std::string hook_lib_dir = GetJString(env, j_hook_lib_dir);
+ auto handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(),
+ nullptr, nullptr, file_redirect_dir_, nullptr);
+ auto driver_library = std::make_shared<Common::DynamicLibrary>(handle);
+ InputCommon::InputSubsystem input_subsystem;
+ auto m_window = std::make_unique<EmuWindow_Android>(
+ &input_subsystem, ANativeWindow_fromSurface(env, j_surf), driver_library);
+
+ Vulkan::vk::InstanceDispatch dld;
+ Vulkan::vk::Instance vk_instance = Vulkan::CreateInstance(
+ *driver_library, dld, VK_API_VERSION_1_1, Core::Frontend::WindowSystemType::Android);
+
+ auto surface = Vulkan::CreateSurface(vk_instance, m_window->GetWindowInfo());
+
+ auto device = Vulkan::CreateDevice(vk_instance, dld, *surface);
+
+ auto driver_version = device.GetDriverVersion();
+ auto version_string =
+ fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(driver_version),
+ VK_API_VERSION_MINOR(driver_version), VK_API_VERSION_PATCH(driver_version));
+
+ jobjectArray j_driver_info =
+ env->NewObjectArray(2, IDCache::GetStringClass(), ToJString(env, version_string));
+ env->SetObjectArrayElement(j_driver_info, 1, ToJString(env, device.GetDriverName()));
+ return j_driver_info;
+}
+
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
Core::Crypto::KeyManager::Instance().ReloadKeys();
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
Settings::LogSettings();
}
-void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2(JNIEnv* env, jclass clazz,
- jstring j_path) {
+void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
+ jint j_program_index) {
const std::string path = GetJString(env, j_path);
- const Core::SystemResultStatus result{RunEmulation(path)};
+ const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
if (result != Core::SystemResultStatus::Success) {
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
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:
const Core::PerfStatsResults& PerfStats();
void ConfigureFilesystemProvider(const std::string& filepath);
void InitializeSystem(bool reload);
- Core::SystemResultStatus InitializeEmulation(const std::string& filepath);
+ Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
+ const std::size_t program_index = 0);
bool IsHandheldOnly();
void SetDeviceType([[maybe_unused]] int index, int type);
@@ -60,6 +61,7 @@ public:
private:
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
static void OnEmulationStopped(Core::SystemResultStatus result);
+ static void ChangeProgram(std::size_t program_index);
private:
// Window management
@@ -84,4 +86,7 @@ private:
// Synchronization
std::condition_variable_any m_cv;
mutable std::mutex m_mutex;
+
+ // Program index for next boot
+ std::atomic<s32> m_next_program_index = -1;
};
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 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
+ android:focusable="false"
android:defaultFocusHighlightEnabled="false"
- android:clickable="false">
+ android:clickable="false"
+ app:rippleColor="@android:color/transparent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/loading_layout"
diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp
index ef301d8b4..7a76c3d0b 100644
--- a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp
+++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp
@@ -89,11 +89,13 @@ u32 AudioRenderer::Receive(Direction dir) {
}
void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
- u64 applet_resource_user_id, bool reset) noexcept {
+ u64 applet_resource_user_id, Kernel::KProcess* process,
+ bool reset) noexcept {
command_buffers[session_id].buffer = buffer;
command_buffers[session_id].size = size;
command_buffers[session_id].time_limit = time_limit;
command_buffers[session_id].applet_resource_user_id = applet_resource_user_id;
+ command_buffers[session_id].process = process;
command_buffers[session_id].reset_buffer = reset;
}
@@ -173,7 +175,8 @@ void AudioRenderer::Main(std::stop_token stop_token) {
// If there are no remaining commands (from the previous list),
// this is a new command list, initialize it.
if (command_buffer.remaining_command_count == 0) {
- command_list_processor.Initialize(system, command_buffer.buffer,
+ command_list_processor.Initialize(system, *command_buffer.process,
+ command_buffer.buffer,
command_buffer.size, streams[index]);
}
diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h
index 57b89d9fe..875266f27 100644
--- a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h
+++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h
@@ -19,6 +19,10 @@ namespace Core {
class System;
} // namespace Core
+namespace Kernel {
+class KProcess;
+}
+
namespace AudioCore {
namespace Sink {
class Sink;
@@ -69,7 +73,8 @@ public:
u32 Receive(Direction dir);
void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
- u64 applet_resource_user_id, bool reset) noexcept;
+ u64 applet_resource_user_id, Kernel::KProcess* process,
+ bool reset) noexcept;
u32 GetRemainCommandCount(s32 session_id) const noexcept;
void ClearRemainCommandCount(s32 session_id) noexcept;
u64 GetRenderingStartTick(s32 session_id) const noexcept;
diff --git a/src/audio_core/adsp/apps/audio_renderer/command_buffer.h b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h
index 3fd1b09dc..d6a721f34 100644
--- a/src/audio_core/adsp/apps/audio_renderer/command_buffer.h
+++ b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h
@@ -6,6 +6,10 @@
#include "audio_core/common/common.h"
#include "common/common_types.h"
+namespace Kernel {
+class KProcess;
+}
+
namespace AudioCore::ADSP::AudioRenderer {
struct CommandBuffer {
@@ -14,6 +18,7 @@ struct CommandBuffer {
u64 size{};
u64 time_limit{};
u64 applet_resource_user_id{};
+ Kernel::KProcess* process{};
bool reset_buffer{};
// Set by the DSP
u32 remaining_command_count{};
diff --git a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp
index 24e4d0496..eef2c0b89 100644
--- a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp
+++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp
@@ -9,14 +9,15 @@
#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
+#include "core/hle/kernel/k_process.h"
#include "core/memory.h"
namespace AudioCore::ADSP::AudioRenderer {
-void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size,
- Sink::SinkStream* stream_) {
+void CommandListProcessor::Initialize(Core::System& system_, Kernel::KProcess& process,
+ CpuAddr buffer, u64 size, Sink::SinkStream* stream_) {
system = &system_;
- memory = &system->ApplicationMemory();
+ memory = &process.GetMemory();
stream = stream_;
header = reinterpret_cast<Renderer::CommandListHeader*>(buffer);
commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader));
diff --git a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h
index 4e5fb793e..944e82505 100644
--- a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h
+++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h
@@ -16,6 +16,10 @@ class Memory;
class System;
} // namespace Core
+namespace Kernel {
+class KProcess;
+}
+
namespace AudioCore {
namespace Sink {
class SinkStream;
@@ -40,7 +44,8 @@ public:
* @param size - The size of the buffer.
* @param stream - The stream to be used for sending the samples.
*/
- void Initialize(Core::System& system, CpuAddr buffer, u64 size, Sink::SinkStream* stream);
+ void Initialize(Core::System& system, Kernel::KProcess& process, CpuAddr buffer, u64 size,
+ Sink::SinkStream* stream);
/**
* Set the maximum processing time for this command list.
diff --git a/src/audio_core/renderer/audio_renderer.cpp b/src/audio_core/renderer/audio_renderer.cpp
index 09efe9be9..df03d03aa 100644
--- a/src/audio_core/renderer/audio_renderer.cpp
+++ b/src/audio_core/renderer/audio_renderer.cpp
@@ -6,6 +6,7 @@
#include "audio_core/renderer/audio_renderer.h"
#include "audio_core/renderer/system_manager.h"
#include "core/core.h"
+#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/service/audio/errors.h"
@@ -17,7 +18,8 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren
Result Renderer::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory,
const u64 transfer_memory_size, const u32 process_handle,
- const u64 applet_resource_user_id, const s32 session_id) {
+ Kernel::KProcess& process, const u64 applet_resource_user_id,
+ const s32 session_id) {
if (params.execution_mode == ExecutionMode::Auto) {
if (!manager.AddSystem(system)) {
LOG_ERROR(Service_Audio,
@@ -28,7 +30,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
}
initialized = true;
- system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
+ system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
applet_resource_user_id, session_id);
return ResultSuccess;
diff --git a/src/audio_core/renderer/audio_renderer.h b/src/audio_core/renderer/audio_renderer.h
index 24650278b..1219f74ca 100644
--- a/src/audio_core/renderer/audio_renderer.h
+++ b/src/audio_core/renderer/audio_renderer.h
@@ -14,7 +14,8 @@ class System;
namespace Kernel {
class KTransferMemory;
-}
+class KProcess;
+} // namespace Kernel
namespace AudioCore {
struct AudioRendererParameterInternal;
@@ -44,7 +45,8 @@ public:
*/
Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
- u32 process_handle, u64 applet_resource_user_id, s32 session_id);
+ u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
+ s32 session_id);
/**
* Finalize the renderer for shutdown.
diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp
index 31f92087c..ca656edae 100644
--- a/src/audio_core/renderer/system.cpp
+++ b/src/audio_core/renderer/system.cpp
@@ -32,6 +32,7 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/memory.h"
@@ -101,7 +102,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
Result System::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
- u32 process_handle_, u64 applet_resource_user_id_, s32 session_id_) {
+ u32 process_handle_, Kernel::KProcess& process_,
+ u64 applet_resource_user_id_, s32 session_id_) {
if (!CheckValidRevision(params.revision)) {
return Service::Audio::ResultInvalidRevision;
}
@@ -117,6 +119,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
behavior.SetUserLibRevision(params.revision);
process_handle = process_handle_;
+ process = &process_;
applet_resource_user_id = applet_resource_user_id_;
session_id = session_id_;
@@ -129,7 +132,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
render_device = params.rendering_device;
execution_mode = params.execution_mode;
- core.ApplicationMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
+ process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
// Note: We're not actually using the transfer memory because it's a pain to code for.
// Allocate the memory normally instead and hope the game doesn't try to read anything back
@@ -613,7 +616,8 @@ void System::SendCommandToDsp() {
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
(static_cast<f32>(render_time_limit_percent) / 100.0f))};
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
- applet_resource_user_id, reset_command_buffers);
+ applet_resource_user_id, process,
+ reset_command_buffers);
reset_command_buffers = false;
command_buffer_size = command_size;
if (remaining_command_count == 0) {
diff --git a/src/audio_core/renderer/system.h b/src/audio_core/renderer/system.h
index 8a8341710..753a0b796 100644
--- a/src/audio_core/renderer/system.h
+++ b/src/audio_core/renderer/system.h
@@ -29,6 +29,7 @@ class System;
namespace Kernel {
class KEvent;
+class KProcess;
class KTransferMemory;
} // namespace Kernel
@@ -80,7 +81,8 @@ public:
*/
Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
- u32 process_handle, u64 applet_resource_user_id, s32 session_id);
+ u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
+ s32 session_id);
/**
* Finalize the system.
@@ -275,6 +277,8 @@ private:
Common::Event terminate_event{};
/// Does what locks do
std::mutex lock{};
+ /// Process this audio render is operating within, used for memory reads/writes.
+ Kernel::KProcess* process{};
/// Handle for the process for this system, unused
u32 process_handle{};
/// Applet resource id for this system, unused
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() {
ASSERT(m_parent != nullptr);
// Resume any threads that began waiting on us while we were pinned.
- for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); ++it) {
+ for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end();
+ it = m_pinned_waiter_list.erase(it)) {
it->EndWait(ResultSuccess);
}
}
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() {
break;
}
- manager = system.ServiceManager().GetService<Mii::MiiDBModule>("mii:e")->GetMiiManager();
+ manager = system.ServiceManager().GetService<Mii::IStaticService>("mii:e")->GetMiiManager();
if (manager == nullptr) {
manager = std::make_shared<Mii::MiiManager>();
}
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 @@
#include "common/logging/log.h"
#include "core/hle/service/audio/audctl.h"
#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/set/system_settings_server.h"
+#include "core/hle/service/sm/sm.h"
namespace Service::Audio {
@@ -19,15 +21,15 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{6, nullptr, "IsTargetConnected"},
{7, nullptr, "SetDefaultTarget"},
{8, nullptr, "GetDefaultTarget"},
- {9, nullptr, "GetAudioOutputMode"},
- {10, nullptr, "SetAudioOutputMode"},
+ {9, &AudCtl::GetAudioOutputMode, "GetAudioOutputMode"},
+ {10, &AudCtl::SetAudioOutputMode, "SetAudioOutputMode"},
{11, nullptr, "SetForceMutePolicy"},
{12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"},
{13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"},
- {14, nullptr, "SetOutputModeSetting"},
+ {14, &AudCtl::SetOutputModeSetting, "SetOutputModeSetting"},
{15, nullptr, "SetOutputTarget"},
{16, nullptr, "SetInputTargetForceEnabled"},
- {17, nullptr, "SetHeadphoneOutputLevelMode"},
+ {17, &AudCtl::SetHeadphoneOutputLevelMode, "SetHeadphoneOutputLevelMode"},
{18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"},
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
@@ -40,7 +42,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{27, nullptr, "SetVolumeMappingTableForDev"},
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
- {30, nullptr, "SetSpeakerAutoMuteEnabled"},
+ {30, &AudCtl::SetSpeakerAutoMuteEnabled, "SetSpeakerAutoMuteEnabled"},
{31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
{32, nullptr, "GetActiveOutputTarget"},
{33, nullptr, "GetTargetDeviceInfo"},
@@ -68,6 +70,9 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
// clang-format on
RegisterHandlers(functions);
+
+ m_set_sys =
+ system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
}
AudCtl::~AudCtl() = default;
@@ -96,6 +101,33 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
rb.Push(target_max_volume);
}
+void AudCtl::GetAudioOutputMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
+
+ Set::AudioOutputMode output_mode{};
+ const auto result = m_set_sys->GetAudioOutputMode(output_mode, target);
+
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(result);
+ rb.PushEnum(output_mode);
+}
+
+void AudCtl::SetAudioOutputMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
+ const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
+
+ const auto result = m_set_sys->SetAudioOutputMode(target, output_mode);
+
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
LOG_WARNING(Audio, "(STUBBED) called");
@@ -106,13 +138,31 @@ void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto value = rp.Pop<u32>();
+ const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
- LOG_WARNING(Audio, "(STUBBED) called, value={}", value);
+ LOG_WARNING(Audio, "(STUBBED) called, target={}", target);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
- rb.PushEnum(AudioOutputMode::PcmAuto);
+ rb.PushEnum(Set::AudioOutputMode::ch_7_1);
+}
+
+void AudCtl::SetOutputModeSetting(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
+ const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
+
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void AudCtl::SetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
+ LOG_WARNING(Audio, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
}
void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
@@ -123,14 +173,28 @@ void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
rb.PushEnum(HeadphoneOutputLevelMode::Normal);
}
+void AudCtl::SetSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto is_speaker_auto_mute_enabled{rp.Pop<bool>()};
+
+ LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
+ is_speaker_auto_mute_enabled);
+
+ const auto result = m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
- const bool is_speaker_auto_mute_enabled = false;
+ bool is_speaker_auto_mute_enabled{};
+ const auto result = m_set_sys->GetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
is_speaker_auto_mute_enabled);
IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
+ rb.Push(result);
rb.Push<u8>(is_speaker_auto_mute_enabled);
}
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 {
class System;
}
+namespace Service::Set {
+class ISystemSettingsServer;
+}
+
namespace Service::Audio {
class AudCtl final : public ServiceFramework<AudCtl> {
@@ -17,14 +21,6 @@ public:
~AudCtl() override;
private:
- enum class AudioOutputMode {
- Invalid,
- Pcm1ch,
- Pcm2ch,
- Pcm6ch,
- PcmAuto,
- };
-
enum class ForceMutePolicy {
Disable,
SpeakerMuteOnHeadphoneUnplugged,
@@ -37,10 +33,18 @@ private:
void GetTargetVolumeMin(HLERequestContext& ctx);
void GetTargetVolumeMax(HLERequestContext& ctx);
+ void GetAudioOutputMode(HLERequestContext& ctx);
+ void SetAudioOutputMode(HLERequestContext& ctx);
void GetForceMutePolicy(HLERequestContext& ctx);
void GetOutputModeSetting(HLERequestContext& ctx);
+ void SetOutputModeSetting(HLERequestContext& ctx);
+ void SetHeadphoneOutputLevelMode(HLERequestContext& ctx);
void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
+ void SetSpeakerAutoMuteEnabled(HLERequestContext& ctx);
void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
+ void AcquireTargetNotification(HLERequestContext& ctx);
+
+ std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
};
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 05581e6e0..10108abc0 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -35,10 +35,11 @@ public:
explicit IAudioRenderer(Core::System& system_, Manager& manager_,
AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
- u32 process_handle, u64 applet_resource_user_id, s32 session_id)
+ u32 process_handle, Kernel::KProcess& process_,
+ u64 applet_resource_user_id, s32 session_id)
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
- impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
+ impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
@@ -59,13 +60,15 @@ public:
// clang-format on
RegisterHandlers(functions);
- impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle,
+ process.Open();
+ impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
applet_resource_user_id, session_id);
}
~IAudioRenderer() override {
impl->Finalize();
service_context.CloseEvent(rendered_event);
+ process.Close();
}
private:
@@ -235,6 +238,7 @@ private:
Kernel::KEvent* rendered_event;
Manager& manager;
std::unique_ptr<Renderer> impl;
+ Kernel::KProcess& process;
Common::ScratchBuffer<u8> output_buffer;
Common::ScratchBuffer<u8> performance_buffer;
};
@@ -455,7 +459,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
return;
}
- auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)};
+ auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
const auto session_id{impl->GetSessionId()};
@@ -472,7 +476,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
- transfer_memory_size, process_handle,
+ transfer_memory_size, process_handle, *process,
applet_resource_user_id, session_id);
}
@@ -522,7 +526,7 @@ void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) {
}
void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
+ LOG_ERROR(Service_Audio, "called. Implement me!");
}
void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index c28eed926..b4d16fed5 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -4,15 +4,18 @@
#include <memory>
#include "common/logging/log.h"
+#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/mii/mii.h"
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/mii/mii_result.h"
#include "core/hle/service/mii/types/char_info.h"
+#include "core/hle/service/mii/types/raw_data.h"
#include "core/hle/service/mii/types/store_data.h"
#include "core/hle/service/mii/types/ver3_store_data.h"
#include "core/hle/service/server_manager.h"
-#include "core/hle/service/service.h"
+#include "core/hle/service/set/system_settings_server.h"
+#include "core/hle/service/sm/sm.h"
namespace Service::Mii {
@@ -24,549 +27,302 @@ public:
is_system_} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &IDatabaseService::IsUpdated, "IsUpdated"},
- {1, &IDatabaseService::IsFullDatabase, "IsFullDatabase"},
- {2, &IDatabaseService::GetCount, "GetCount"},
- {3, &IDatabaseService::Get, "Get"},
- {4, &IDatabaseService::Get1, "Get1"},
- {5, &IDatabaseService::UpdateLatest, "UpdateLatest"},
- {6, &IDatabaseService::BuildRandom, "BuildRandom"},
- {7, &IDatabaseService::BuildDefault, "BuildDefault"},
- {8, &IDatabaseService::Get2, "Get2"},
- {9, &IDatabaseService::Get3, "Get3"},
- {10, &IDatabaseService::UpdateLatest1, "UpdateLatest1"},
- {11, &IDatabaseService::FindIndex, "FindIndex"},
- {12, &IDatabaseService::Move, "Move"},
- {13, &IDatabaseService::AddOrReplace, "AddOrReplace"},
- {14, &IDatabaseService::Delete, "Delete"},
- {15, &IDatabaseService::DestroyFile, "DestroyFile"},
- {16, &IDatabaseService::DeleteFile, "DeleteFile"},
- {17, &IDatabaseService::Format, "Format"},
+ {0, D<&IDatabaseService::IsUpdated>, "IsUpdated"},
+ {1, D<&IDatabaseService::IsFullDatabase>, "IsFullDatabase"},
+ {2, D<&IDatabaseService::GetCount>, "GetCount"},
+ {3, D<&IDatabaseService::Get>, "Get"},
+ {4, D<&IDatabaseService::Get1>, "Get1"},
+ {5, D<&IDatabaseService::UpdateLatest>, "UpdateLatest"},
+ {6, D<&IDatabaseService::BuildRandom>, "BuildRandom"},
+ {7, D<&IDatabaseService::BuildDefault>, "BuildDefault"},
+ {8, D<&IDatabaseService::Get2>, "Get2"},
+ {9, D<&IDatabaseService::Get3>, "Get3"},
+ {10, D<&IDatabaseService::UpdateLatest1>, "UpdateLatest1"},
+ {11, D<&IDatabaseService::FindIndex>, "FindIndex"},
+ {12, D<&IDatabaseService::Move>, "Move"},
+ {13, D<&IDatabaseService::AddOrReplace>, "AddOrReplace"},
+ {14, D<&IDatabaseService::Delete>, "Delete"},
+ {15, D<&IDatabaseService::DestroyFile>, "DestroyFile"},
+ {16, D<&IDatabaseService::DeleteFile>, "DeleteFile"},
+ {17, D<&IDatabaseService::Format>, "Format"},
{18, nullptr, "Import"},
{19, nullptr, "Export"},
- {20, &IDatabaseService::IsBrokenDatabaseWithClearFlag, "IsBrokenDatabaseWithClearFlag"},
- {21, &IDatabaseService::GetIndex, "GetIndex"},
- {22, &IDatabaseService::SetInterfaceVersion, "SetInterfaceVersion"},
- {23, &IDatabaseService::Convert, "Convert"},
- {24, &IDatabaseService::ConvertCoreDataToCharInfo, "ConvertCoreDataToCharInfo"},
- {25, &IDatabaseService::ConvertCharInfoToCoreData, "ConvertCharInfoToCoreData"},
- {26, &IDatabaseService::Append, "Append"},
+ {20, D<&IDatabaseService::IsBrokenDatabaseWithClearFlag>, "IsBrokenDatabaseWithClearFlag"},
+ {21, D<&IDatabaseService::GetIndex>, "GetIndex"},
+ {22, D<&IDatabaseService::SetInterfaceVersion>, "SetInterfaceVersion"},
+ {23, D<&IDatabaseService::Convert>, "Convert"},
+ {24, D<&IDatabaseService::ConvertCoreDataToCharInfo>, "ConvertCoreDataToCharInfo"},
+ {25, D<&IDatabaseService::ConvertCharInfoToCoreData>, "ConvertCharInfoToCoreData"},
+ {26, D<&IDatabaseService::Append>, "Append"},
};
// clang-format on
RegisterHandlers(functions);
+ m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>(
+ "set:sys", true);
manager->Initialize(metadata);
}
private:
- void IsUpdated(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto source_flag{rp.PopRaw<SourceFlag>()};
-
+ Result IsUpdated(Out<bool> out_is_updated, SourceFlag source_flag) {
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
- const bool is_updated = manager->IsUpdated(metadata, source_flag);
+ *out_is_updated = manager->IsUpdated(metadata, source_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(is_updated);
+ R_SUCCEED();
}
- void IsFullDatabase(HLERequestContext& ctx) {
+ Result IsFullDatabase(Out<bool> out_is_full_database) {
LOG_DEBUG(Service_Mii, "called");
- const bool is_full_database = manager->IsFullDatabase();
+ *out_is_full_database = manager->IsFullDatabase();
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(is_full_database);
+ R_SUCCEED();
}
- void GetCount(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto source_flag{rp.PopRaw<SourceFlag>()};
-
- const u32 mii_count = manager->GetCount(metadata, source_flag);
+ Result GetCount(Out<u32> out_mii_count, SourceFlag source_flag) {
+ *out_mii_count = manager->GetCount(metadata, source_flag);
- LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, mii_count);
+ LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
+ *out_mii_count);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(mii_count);
+ R_SUCCEED();
}
- void Get(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto source_flag{rp.PopRaw<SourceFlag>()};
- const auto output_size{ctx.GetWriteBufferNumElements<CharInfoElement>()};
-
- u32 mii_count{};
- std::vector<CharInfoElement> char_info_elements(output_size);
- const auto result = manager->Get(metadata, char_info_elements, mii_count, source_flag);
-
- if (mii_count != 0) {
- ctx.WriteBuffer(char_info_elements);
- }
+ Result Get(Out<u32> out_mii_count, SourceFlag source_flag,
+ OutArray<CharInfoElement, BufferAttr_HipcMapAlias> char_info_element_buffer) {
+ const auto result =
+ manager->Get(metadata, char_info_element_buffer, *out_mii_count, source_flag);
- LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
- output_size, mii_count);
+ LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
+ *out_mii_count);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(mii_count);
+ R_RETURN(result);
}
- void Get1(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto source_flag{rp.PopRaw<SourceFlag>()};
- const auto output_size{ctx.GetWriteBufferNumElements<CharInfo>()};
+ Result Get1(Out<u32> out_mii_count, SourceFlag source_flag,
+ OutArray<CharInfo, BufferAttr_HipcMapAlias> char_info_buffer) {
+ const auto result = manager->Get(metadata, char_info_buffer, *out_mii_count, source_flag);
- u32 mii_count{};
- std::vector<CharInfo> char_info(output_size);
- const auto result = manager->Get(metadata, char_info, mii_count, source_flag);
+ LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
+ *out_mii_count);
- if (mii_count != 0) {
- ctx.WriteBuffer(char_info);
- }
-
- LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
- output_size, mii_count);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(mii_count);
+ R_RETURN(result);
}
- void UpdateLatest(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto char_info{rp.PopRaw<CharInfo>()};
- const auto source_flag{rp.PopRaw<SourceFlag>()};
-
+ Result UpdateLatest(Out<CharInfo> out_char_info, CharInfo& char_info, SourceFlag source_flag) {
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
- CharInfo new_char_info{};
- const auto result = manager->UpdateLatest(metadata, new_char_info, char_info, source_flag);
- if (result.IsFailure()) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
- rb.Push(ResultSuccess);
- rb.PushRaw(new_char_info);
+ R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag));
}
- void BuildRandom(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto age{rp.PopRaw<Age>()};
- const auto gender{rp.PopRaw<Gender>()};
- const auto race{rp.PopRaw<Race>()};
-
+ Result BuildRandom(Out<CharInfo> out_char_info, Age age, Gender gender, Race race) {
LOG_DEBUG(Service_Mii, "called with age={}, gender={}, race={}", age, gender, race);
- if (age > Age::All) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultInvalidArgument);
- return;
- }
-
- if (gender > Gender::All) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultInvalidArgument);
- return;
- }
-
- if (race > Race::All) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultInvalidArgument);
- return;
- }
-
- CharInfo char_info{};
- manager->BuildRandom(char_info, age, gender, race);
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
- rb.Push(ResultSuccess);
- rb.PushRaw(char_info);
- }
+ R_UNLESS(age <= Age::All, ResultInvalidArgument);
+ R_UNLESS(gender <= Gender::All, ResultInvalidArgument);
+ R_UNLESS(race <= Race::All, ResultInvalidArgument);
- void BuildDefault(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto index{rp.Pop<u32>()};
+ manager->BuildRandom(*out_char_info, age, gender, race);
- LOG_DEBUG(Service_Mii, "called with index={}", index);
+ R_SUCCEED();
+ }
- if (index > 5) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultInvalidArgument);
- return;
- }
+ Result BuildDefault(Out<CharInfo> out_char_info, s32 index) {
+ LOG_DEBUG(Service_Mii, "called with index={}", index);
+ R_UNLESS(index < static_cast<s32>(RawData::DefaultMii.size()), ResultInvalidArgument);
- CharInfo char_info{};
- manager->BuildDefault(char_info, index);
+ manager->BuildDefault(*out_char_info, index);
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
- rb.Push(ResultSuccess);
- rb.PushRaw(char_info);
+ R_SUCCEED();
}
- void Get2(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto source_flag{rp.PopRaw<SourceFlag>()};
- const auto output_size{ctx.GetWriteBufferNumElements<StoreDataElement>()};
+ Result Get2(Out<u32> out_mii_count, SourceFlag source_flag,
+ OutArray<StoreDataElement, BufferAttr_HipcMapAlias> store_data_element_buffer) {
+ const auto result =
+ manager->Get(metadata, store_data_element_buffer, *out_mii_count, source_flag);
- u32 mii_count{};
- std::vector<StoreDataElement> store_data_elements(output_size);
- const auto result = manager->Get(metadata, store_data_elements, mii_count, source_flag);
+ LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
+ *out_mii_count);
- if (mii_count != 0) {
- ctx.WriteBuffer(store_data_elements);
- }
-
- LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
- output_size, mii_count);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(mii_count);
+ R_RETURN(result);
}
- void Get3(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto source_flag{rp.PopRaw<SourceFlag>()};
- const auto output_size{ctx.GetWriteBufferNumElements<StoreData>()};
-
- u32 mii_count{};
- std::vector<StoreData> store_data(output_size);
- const auto result = manager->Get(metadata, store_data, mii_count, source_flag);
+ Result Get3(Out<u32> out_mii_count, SourceFlag source_flag,
+ OutArray<StoreData, BufferAttr_HipcMapAlias> store_data_buffer) {
+ const auto result = manager->Get(metadata, store_data_buffer, *out_mii_count, source_flag);
- if (mii_count != 0) {
- ctx.WriteBuffer(store_data);
- }
+ LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
+ *out_mii_count);
- LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
- output_size, mii_count);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(mii_count);
+ R_RETURN(result);
}
- void UpdateLatest1(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto store_data{rp.PopRaw<StoreData>()};
- const auto source_flag{rp.PopRaw<SourceFlag>()};
-
+ Result UpdateLatest1(Out<StoreData> out_store_data, StoreData& store_data,
+ SourceFlag source_flag) {
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
+ R_UNLESS(is_system, ResultPermissionDenied);
- Result result = ResultSuccess;
- if (!is_system) {
- result = ResultPermissionDenied;
- }
-
- StoreData new_store_data{};
- if (result.IsSuccess()) {
- result = manager->UpdateLatest(metadata, new_store_data, store_data, source_flag);
- }
-
- if (result.IsFailure()) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(StoreData) / sizeof(u32)};
- rb.Push(ResultSuccess);
- rb.PushRaw<StoreData>(new_store_data);
+ R_RETURN(manager->UpdateLatest(metadata, *out_store_data, store_data, source_flag));
}
- void FindIndex(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto create_id{rp.PopRaw<Common::UUID>()};
- const auto is_special{rp.PopRaw<bool>()};
-
+ Result FindIndex(Out<s32> out_index, Common::UUID create_id, bool is_special) {
LOG_INFO(Service_Mii, "called with create_id={}, is_special={}",
create_id.FormattedString(), is_special);
- const s32 index = manager->FindIndex(create_id, is_special);
+ *out_index = manager->FindIndex(create_id, is_special);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(index);
+ R_SUCCEED();
}
- void Move(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto create_id{rp.PopRaw<Common::UUID>()};
- const auto new_index{rp.PopRaw<s32>()};
-
+ Result Move(Common::UUID create_id, s32 new_index) {
LOG_INFO(Service_Mii, "called with create_id={}, new_index={}", create_id.FormattedString(),
new_index);
+ R_UNLESS(is_system, ResultPermissionDenied);
- Result result = ResultSuccess;
- if (!is_system) {
- result = ResultPermissionDenied;
- }
+ const u32 count = manager->GetCount(metadata, SourceFlag::Database);
- if (result.IsSuccess()) {
- const u32 count = manager->GetCount(metadata, SourceFlag::Database);
- if (new_index < 0 || new_index >= static_cast<s32>(count)) {
- result = ResultInvalidArgument;
- }
- }
+ R_UNLESS(new_index >= 0 && new_index < static_cast<s32>(count), ResultInvalidArgument);
- if (result.IsSuccess()) {
- result = manager->Move(metadata, new_index, create_id);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(manager->Move(metadata, new_index, create_id));
}
- void AddOrReplace(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto store_data{rp.PopRaw<StoreData>()};
-
+ Result AddOrReplace(StoreData& store_data) {
LOG_INFO(Service_Mii, "called");
+ R_UNLESS(is_system, ResultPermissionDenied);
- Result result = ResultSuccess;
-
- if (!is_system) {
- result = ResultPermissionDenied;
- }
+ const auto result = manager->AddOrReplace(metadata, store_data);
- if (result.IsSuccess()) {
- result = manager->AddOrReplace(metadata, store_data);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(result);
}
- void Delete(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto create_id{rp.PopRaw<Common::UUID>()};
-
+ Result Delete(Common::UUID create_id) {
LOG_INFO(Service_Mii, "called, create_id={}", create_id.FormattedString());
+ R_UNLESS(is_system, ResultPermissionDenied);
- Result result = ResultSuccess;
-
- if (!is_system) {
- result = ResultPermissionDenied;
- }
-
- if (result.IsSuccess()) {
- result = manager->Delete(metadata, create_id);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(manager->Delete(metadata, create_id));
}
- void DestroyFile(HLERequestContext& ctx) {
- // This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled");
- const bool is_db_test_mode_enabled = false;
+ Result DestroyFile() {
+ bool is_db_test_mode_enabled{};
+ m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
+ R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
- Result result = ResultSuccess;
-
- if (!is_db_test_mode_enabled) {
- result = ResultTestModeOnly;
- }
-
- if (result.IsSuccess()) {
- result = manager->DestroyFile(metadata);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(manager->DestroyFile(metadata));
}
- void DeleteFile(HLERequestContext& ctx) {
- // This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled");
- const bool is_db_test_mode_enabled = false;
+ Result DeleteFile() {
+ bool is_db_test_mode_enabled{};
+ m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
+ R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
- Result result = ResultSuccess;
-
- if (!is_db_test_mode_enabled) {
- result = ResultTestModeOnly;
- }
-
- if (result.IsSuccess()) {
- result = manager->DeleteFile();
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(manager->DeleteFile());
}
- void Format(HLERequestContext& ctx) {
- // This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled");
- const bool is_db_test_mode_enabled = false;
+ Result Format() {
+ bool is_db_test_mode_enabled{};
+ m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
+ R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
- Result result = ResultSuccess;
-
- if (!is_db_test_mode_enabled) {
- result = ResultTestModeOnly;
- }
-
- if (result.IsSuccess()) {
- result = manager->Format(metadata);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(manager->Format(metadata));
}
- void IsBrokenDatabaseWithClearFlag(HLERequestContext& ctx) {
+ Result IsBrokenDatabaseWithClearFlag(Out<bool> out_is_broken_with_clear_flag) {
LOG_DEBUG(Service_Mii, "called");
+ R_UNLESS(is_system, ResultPermissionDenied);
- bool is_broken_with_clear_flag = false;
- Result result = ResultSuccess;
+ *out_is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata);
- if (!is_system) {
- result = ResultPermissionDenied;
- }
-
- if (result.IsSuccess()) {
- is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata);
- }
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push<u8>(is_broken_with_clear_flag);
+ R_SUCCEED();
}
- void GetIndex(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto info{rp.PopRaw<CharInfo>()};
-
+ Result GetIndex(Out<s32> out_index, CharInfo& char_info) {
LOG_DEBUG(Service_Mii, "called");
- s32 index{};
- const auto result = manager->GetIndex(metadata, info, index);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(index);
+ R_RETURN(manager->GetIndex(metadata, char_info, *out_index));
}
- void SetInterfaceVersion(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto interface_version{rp.PopRaw<u32>()};
-
+ Result SetInterfaceVersion(u32 interface_version) {
LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version);
manager->SetInterfaceVersion(metadata, interface_version);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
- void Convert(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto mii_v3{rp.PopRaw<Ver3StoreData>()};
-
+ Result Convert(Out<CharInfo> out_char_info, Ver3StoreData& mii_v3) {
LOG_INFO(Service_Mii, "called");
- CharInfo char_info{};
- const auto result = manager->ConvertV3ToCharInfo(char_info, mii_v3);
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
- rb.Push(result);
- rb.PushRaw<CharInfo>(char_info);
+ R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3));
}
- void ConvertCoreDataToCharInfo(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto core_data{rp.PopRaw<CoreData>()};
-
+ Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, CoreData& core_data) {
LOG_INFO(Service_Mii, "called");
- CharInfo char_info{};
- const auto result = manager->ConvertCoreDataToCharInfo(char_info, core_data);
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
- rb.Push(result);
- rb.PushRaw<CharInfo>(char_info);
+ R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data));
}
- void ConvertCharInfoToCoreData(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto char_info{rp.PopRaw<CharInfo>()};
-
+ Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, CharInfo& char_info) {
LOG_INFO(Service_Mii, "called");
- CoreData core_data{};
- const auto result = manager->ConvertCharInfoToCoreData(core_data, char_info);
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(CoreData) / sizeof(u32)};
- rb.Push(result);
- rb.PushRaw<CoreData>(core_data);
+ R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info));
}
- void Append(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto char_info{rp.PopRaw<CharInfo>()};
-
+ Result Append(CharInfo& char_info) {
LOG_INFO(Service_Mii, "called");
- const auto result = manager->Append(metadata, char_info);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(manager->Append(metadata, char_info));
}
std::shared_ptr<MiiManager> manager = nullptr;
DatabaseSessionMetadata metadata{};
bool is_system{};
+
+ std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
};
-MiiDBModule::MiiDBModule(Core::System& system_, const char* name_,
- std::shared_ptr<MiiManager> mii_manager, bool is_system_)
+IStaticService::IStaticService(Core::System& system_, const char* name_,
+ std::shared_ptr<MiiManager> mii_manager, bool is_system_)
: ServiceFramework{system_, name_}, manager{mii_manager}, is_system{is_system_} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
+ {0, D<&IStaticService::GetDatabaseService>, "GetDatabaseService"},
};
// clang-format on
RegisterHandlers(functions);
-
- if (manager == nullptr) {
- manager = std::make_shared<MiiManager>();
- }
}
-MiiDBModule::~MiiDBModule() = default;
-
-void MiiDBModule::GetDatabaseService(HLERequestContext& ctx) {
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IDatabaseService>(system, manager, is_system);
+IStaticService::~IStaticService() = default;
+Result IStaticService::GetDatabaseService(
+ Out<SharedPointer<IDatabaseService>> out_database_service) {
LOG_DEBUG(Service_Mii, "called");
+
+ *out_database_service = std::make_shared<IDatabaseService>(system, manager, is_system);
+
+ R_SUCCEED();
}
-std::shared_ptr<MiiManager> MiiDBModule::GetMiiManager() {
+std::shared_ptr<MiiManager> IStaticService::GetMiiManager() {
return manager;
}
-class MiiImg final : public ServiceFramework<MiiImg> {
+class IImageDatabaseService final : public ServiceFramework<IImageDatabaseService> {
public:
- explicit MiiImg(Core::System& system_) : ServiceFramework{system_, "miiimg"} {
+ explicit IImageDatabaseService(Core::System& system_) : ServiceFramework{system_, "miiimg"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &MiiImg::Initialize, "Initialize"},
+ {0, D<&IImageDatabaseService::Initialize>, "Initialize"},
{10, nullptr, "Reload"},
- {11, &MiiImg::GetCount, "GetCount"},
+ {11, D<&IImageDatabaseService::GetCount>, "GetCount"},
{12, nullptr, "IsEmpty"},
{13, nullptr, "IsFull"},
{14, nullptr, "GetAttribute"},
@@ -585,31 +341,30 @@ public:
}
private:
- void Initialize(HLERequestContext& ctx) {
+ Result Initialize() {
LOG_INFO(Service_Mii, "called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
- void GetCount(HLERequestContext& ctx) {
+ Result GetCount(Out<u32> out_count) {
LOG_DEBUG(Service_Mii, "called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(0);
+ *out_count = 0;
+
+ R_SUCCEED();
}
};
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- std::shared_ptr<MiiManager> manager = nullptr;
+ std::shared_ptr<MiiManager> manager = std::make_shared<MiiManager>();
server_manager->RegisterNamedService(
- "mii:e", std::make_shared<MiiDBModule>(system, "mii:e", manager, true));
+ "mii:e", std::make_shared<IStaticService>(system, "mii:e", manager, true));
server_manager->RegisterNamedService(
- "mii:u", std::make_shared<MiiDBModule>(system, "mii:u", manager, false));
- server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system));
+ "mii:u", std::make_shared<IStaticService>(system, "mii:u", manager, false));
+ server_manager->RegisterNamedService("miiimg", std::make_shared<IImageDatabaseService>(system));
ServerManager::RunServer(std::move(server_manager));
}
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 @@
#pragma once
-#include "core/hle/service/service.h"
+#include "core/hle/service/cmif_types.h"
namespace Core {
class System;
@@ -11,19 +11,20 @@ class System;
namespace Service::Mii {
class MiiManager;
+class IDatabaseService;
-class MiiDBModule final : public ServiceFramework<MiiDBModule> {
+class IStaticService final : public ServiceFramework<IStaticService> {
public:
- explicit MiiDBModule(Core::System& system_, const char* name_,
- std::shared_ptr<MiiManager> mii_manager, bool is_system_);
- ~MiiDBModule() override;
+ explicit IStaticService(Core::System& system_, const char* name_,
+ std::shared_ptr<MiiManager> mii_manager, bool is_system_);
+ ~IStaticService() override;
std::shared_ptr<MiiManager> GetMiiManager();
private:
- void GetDatabaseService(HLERequestContext& ctx);
+ Result GetDatabaseService(Out<SharedPointer<IDatabaseService>> out_database_service);
- std::shared_ptr<MiiManager> manager = nullptr;
+ std::shared_ptr<MiiManager> manager{nullptr};
bool is_system{};
};
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 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "common/settings.h"
#include "core/hle/service/set/setting_formats/system_settings.h"
namespace Service::Set {
@@ -52,6 +53,17 @@ SystemSettings DefaultSystemSettings() {
settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0;
settings.vibration_master_volume = 1.0f;
+ const auto language_code =
+ available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
+ const auto key_code =
+ std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
+ [=](const auto& element) { return element.first == language_code; });
+
+ settings.keyboard_layout = KeyboardLayout::EnglishUs;
+ if (key_code != language_to_layout.end()) {
+ settings.keyboard_layout = key_code->second;
+ }
+
return settings;
}
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 {
// nn::settings::system::AudioVolume
std::array<u8, 0x8> audio_volume_type0;
std::array<u8, 0x8> audio_volume_type1;
- // nn::settings::system::AudioOutputMode
- s32 audio_output_mode_type0;
- s32 audio_output_mode_type1;
- s32 audio_output_mode_type2;
+ AudioOutputMode audio_output_mode_hdmi;
+ AudioOutputMode audio_output_mode_speaker;
+ AudioOutputMode audio_output_mode_headphone;
bool force_mute_on_headphone_removed;
INSERT_PADDING_BYTES(0x3);
s32 headphone_volume_warning_count;
@@ -224,9 +223,8 @@ struct SystemSettings {
INSERT_PADDING_BYTES(0x3);
// nn::settings::system::AudioVolume
std::array<u8, 0x8> audio_volume_type2;
- // nn::settings::system::AudioOutputMode
- s32 audio_output_mode_type3;
- s32 audio_output_mode_type4;
+ AudioOutputMode audio_output_mode_type3;
+ AudioOutputMode audio_output_mode_type4;
bool hearing_protection_safeguard_flag;
INSERT_PADDING_BYTES(0x3);
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 {
/// This is nn::settings::system::AudioOutputModeTarget
enum class AudioOutputModeTarget : u32 {
+ None,
Hdmi,
Speaker,
Headphone,
+ Type3,
+ Type4,
};
/// This is nn::settings::system::AudioVolumeTarget
@@ -367,6 +370,12 @@ struct AccountNotificationSettings {
static_assert(sizeof(AccountNotificationSettings) == 0x18,
"AccountNotificationSettings is an invalid size");
+/// This is nn::settings::factory::BatteryLot
+struct BatteryLot {
+ std::array<char, 0x18> lot_number;
+};
+static_assert(sizeof(BatteryLot) == 0x18, "BatteryLot is an invalid size");
+
/// This is nn::settings::system::EulaVersion
struct EulaVersion {
u32 version;
@@ -436,6 +445,12 @@ struct NotificationSettings {
};
static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size");
+/// This is nn::settings::factory::SerialNumber
+struct SerialNumber {
+ std::array<char, 0x18> serial_number;
+};
+static_assert(sizeof(SerialNumber) == 0x18, "SerialNumber is an invalid size");
+
/// This is nn::settings::system::SleepSettings
struct SleepSettings {
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 @@
namespace Service::Set {
namespace {
-constexpr u32 SETTINGS_VERSION{1u};
+constexpr u32 SETTINGS_VERSION{2u};
constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't');
struct SettingsHeader {
u64 magic;
@@ -131,10 +131,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"},
{41, nullptr, "GetEdid"},
{42, nullptr, "SetEdid"},
- {43, nullptr, "GetAudioOutputMode"},
- {44, nullptr, "SetAudioOutputMode"},
- {45, &ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved, "IsForceMuteOnHeadphoneRemoved"},
- {46, &ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved, "SetForceMuteOnHeadphoneRemoved"},
+ {43, &ISystemSettingsServer::GetAudioOutputMode, "GetAudioOutputMode"},
+ {44, &ISystemSettingsServer::SetAudioOutputMode, "SetAudioOutputMode"},
+ {45, &ISystemSettingsServer::GetSpeakerAutoMuteFlag , "GetSpeakerAutoMuteFlag"},
+ {46, &ISystemSettingsServer::SetSpeakerAutoMuteFlag , "SetSpeakerAutoMuteFlag"},
{47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"},
{48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"},
{49, nullptr, "GetDataDeletionSettings"},
@@ -155,8 +155,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"},
{65, nullptr, "GetUsb30EnableFlag"},
{66, nullptr, "SetUsb30EnableFlag"},
- {67, nullptr, "GetBatteryLot"},
- {68, nullptr, "GetSerialNumber"},
+ {67, &ISystemSettingsServer::GetBatteryLot, "GetBatteryLot"},
+ {68, &ISystemSettingsServer::GetSerialNumber, "GetSerialNumber"},
{69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"},
{70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"},
{71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"},
@@ -184,11 +184,11 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
{94, nullptr, "GetFatalDirtyFlags"},
{95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
- {96, nullptr, "SetAutoUpdateEnableFlag"},
+ {96, &ISystemSettingsServer::SetAutoUpdateEnableFlag, "SetAutoUpdateEnableFlag"},
{97, nullptr, "GetNxControllerSettings"},
{98, nullptr, "SetNxControllerSettings"},
{99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
- {100, nullptr, "SetBatteryPercentageFlag"},
+ {100, &ISystemSettingsServer::SetBatteryPercentageFlag, "SetBatteryPercentageFlag"},
{101, nullptr, "GetExternalRtcResetFlag"},
{102, nullptr, "SetExternalRtcResetFlag"},
{103, nullptr, "GetUsbFullKeyEnableFlag"},
@@ -208,12 +208,12 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{117, nullptr, "GetHeadphoneVolumeUpdateFlag"},
{118, nullptr, "SetHeadphoneVolumeUpdateFlag"},
{119, nullptr, "NeedsToUpdateHeadphoneVolume"},
- {120, nullptr, "GetPushNotificationActivityModeOnSleep"},
- {121, nullptr, "SetPushNotificationActivityModeOnSleep"},
+ {120, &ISystemSettingsServer::GetPushNotificationActivityModeOnSleep, "GetPushNotificationActivityModeOnSleep"},
+ {121, &ISystemSettingsServer::SetPushNotificationActivityModeOnSleep, "SetPushNotificationActivityModeOnSleep"},
{122, nullptr, "GetServiceDiscoveryControlSettings"},
{123, nullptr, "SetServiceDiscoveryControlSettings"},
{124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
- {125, nullptr, "SetErrorReportSharePermission"},
+ {125, &ISystemSettingsServer::SetErrorReportSharePermission, "SetErrorReportSharePermission"},
{126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
{127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
@@ -225,7 +225,7 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
{136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"},
- {137, nullptr, "SetKeyboardLayout"},
+ {137, &ISystemSettingsServer::SetKeyboardLayout, "SetKeyboardLayout"},
{138, nullptr, "GetWebInspectorFlag"},
{139, nullptr, "GetAllowedSslHosts"},
{140, nullptr, "GetHostFsMountPoint"},
@@ -291,8 +291,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{200, nullptr, "SetButtonConfigRegisteredSettings"},
{201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"},
{202, nullptr, "SetFieldTestingFlag"},
- {203, nullptr, "GetPanelCrcMode"},
- {204, nullptr, "SetPanelCrcMode"},
+ {203, &ISystemSettingsServer::GetPanelCrcMode, "GetPanelCrcMode"},
+ {204, &ISystemSettingsServer::SetPanelCrcMode, "SetPanelCrcMode"},
{205, nullptr, "GetNxControllerSettingsEx"},
{206, nullptr, "SetNxControllerSettingsEx"},
{207, nullptr, "GetHearingProtectionSafeguardFlag"},
@@ -349,7 +349,7 @@ bool ISystemSettingsServer::LoadSettingsFile(std::filesystem::path& path, auto&&
}
SettingsHeader hdr{};
file.read(reinterpret_cast<char*>(&hdr), sizeof(hdr));
- return hdr.magic == SETTINGS_MAGIC && hdr.version == SETTINGS_VERSION;
+ return hdr.magic == SETTINGS_MAGIC && hdr.version >= SETTINGS_VERSION;
};
if (!exists || !file_size_ok) {
@@ -390,7 +390,7 @@ bool ISystemSettingsServer::StoreSettingsFile(std::filesystem::path& path, auto&
}
auto settings_base = path / "settings";
- auto settings_tmp_file = settings_base;
+ std::filesystem::path settings_tmp_file = settings_base;
settings_tmp_file = settings_tmp_file.replace_extension("tmp");
std::ofstream file(settings_tmp_file, std::ios::binary | std::ios::out);
if (!file.is_open()) {
@@ -722,6 +722,9 @@ static Settings GetSettings() {
ret["hid_debug"]["disabled_features_per_id"] = std::vector<u8>(0xa8);
ret["hid_debug"]["touch_firmware_auto_update_disabled"] = ToBytes(bool{false});
+ // Mii
+ ret["mii"]["is_db_test_mode_enabled"] = ToBytes(bool{false});
+
// Settings
ret["settings_debug"]["is_debug_mode_enabled"] = ToBytes(bool{false});
@@ -814,7 +817,34 @@ void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
-void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) {
+void ISystemSettingsServer::GetAudioOutputMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto target{rp.PopEnum<AudioOutputModeTarget>()};
+
+ AudioOutputMode output_mode{};
+ const auto result = GetAudioOutputMode(output_mode, target);
+
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(result);
+ rb.PushEnum(output_mode);
+}
+
+void ISystemSettingsServer::SetAudioOutputMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto target{rp.PopEnum<AudioOutputModeTarget>()};
+ const auto output_mode{rp.PopEnum<AudioOutputMode>()};
+
+ const auto result = SetAudioOutputMode(target, output_mode);
+
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void ISystemSettingsServer::GetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}",
m_system_settings.force_mute_on_headphone_removed);
@@ -823,7 +853,7 @@ void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx
rb.PushRaw(m_system_settings.force_mute_on_headphone_removed);
}
-void ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) {
+void ISystemSettingsServer::SetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>();
SetSaveNeeded();
@@ -966,6 +996,26 @@ void ISystemSettingsServer::SetPrimaryAlbumStorage(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
+void ISystemSettingsServer::GetBatteryLot(HLERequestContext& ctx) {
+ BatteryLot battery_lot = {"YUZUEMULATOR123456789"};
+
+ LOG_INFO(Service_SET, "called");
+
+ IPC::ResponseBuilder rb{ctx, 8};
+ rb.Push(ResultSuccess);
+ rb.PushRaw(battery_lot);
+}
+
+void ISystemSettingsServer::GetSerialNumber(HLERequestContext& ctx) {
+ SerialNumber console_serial = {"YUZ10012345678"};
+
+ LOG_INFO(Service_SET, "called");
+
+ IPC::ResponseBuilder rb{ctx, 8};
+ rb.Push(ResultSuccess);
+ rb.PushRaw(console_serial);
+}
+
void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag);
@@ -1129,6 +1179,17 @@ void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
rb.Push(m_system_settings.auto_update_enable_flag);
}
+void ISystemSettingsServer::SetAutoUpdateEnableFlag(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ m_system_settings.auto_update_enable_flag = rp.Pop<bool>();
+ SetSaveNeeded();
+
+ LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}",
m_system_settings.battery_percentage_flag);
@@ -1138,6 +1199,18 @@ void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
rb.Push(m_system_settings.battery_percentage_flag);
}
+void ISystemSettingsServer::SetBatteryPercentageFlag(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ m_system_settings.battery_percentage_flag = rp.Pop<bool>();
+ SetSaveNeeded();
+
+ LOG_INFO(Service_SET, "called, battery_percentage_flag={}",
+ m_system_settings.battery_percentage_flag);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called.");
@@ -1161,6 +1234,27 @@ void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestConte
rb.Push(offset);
}
+void ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
+ LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
+ m_system_settings.push_notification_activity_mode_on_sleep);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(m_system_settings.push_notification_activity_mode_on_sleep);
+}
+
+void ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ m_system_settings.push_notification_activity_mode_on_sleep = rp.Pop<s32>();
+ SetSaveNeeded();
+
+ LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
+ m_system_settings.push_notification_activity_mode_on_sleep);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, error_report_share_permission={}",
m_system_settings.error_report_share_permission);
@@ -1170,6 +1264,18 @@ void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx
rb.PushEnum(m_system_settings.error_report_share_permission);
}
+void ISystemSettingsServer::SetErrorReportSharePermission(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ m_system_settings.error_report_share_permission = rp.PopEnum<ErrorReportSharePermission>();
+ SetSaveNeeded();
+
+ LOG_INFO(Service_SET, "called, error_report_share_permission={}",
+ m_system_settings.error_report_share_permission);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag);
@@ -1190,22 +1296,22 @@ void ISystemSettingsServer::SetAppletLaunchFlags(HLERequestContext& ctx) {
}
void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) {
- const auto language_code =
- available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
- const auto key_code =
- std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
- [=](const auto& element) { return element.first == language_code; });
-
- KeyboardLayout selected_keyboard_layout = KeyboardLayout::EnglishUs;
- if (key_code != language_to_layout.end()) {
- selected_keyboard_layout = key_code->second;
- }
-
- LOG_INFO(Service_SET, "called, selected_keyboard_layout={}", selected_keyboard_layout);
+ LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
- rb.Push(static_cast<u32>(selected_keyboard_layout));
+ rb.Push(static_cast<u32>(m_system_settings.keyboard_layout));
+}
+
+void ISystemSettingsServer::SetKeyboardLayout(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ m_system_settings.keyboard_layout = rp.PopRaw<KeyboardLayout>();
+ SetSaveNeeded();
+
+ LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
@@ -1297,6 +1403,25 @@ void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) {
rb.Push(m_system_settings.field_testing_flag);
}
+void ISystemSettingsServer::GetPanelCrcMode(HLERequestContext& ctx) {
+ LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(m_system_settings.panel_crc_mode);
+}
+
+void ISystemSettingsServer::SetPanelCrcMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ m_system_settings.panel_crc_mode = rp.PopRaw<s32>();
+ SetSaveNeeded();
+
+ LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
void ISystemSettingsServer::SetupSettings() {
auto system_dir =
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050";
@@ -1387,6 +1512,66 @@ Result ISystemSettingsServer::SetVibrationMasterVolume(f32 volume) {
R_SUCCEED();
}
+Result ISystemSettingsServer::GetAudioOutputMode(AudioOutputMode& out_output_mode,
+ AudioOutputModeTarget target) const {
+ switch (target) {
+ case AudioOutputModeTarget::Hdmi:
+ out_output_mode = m_system_settings.audio_output_mode_hdmi;
+ break;
+ case AudioOutputModeTarget::Speaker:
+ out_output_mode = m_system_settings.audio_output_mode_speaker;
+ break;
+ case AudioOutputModeTarget::Headphone:
+ out_output_mode = m_system_settings.audio_output_mode_headphone;
+ break;
+ case AudioOutputModeTarget::Type3:
+ out_output_mode = m_system_settings.audio_output_mode_type3;
+ break;
+ case AudioOutputModeTarget::Type4:
+ out_output_mode = m_system_settings.audio_output_mode_type4;
+ break;
+ default:
+ LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
+ }
+ R_SUCCEED();
+}
+
+Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target,
+ AudioOutputMode output_mode) {
+ switch (target) {
+ case AudioOutputModeTarget::Hdmi:
+ m_system_settings.audio_output_mode_hdmi = output_mode;
+ break;
+ case AudioOutputModeTarget::Speaker:
+ m_system_settings.audio_output_mode_speaker = output_mode;
+ break;
+ case AudioOutputModeTarget::Headphone:
+ m_system_settings.audio_output_mode_headphone = output_mode;
+ break;
+ case AudioOutputModeTarget::Type3:
+ m_system_settings.audio_output_mode_type3 = output_mode;
+ break;
+ case AudioOutputModeTarget::Type4:
+ m_system_settings.audio_output_mode_type4 = output_mode;
+ break;
+ default:
+ LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
+ }
+ SetSaveNeeded();
+ R_SUCCEED();
+}
+
+Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(bool& is_auto_mute) const {
+ is_auto_mute = m_system_settings.force_mute_on_headphone_removed;
+ R_SUCCEED();
+}
+
+Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool is_auto_mute) {
+ m_system_settings.force_mute_on_headphone_removed = is_auto_mute;
+ SetSaveNeeded();
+ R_SUCCEED();
+}
+
Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const {
out_id = m_private_settings.external_clock_source_id;
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:
Result GetVibrationMasterVolume(f32& out_volume) const;
Result SetVibrationMasterVolume(f32 volume);
+ Result GetAudioOutputMode(AudioOutputMode& out_output_mode, AudioOutputModeTarget target) const;
+ Result SetAudioOutputMode(AudioOutputModeTarget target, AudioOutputMode output_mode);
+ Result GetSpeakerAutoMuteFlag(bool& is_auto_mute) const;
+ Result SetSpeakerAutoMuteFlag(bool auto_mute);
Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const;
Result SetExternalSteadyClockSourceId(const Common::UUID& id);
Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const;
@@ -97,8 +101,10 @@ private:
void GetSettingsItemValue(HLERequestContext& ctx);
void GetTvSettings(HLERequestContext& ctx);
void SetTvSettings(HLERequestContext& ctx);
- void IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx);
- void SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx);
+ void GetAudioOutputMode(HLERequestContext& ctx);
+ void SetAudioOutputMode(HLERequestContext& ctx);
+ void GetSpeakerAutoMuteFlag(HLERequestContext& ctx);
+ void SetSpeakerAutoMuteFlag(HLERequestContext& ctx);
void GetDebugModeFlag(HLERequestContext& ctx);
void GetQuestFlag(HLERequestContext& ctx);
void SetQuestFlag(HLERequestContext& ctx);
@@ -111,6 +117,8 @@ private:
void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
void GetPrimaryAlbumStorage(HLERequestContext& ctx);
void SetPrimaryAlbumStorage(HLERequestContext& ctx);
+ void GetBatteryLot(HLERequestContext& ctx);
+ void GetSerialNumber(HLERequestContext& ctx);
void GetNfcEnableFlag(HLERequestContext& ctx);
void SetNfcEnableFlag(HLERequestContext& ctx);
void GetSleepSettings(HLERequestContext& ctx);
@@ -126,13 +134,19 @@ private:
void SetBluetoothEnableFlag(HLERequestContext& ctx);
void GetMiiAuthorId(HLERequestContext& ctx);
void GetAutoUpdateEnableFlag(HLERequestContext& ctx);
+ void SetAutoUpdateEnableFlag(HLERequestContext& ctx);
void GetBatteryPercentageFlag(HLERequestContext& ctx);
+ void SetBatteryPercentageFlag(HLERequestContext& ctx);
void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
+ void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
+ void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
void GetErrorReportSharePermission(HLERequestContext& ctx);
+ void SetErrorReportSharePermission(HLERequestContext& ctx);
void GetAppletLaunchFlags(HLERequestContext& ctx);
void SetAppletLaunchFlags(HLERequestContext& ctx);
void GetKeyboardLayout(HLERequestContext& ctx);
+ void SetKeyboardLayout(HLERequestContext& ctx);
void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
@@ -141,6 +155,8 @@ private:
void GetHomeMenuScheme(HLERequestContext& ctx);
void GetHomeMenuSchemeModel(HLERequestContext& ctx);
void GetFieldTestingFlag(HLERequestContext& ctx);
+ void GetPanelCrcMode(HLERequestContext& ctx);
+ void SetPanelCrcMode(HLERequestContext& ctx);
bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func);
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() {
keyboard->SetAppletResource(applet_resource, &shared_mutex);
const auto settings =
- system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys");
+ system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, settings);
six_axis->SetAppletResource(applet_resource, &shared_mutex);
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 @@
namespace Service::HID {
HidFirmwareSettings::HidFirmwareSettings(Core::System& system) {
- m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys");
+ m_set_sys =
+ system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
LoadSettings(true);
}
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) {
}
void ConfigureGraphics::UpdateVsyncSetting() const {
+ const Settings::RendererBackend backend{GetCurrentGraphicsBackend()};
+ if (backend == Settings::RendererBackend::Null) {
+ return;
+ }
+
const auto mode = vsync_mode_combobox_enum_map[vsync_mode_combobox->currentIndex()];
const auto vsync_mode = PresentModeToSetting(mode);
Settings::values.vsync_mode.SetValue(vsync_mode);