Compare commits
30 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e93537266 | ||
|
|
6a2532fe17 | ||
|
|
3655115105 | ||
|
|
5561a08d59 | ||
|
|
e687ca8735 | ||
|
|
0bf46cb1ee | ||
|
|
72c897c49d | ||
|
|
077a50a547 | ||
|
|
820f1c8a16 | ||
|
|
b163757e1f | ||
|
|
b75401a2cb | ||
|
|
12e7ee2357 | ||
|
|
3ec41503e3 | ||
|
|
c770af9b12 | ||
|
|
2d8f80b65e | ||
|
|
6c4eb2733d | ||
|
|
d5e8c9d04f | ||
|
|
3f1290cee3 | ||
|
|
5a20d07c21 | ||
|
|
9f91d310c6 | ||
|
|
6527c0d2fc | ||
|
|
ce2eb6e8ee | ||
|
|
8b47465586 | ||
|
|
3065ab0fd8 | ||
|
|
a2407a2964 | ||
|
|
16b79df836 | ||
|
|
6a4b25699d | ||
|
|
c5e88c654e | ||
|
|
e231b8b6f5 | ||
|
|
68fe1e3476 |
2
externals/nx_tzdb/CMakeLists.txt
vendored
2
externals/nx_tzdb/CMakeLists.txt
vendored
@@ -32,7 +32,7 @@ set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip")
|
||||
|
||||
set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb")
|
||||
|
||||
if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ARCHIVE})
|
||||
if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR})
|
||||
set(NX_TZDB_DOWNLOAD_URL "https://github.com/lat9nq/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
|
||||
|
||||
message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...")
|
||||
|
||||
4
externals/nx_tzdb/NxTzdbCreateHeader.cmake
vendored
4
externals/nx_tzdb/NxTzdbCreateHeader.cmake
vendored
@@ -11,6 +11,10 @@ execute_process(
|
||||
WORKING_DIRECTORY ${ZONE_PATH}
|
||||
OUTPUT_VARIABLE FILE_LIST)
|
||||
|
||||
if (NOT FILE_LIST)
|
||||
message(FATAL_ERROR "No timezone files found in directory ${ZONE_PATH}, did the download fail?")
|
||||
endif()
|
||||
|
||||
set(DIRECTORY_NAME ${HEADER_NAME})
|
||||
|
||||
set(FILE_DATA "")
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -301,6 +301,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
|
||||
R.id.menu_exit -> {
|
||||
emulationState.stop()
|
||||
NativeConfig.reloadGlobalConfig()
|
||||
emulationViewModel.setIsEmulationStopping(true)
|
||||
binding.drawerLayout.close()
|
||||
binding.inGameMenu.requestFocus()
|
||||
@@ -423,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()
|
||||
@@ -434,7 +463,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
|
||||
updateScreenLayout()
|
||||
|
||||
emulationState.run(emulationActivity!!.isActivityRecreated)
|
||||
emulationState.run(emulationActivity!!.isActivityRecreated, programIndex)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -832,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.
|
||||
@@ -877,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
|
||||
@@ -888,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?) {
|
||||
@@ -931,7 +971,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
private fun runWithValidSurface() {
|
||||
private fun runWithValidSurface(programIndex: Int = 0) {
|
||||
NativeLibrary.surfaceChanged(surface)
|
||||
if (!emulationCanStart.invoke()) {
|
||||
return
|
||||
@@ -939,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()
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -19,6 +19,7 @@ jmethodID GetExitEmulationActivity();
|
||||
jmethodID GetDiskCacheLoadProgress();
|
||||
jmethodID GetOnEmulationStarted();
|
||||
jmethodID GetOnEmulationStopped();
|
||||
jmethodID GetOnProgramChanged();
|
||||
|
||||
jclass GetGameClass();
|
||||
jmethodID GetGameConstructor();
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -15,25 +15,34 @@ namespace Common {
|
||||
|
||||
#if _MSC_VER
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
|
||||
template <typename T>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected);
|
||||
template <typename T>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual);
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected) {
|
||||
const u8 result =
|
||||
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
|
||||
return result == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected) {
|
||||
const u16 result =
|
||||
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
|
||||
return result == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected) {
|
||||
const u32 result =
|
||||
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
|
||||
return result == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected) {
|
||||
const u64 result = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer),
|
||||
value, expected);
|
||||
return result == expected;
|
||||
@@ -45,29 +54,32 @@ namespace Common {
|
||||
reinterpret_cast<__int64*>(expected.data())) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
|
||||
u8& actual) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected, u8& actual) {
|
||||
actual =
|
||||
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
|
||||
u16& actual) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected,
|
||||
u16& actual) {
|
||||
actual =
|
||||
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
|
||||
u32& actual) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected,
|
||||
u32& actual) {
|
||||
actual =
|
||||
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
|
||||
u64& actual) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected,
|
||||
u64& actual) {
|
||||
actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value,
|
||||
expected);
|
||||
return actual == expected;
|
||||
@@ -91,23 +103,12 @@ namespace Common {
|
||||
|
||||
#else
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
|
||||
template <typename T>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected) {
|
||||
return __sync_bool_compare_and_swap(pointer, expected, value);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
|
||||
return __sync_bool_compare_and_swap(pointer, expected, value);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
|
||||
return __sync_bool_compare_and_swap(pointer, expected, value);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
|
||||
return __sync_bool_compare_and_swap(pointer, expected, value);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected) {
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected) {
|
||||
unsigned __int128 value_a;
|
||||
unsigned __int128 expected_a;
|
||||
std::memcpy(&value_a, value.data(), sizeof(u128));
|
||||
@@ -115,31 +116,13 @@ namespace Common {
|
||||
return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
|
||||
u8& actual) {
|
||||
template <typename T>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual) {
|
||||
actual = __sync_val_compare_and_swap(pointer, expected, value);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
|
||||
u16& actual) {
|
||||
actual = __sync_val_compare_and_swap(pointer, expected, value);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
|
||||
u32& actual) {
|
||||
actual = __sync_val_compare_and_swap(pointer, expected, value);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
|
||||
u64& actual) {
|
||||
actual = __sync_val_compare_and_swap(pointer, expected, value);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected,
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected,
|
||||
u128& actual) {
|
||||
unsigned __int128 value_a;
|
||||
unsigned __int128 expected_a;
|
||||
@@ -151,7 +134,7 @@ namespace Common {
|
||||
return actual_a == expected_a;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) {
|
||||
[[nodiscard]] inline u128 AtomicLoad128(u64* pointer) {
|
||||
unsigned __int128 zeros_a = 0;
|
||||
unsigned __int128 result_a =
|
||||
__sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -931,8 +931,8 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
|
||||
sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent");
|
||||
|
||||
// Configure applets to be in foreground state
|
||||
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
}
|
||||
|
||||
ICommonStateGetter::~ICommonStateGetter() {
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>()};
|
||||
Result GetCount(Out<u32> out_mii_count, SourceFlag source_flag) {
|
||||
*out_mii_count = manager->GetCount(metadata, source_flag);
|
||||
|
||||
const u32 mii_count = manager->GetCount(metadata, source_flag);
|
||||
LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
|
||||
*out_mii_count);
|
||||
|
||||
LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, 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>()};
|
||||
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);
|
||||
|
||||
u32 mii_count{};
|
||||
std::vector<CharInfoElement> char_info_elements(output_size);
|
||||
const auto result = manager->Get(metadata, char_info_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(char_info_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 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;
|
||||
}
|
||||
R_UNLESS(age <= Age::All, ResultInvalidArgument);
|
||||
R_UNLESS(gender <= Gender::All, ResultInvalidArgument);
|
||||
R_UNLESS(race <= Race::All, ResultInvalidArgument);
|
||||
|
||||
if (gender > Gender::All) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultInvalidArgument);
|
||||
return;
|
||||
}
|
||||
manager->BuildRandom(*out_char_info, age, gender, race);
|
||||
|
||||
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_SUCCEED();
|
||||
}
|
||||
|
||||
void BuildDefault(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto index{rp.Pop<u32>()};
|
||||
|
||||
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);
|
||||
|
||||
if (index > 5) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultInvalidArgument);
|
||||
return;
|
||||
}
|
||||
manager->BuildDefault(*out_char_info, index);
|
||||
|
||||
CharInfo char_info{};
|
||||
manager->BuildDefault(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>()};
|
||||
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);
|
||||
|
||||
u32 mii_count{};
|
||||
std::vector<StoreData> store_data(output_size);
|
||||
const auto result = manager->Get(metadata, store_data, 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);
|
||||
}
|
||||
|
||||
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;
|
||||
const auto result = manager->AddOrReplace(metadata, store_data);
|
||||
|
||||
if (!is_system) {
|
||||
result = ResultPermissionDenied;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
*out_is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result GetIndex(Out<s32> out_index, CharInfo& char_info) {
|
||||
LOG_DEBUG(Service_Mii, "called");
|
||||
|
||||
bool is_broken_with_clear_flag = false;
|
||||
Result result = ResultSuccess;
|
||||
|
||||
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_RETURN(manager->GetIndex(metadata, char_info, *out_index));
|
||||
}
|
||||
|
||||
void GetIndex(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto info{rp.PopRaw<CharInfo>()};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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{};
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -781,8 +781,7 @@ struct Memory::Impl {
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); });
|
||||
if (ptr) {
|
||||
const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr);
|
||||
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
|
||||
return Common::AtomicCompareAndSwap(reinterpret_cast<T*>(ptr), data, expected);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -796,8 +795,7 @@ struct Memory::Impl {
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); });
|
||||
if (ptr) {
|
||||
const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr);
|
||||
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
|
||||
return Common::AtomicCompareAndSwap(reinterpret_cast<u64*>(ptr), data, expected);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -298,6 +298,16 @@ void Config::ReadDebuggingValues() {
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
void Config::ReadLinuxValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Linux));
|
||||
|
||||
ReadCategory(Settings::Category::Linux);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Config::ReadServiceValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
|
||||
|
||||
@@ -404,6 +414,9 @@ void Config::ReadValues() {
|
||||
ReadControlValues();
|
||||
ReadCoreValues();
|
||||
ReadCpuValues();
|
||||
#ifdef __unix__
|
||||
ReadLinuxValues();
|
||||
#endif
|
||||
ReadRendererValues();
|
||||
ReadAudioValues();
|
||||
ReadSystemValues();
|
||||
@@ -504,6 +517,9 @@ void Config::SaveValues() {
|
||||
SaveControlValues();
|
||||
SaveCoreValues();
|
||||
SaveCpuValues();
|
||||
#ifdef __unix__
|
||||
SaveLinuxValues();
|
||||
#endif
|
||||
SaveRendererValues();
|
||||
SaveAudioValues();
|
||||
SaveSystemValues();
|
||||
@@ -578,6 +594,16 @@ void Config::SaveDebuggingValues() {
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
void Config::SaveLinuxValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Linux));
|
||||
|
||||
WriteCategory(Settings::Category::Linux);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Config::SaveNetworkValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
|
||||
|
||||
|
||||
@@ -76,6 +76,9 @@ protected:
|
||||
void ReadCoreValues();
|
||||
void ReadDataStorageValues();
|
||||
void ReadDebuggingValues();
|
||||
#ifdef __unix__
|
||||
void ReadLinuxValues();
|
||||
#endif
|
||||
void ReadServiceValues();
|
||||
void ReadDisabledAddOnValues();
|
||||
void ReadMiscellaneousValues();
|
||||
@@ -107,6 +110,9 @@ protected:
|
||||
void SaveCoreValues();
|
||||
void SaveDataStorageValues();
|
||||
void SaveDebuggingValues();
|
||||
#ifdef __unix__
|
||||
void SaveLinuxValues();
|
||||
#endif
|
||||
void SaveNetworkValues();
|
||||
void SaveDisabledAddOnValues();
|
||||
void SaveMiscellaneousValues();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -137,7 +137,7 @@ void NpadAbstractPropertiesHandler::UpdateAllDeviceProperties() {
|
||||
const auto npad_index = NpadIdTypeToIndex(npad_id_type);
|
||||
for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
|
||||
auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index);
|
||||
if (!data->flag.is_assigned) {
|
||||
if (data == nullptr || !data->flag.is_assigned) {
|
||||
continue;
|
||||
}
|
||||
auto& npad_entry = data->shared_memory_format->npad.npad_entry[npad_index];
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,9 @@ add_executable(yuzu
|
||||
configuration/configure_input_profile_dialog.cpp
|
||||
configuration/configure_input_profile_dialog.h
|
||||
configuration/configure_input_profile_dialog.ui
|
||||
configuration/configure_linux_tab.cpp
|
||||
configuration/configure_linux_tab.h
|
||||
configuration/configure_linux_tab.ui
|
||||
configuration/configure_mouse_panning.cpp
|
||||
configuration/configure_mouse_panning.h
|
||||
configuration/configure_mouse_panning.ui
|
||||
|
||||
@@ -24,6 +24,8 @@ class Builder;
|
||||
}
|
||||
|
||||
class ConfigureAudio : public ConfigurationShared::Tab {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureAudio(const Core::System& system_,
|
||||
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
|
||||
|
||||
@@ -24,6 +24,8 @@ class Builder;
|
||||
}
|
||||
|
||||
class ConfigureCpu : public ConfigurationShared::Tab {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureCpu(const Core::System& system_,
|
||||
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
|
||||
|
||||
@@ -25,6 +25,8 @@ class Builder;
|
||||
}
|
||||
|
||||
class ConfigureGeneral : public ConfigurationShared::Tab {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureGeneral(const Core::System& system_,
|
||||
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -43,6 +43,8 @@ class Builder;
|
||||
}
|
||||
|
||||
class ConfigureGraphics : public ConfigurationShared::Tab {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureGraphics(
|
||||
const Core::System& system_, std::vector<VkDeviceInfo::Record>& records,
|
||||
|
||||
@@ -21,6 +21,8 @@ class Builder;
|
||||
}
|
||||
|
||||
class ConfigureGraphicsAdvanced : public ConfigurationShared::Tab {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureGraphicsAdvanced(
|
||||
const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
|
||||
|
||||
75
src/yuzu/configuration/configure_linux_tab.cpp
Normal file
75
src/yuzu/configuration/configure_linux_tab.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "ui_configure_linux_tab.h"
|
||||
#include "yuzu/configuration/configuration_shared.h"
|
||||
#include "yuzu/configuration/configure_linux_tab.h"
|
||||
#include "yuzu/configuration/shared_widget.h"
|
||||
|
||||
ConfigureLinuxTab::ConfigureLinuxTab(const Core::System& system_,
|
||||
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,
|
||||
const ConfigurationShared::Builder& builder, QWidget* parent)
|
||||
: Tab(group_, parent), ui(std::make_unique<Ui::ConfigureLinuxTab>()), system{system_} {
|
||||
ui->setupUi(this);
|
||||
|
||||
Setup(builder);
|
||||
|
||||
SetConfiguration();
|
||||
}
|
||||
|
||||
ConfigureLinuxTab::~ConfigureLinuxTab() = default;
|
||||
|
||||
void ConfigureLinuxTab::SetConfiguration() {}
|
||||
void ConfigureLinuxTab::Setup(const ConfigurationShared::Builder& builder) {
|
||||
QLayout& linux_layout = *ui->linux_widget->layout();
|
||||
|
||||
std::map<u32, QWidget*> linux_hold{};
|
||||
|
||||
std::vector<Settings::BasicSetting*> settings;
|
||||
const auto push = [&](Settings::Category category) {
|
||||
for (const auto setting : Settings::values.linkage.by_category[category]) {
|
||||
settings.push_back(setting);
|
||||
}
|
||||
};
|
||||
|
||||
push(Settings::Category::Linux);
|
||||
|
||||
for (auto* setting : settings) {
|
||||
auto* widget = builder.BuildWidget(setting, apply_funcs);
|
||||
|
||||
if (widget == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (!widget->Valid()) {
|
||||
widget->deleteLater();
|
||||
continue;
|
||||
}
|
||||
|
||||
linux_hold.insert({setting->Id(), widget});
|
||||
}
|
||||
|
||||
for (const auto& [id, widget] : linux_hold) {
|
||||
linux_layout.addWidget(widget);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureLinuxTab::ApplyConfiguration() {
|
||||
const bool is_powered_on = system.IsPoweredOn();
|
||||
for (const auto& apply_func : apply_funcs) {
|
||||
apply_func(is_powered_on);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureLinuxTab::changeEvent(QEvent* event) {
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
RetranslateUI();
|
||||
}
|
||||
|
||||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
void ConfigureLinuxTab::RetranslateUI() {
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
44
src/yuzu/configuration/configure_linux_tab.h
Normal file
44
src/yuzu/configuration/configure_linux_tab.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Ui {
|
||||
class ConfigureLinuxTab;
|
||||
}
|
||||
|
||||
namespace ConfigurationShared {
|
||||
class Builder;
|
||||
}
|
||||
|
||||
class ConfigureLinuxTab : public ConfigurationShared::Tab {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureLinuxTab(const Core::System& system_,
|
||||
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
|
||||
const ConfigurationShared::Builder& builder,
|
||||
QWidget* parent = nullptr);
|
||||
~ConfigureLinuxTab() override;
|
||||
|
||||
void ApplyConfiguration() override;
|
||||
void SetConfiguration() override;
|
||||
|
||||
private:
|
||||
void changeEvent(QEvent* event) override;
|
||||
void RetranslateUI();
|
||||
|
||||
void Setup(const ConfigurationShared::Builder& builder);
|
||||
|
||||
std::unique_ptr<Ui::ConfigureLinuxTab> ui;
|
||||
|
||||
const Core::System& system;
|
||||
|
||||
std::vector<std::function<void(bool)>> apply_funcs{};
|
||||
};
|
||||
53
src/yuzu/configuration/configure_linux_tab.ui
Normal file
53
src/yuzu/configuration/configure_linux_tab.ui
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ConfigureLinuxTab</class>
|
||||
<widget class="QWidget" name="ConfigureLinuxTab">
|
||||
<property name="accessibleName">
|
||||
<string>Linux</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="LinuxGroupBox">
|
||||
<property name="title">
|
||||
<string>Linux</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="LinuxVerticalLayout_1">
|
||||
<item>
|
||||
<widget class="QWidget" name="linux_widget" native="true">
|
||||
<layout class="QVBoxLayout" name="LinuxVerticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -26,6 +26,7 @@ class ConfigureMotionTouch;
|
||||
/// A dialog for touchpad calibration configuration.
|
||||
class CalibrationConfigurationDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port);
|
||||
~CalibrationConfigurationDialog() override;
|
||||
|
||||
@@ -16,6 +16,7 @@ class ConfigureMousePanning;
|
||||
|
||||
class ConfigureMousePanning : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureMousePanning(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_,
|
||||
float right_stick_deadzone, float right_stick_range);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "yuzu/configuration/configure_graphics.h"
|
||||
#include "yuzu/configuration/configure_graphics_advanced.h"
|
||||
#include "yuzu/configuration/configure_input_per_game.h"
|
||||
#include "yuzu/configuration/configure_linux_tab.h"
|
||||
#include "yuzu/configuration/configure_per_game.h"
|
||||
#include "yuzu/configuration/configure_per_game_addons.h"
|
||||
#include "yuzu/configuration/configure_system.h"
|
||||
@@ -60,6 +61,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
|
||||
system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); },
|
||||
[](Settings::AspectRatio, Settings::ResolutionSetup) {}, tab_group, *builder, this);
|
||||
input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);
|
||||
linux_tab = std::make_unique<ConfigureLinuxTab>(system_, tab_group, *builder, this);
|
||||
system_tab = std::make_unique<ConfigureSystem>(system_, tab_group, *builder, this);
|
||||
|
||||
ui->setupUi(this);
|
||||
@@ -71,6 +73,10 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
|
||||
ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics"));
|
||||
ui->tabWidget->addTab(audio_tab.get(), tr("Audio"));
|
||||
ui->tabWidget->addTab(input_tab.get(), tr("Input Profiles"));
|
||||
// Only show Linux tab on Unix
|
||||
#ifdef __unix__
|
||||
ui->tabWidget->addTab(linux_tab.get(), tr("Linux"));
|
||||
#endif
|
||||
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
setWindowTitle(tr("Properties"));
|
||||
|
||||
@@ -32,6 +32,7 @@ class ConfigureCpu;
|
||||
class ConfigureGraphics;
|
||||
class ConfigureGraphicsAdvanced;
|
||||
class ConfigureInputPerGame;
|
||||
class ConfigureLinuxTab;
|
||||
class ConfigureSystem;
|
||||
|
||||
class QGraphicsScene;
|
||||
@@ -85,5 +86,6 @@ private:
|
||||
std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab;
|
||||
std::unique_ptr<ConfigureGraphics> graphics_tab;
|
||||
std::unique_ptr<ConfigureInputPerGame> input_tab;
|
||||
std::unique_ptr<ConfigureLinuxTab> linux_tab;
|
||||
std::unique_ptr<ConfigureSystem> system_tab;
|
||||
};
|
||||
|
||||
@@ -27,6 +27,8 @@ class Builder;
|
||||
}
|
||||
|
||||
class ConfigureSystem : public ConfigurationShared::Tab {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureSystem(Core::System& system_,
|
||||
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
|
||||
|
||||
Reference in New Issue
Block a user