diff options
116 files changed, 2381 insertions, 2802 deletions
diff --git a/.gitmodules b/.gitmodules index e65997afc..52256d86f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -64,3 +64,6 @@ [submodule "oaknut"] path = externals/oaknut url = https://github.com/merryhime/oaknut +[submodule "Vulkan-Utility-Libraries"] + path = externals/Vulkan-Utility-Libraries + url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 7cd6b2108..eb26fbfd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,8 @@ option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}") option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON) +option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON) + option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) @@ -308,6 +310,10 @@ if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS) find_package(Vulkan 1.3.274 REQUIRED) endif() +if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES) + find_package(VulkanUtilityLibraries REQUIRED) +endif() + if (ENABLE_LIBUSB) find_package(libusb 1.0.24 MODULE) endif() diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 15b444338..42355716c 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -154,6 +154,11 @@ if (YUZU_USE_EXTERNAL_VULKAN_HEADERS) add_subdirectory(Vulkan-Headers) endif() +# Vulkan-Utility-Libraries +if (YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES) + add_subdirectory(Vulkan-Utility-Libraries) +endif() + # TZDB (Time Zone Database) add_subdirectory(nx_tzdb) diff --git a/externals/Vulkan-Utility-Libraries b/externals/Vulkan-Utility-Libraries new file mode 160000 +Subproject 524f8910d0e4a5f2ec5961996b23e5b74b95cb1 diff --git a/externals/tz/tz/tz.cpp b/externals/tz/tz/tz.cpp index 0c8b68217..04fa6cc8a 100644 --- a/externals/tz/tz/tz.cpp +++ b/externals/tz/tz/tz.cpp @@ -1625,11 +1625,11 @@ s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary) { return 0; } -bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep) { +bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep) { return localsub(sp, timep, 0, tmp) == nullptr; } -u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp) { +u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp) { return time1(out_time, tmp, localsub, sp, 0); } diff --git a/externals/tz/tz/tz.h b/externals/tz/tz/tz.h index 38605cfb1..dae4459bc 100644 --- a/externals/tz/tz/tz.h +++ b/externals/tz/tz/tz.h @@ -75,7 +75,7 @@ static_assert(sizeof(CalendarTimeInternal) == 0x3C, "CalendarTimeInternal has th s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary); -bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep); -u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp); +bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep); +u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp); } // namespace Tz diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt index 55abba093..53137b2e2 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt @@ -261,7 +261,7 @@ object NativeLibrary { /** * Begins emulation. */ - external fun run(path: String?) + external fun run(path: String?, programIndex: Int = 0) // Surface Handling external fun surfaceChanged(surf: Surface?) @@ -489,6 +489,12 @@ object NativeLibrary { sEmulationActivity.get()!!.onEmulationStopped(status) } + @Keep + @JvmStatic + fun onProgramChanged(programIndex: Int) { + sEmulationActivity.get()!!.onProgramChanged(programIndex) + } + /** * Logs the Yuzu version, Android version and, CPU. */ diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index 26cddecf4..564aaf305 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt @@ -76,7 +76,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener { override fun onDestroy() { stopForegroundService(this) - emulationViewModel.clear() super.onDestroy() } @@ -446,9 +445,14 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener { } fun onEmulationStopped(status: Int) { - if (status == 0) { + if (status == 0 && emulationViewModel.programChanged.value == -1) { finish() } + emulationViewModel.setEmulationStopped(true) + } + + fun onProgramChanged(programIndex: Int) { + emulationViewModel.setProgramChanged(programIndex) } private fun startMotionSensorListener() { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt index d6f17cf29..f218c76ef 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt @@ -7,6 +7,7 @@ import android.text.TextUtils import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding import org.yuzu.yuzu_emu.features.settings.model.StringSetting import org.yuzu.yuzu_emu.model.Driver @@ -57,13 +58,9 @@ class DriverAdapter(private val driverViewModel: DriverViewModel) : title.text = model.title version.text = model.version description.text = model.description - if (model.description.isNotEmpty()) { - version.visibility = View.VISIBLE - description.visibility = View.VISIBLE + if (model.title != binding.root.context.getString(R.string.system_gpu_driver)) { buttonDelete.visibility = View.VISIBLE } else { - version.visibility = View.GONE - description.visibility = View.GONE buttonDelete.visibility = View.GONE } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index ef393c4be..1f591ced1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -424,10 +424,38 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { } } } + launch { + repeatOnLifecycle(Lifecycle.State.CREATED) { + emulationViewModel.programChanged.collect { + if (it != 0) { + emulationViewModel.setEmulationStarted(false) + binding.drawerLayout.close() + binding.drawerLayout + .setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) + ViewUtils.hideView(binding.surfaceInputOverlay) + ViewUtils.showView(binding.loadingIndicator) + } + } + } + } + launch { + repeatOnLifecycle(Lifecycle.State.CREATED) { + emulationViewModel.emulationStopped.collect { + if (it && emulationViewModel.programChanged.value != -1) { + if (perfStatsUpdater != null) { + perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!) + } + emulationState.changeProgram(emulationViewModel.programChanged.value) + emulationViewModel.setProgramChanged(-1) + emulationViewModel.setEmulationStopped(false) + } + } + } + } } } - private fun startEmulation() { + private fun startEmulation(programIndex: Int = 0) { if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) { if (!DirectoryInitialization.areDirectoriesReady) { DirectoryInitialization.start() @@ -435,7 +463,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { updateScreenLayout() - emulationState.run(emulationActivity!!.isActivityRecreated) + emulationState.run(emulationActivity!!.isActivityRecreated, programIndex) } } @@ -833,6 +861,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { ) { private var state: State private var surface: Surface? = null + lateinit var emulationThread: Thread init { // Starting state is stopped. @@ -878,7 +907,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { } @Synchronized - fun run(isActivityRecreated: Boolean) { + fun run(isActivityRecreated: Boolean, programIndex: Int = 0) { if (isActivityRecreated) { if (NativeLibrary.isRunning()) { state = State.PAUSED @@ -889,10 +918,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { // If the surface is set, run now. Otherwise, wait for it to get set. if (surface != null) { - runWithValidSurface() + runWithValidSurface(programIndex) } } + @Synchronized + fun changeProgram(programIndex: Int) { + emulationThread.join() + emulationThread = Thread({ + Log.debug("[EmulationFragment] Starting emulation thread.") + NativeLibrary.run(gamePath, programIndex) + }, "NativeEmulation") + emulationThread.start() + } + // Surface callbacks @Synchronized fun newSurface(surface: Surface?) { @@ -932,7 +971,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { } } - private fun runWithValidSurface() { + private fun runWithValidSurface(programIndex: Int = 0) { NativeLibrary.surfaceChanged(surface) if (!emulationCanStart.invoke()) { return @@ -940,9 +979,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { when (state) { State.STOPPED -> { - val emulationThread = Thread({ + emulationThread = Thread({ Log.debug("[EmulationFragment] Starting emulation thread.") - NativeLibrary.run(gamePath) + NativeLibrary.run(gamePath, programIndex) }, "NativeEmulation") emulationThread.start() } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt index 5ed754c96..a49c887a1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt @@ -66,10 +66,13 @@ class DriverViewModel : ViewModel() { fun updateDriverList() { val selectedDriver = GpuDriverHelper.customDriverSettingData + val systemDriverData = GpuDriverHelper.getSystemDriverInfo() val newDriverList = mutableListOf( Driver( selectedDriver == GpuDriverMetadata(), - YuzuApplication.appContext.getString(R.string.system_gpu_driver) + YuzuApplication.appContext.getString(R.string.system_gpu_driver), + systemDriverData?.get(0) ?: "", + systemDriverData?.get(1) ?: "" ) ) driverData.forEach { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt index b66f47fe7..d024493cd 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt @@ -15,6 +15,12 @@ class EmulationViewModel : ViewModel() { val isEmulationStopping: StateFlow<Boolean> get() = _isEmulationStopping private val _isEmulationStopping = MutableStateFlow(false) + private val _emulationStopped = MutableStateFlow(false) + val emulationStopped = _emulationStopped.asStateFlow() + + private val _programChanged = MutableStateFlow(-1) + val programChanged = _programChanged.asStateFlow() + val shaderProgress: StateFlow<Int> get() = _shaderProgress private val _shaderProgress = MutableStateFlow(0) @@ -35,6 +41,17 @@ class EmulationViewModel : ViewModel() { _isEmulationStopping.value = value } + fun setEmulationStopped(value: Boolean) { + if (value) { + _emulationStarted.value = false + } + _emulationStopped.value = value + } + + fun setProgramChanged(programIndex: Int) { + _programChanged.value = programIndex + } + fun setShaderProgress(progress: Int) { _shaderProgress.value = progress } @@ -56,20 +73,4 @@ class EmulationViewModel : ViewModel() { fun setDrawerOpen(value: Boolean) { _drawerOpen.value = value } - - fun clear() { - setEmulationStarted(false) - setIsEmulationStopping(false) - setShaderProgress(0) - setTotalShaders(0) - setShaderMessage("") - } - - companion object { - const val KEY_EMULATION_STARTED = "EmulationStarted" - const val KEY_IS_EMULATION_STOPPING = "IsEmulationStarting" - const val KEY_SHADER_PROGRESS = "ShaderProgress" - const val KEY_TOTAL_SHADERS = "TotalShaders" - const val KEY_SHADER_MESSAGE = "ShaderMessage" - } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt index 81212cbee..a72dea8f1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt @@ -3,8 +3,10 @@ package org.yuzu.yuzu_emu.utils +import android.graphics.SurfaceTexture import android.net.Uri import android.os.Build +import android.view.Surface import java.io.File import java.io.IOException import org.yuzu.yuzu_emu.NativeLibrary @@ -195,6 +197,11 @@ object GpuDriverHelper { external fun supportsCustomDriverLoading(): Boolean + external fun getSystemDriverInfo( + surface: Surface = Surface(SurfaceTexture(true)), + hookLibPath: String = GpuDriverHelper.hookLibPath!! + ): Array<String>? + // Parse the custom driver metadata to retrieve the name. val installedCustomDriverData: GpuDriverMetadata get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME)) diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index 2acc93da8..abc6055ab 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt @@ -22,7 +22,7 @@ add_library(yuzu-android SHARED set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) -target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common) +target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers) target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log) if (ARCHITECTURE_arm64) target_link_libraries(yuzu-android PRIVATE adrenotools) diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp index 96f2ad3d4..f30100bd8 100644 --- a/src/android/app/src/main/jni/id_cache.cpp +++ b/src/android/app/src/main/jni/id_cache.cpp @@ -19,6 +19,7 @@ static jmethodID s_exit_emulation_activity; static jmethodID s_disk_cache_load_progress; static jmethodID s_on_emulation_started; static jmethodID s_on_emulation_stopped; +static jmethodID s_on_program_changed; static jclass s_game_class; static jmethodID s_game_constructor; @@ -123,6 +124,10 @@ jmethodID GetOnEmulationStopped() { return s_on_emulation_stopped; } +jmethodID GetOnProgramChanged() { + return s_on_program_changed; +} + jclass GetGameClass() { return s_game_class; } @@ -306,6 +311,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V"); s_on_emulation_stopped = env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V"); + s_on_program_changed = + env->GetStaticMethodID(s_native_library_class, "onProgramChanged", "(I)V"); const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game"); s_game_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_class)); diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h index a002e705d..00e48afc0 100644 --- a/src/android/app/src/main/jni/id_cache.h +++ b/src/android/app/src/main/jni/id_cache.h @@ -19,6 +19,7 @@ jmethodID GetExitEmulationActivity(); jmethodID GetDiskCacheLoadProgress(); jmethodID GetOnEmulationStarted(); jmethodID GetOnEmulationStopped(); +jmethodID GetOnProgramChanged(); jclass GetGameClass(); jmethodID GetGameConstructor(); diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 3fd9a500c..64627db88 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -60,6 +60,9 @@ #include "jni/id_cache.h" #include "jni/native.h" #include "video_core/renderer_base.h" +#include "video_core/renderer_vulkan/renderer_vulkan.h" +#include "video_core/vulkan_common/vulkan_instance.h" +#include "video_core/vulkan_common/vulkan_surface.h" #define jconst [[maybe_unused]] const auto #define jauto [[maybe_unused]] auto @@ -208,7 +211,8 @@ void EmulationSession::InitializeSystem(bool reload) { m_system.GetFileSystemController().CreateFactories(*m_vfs); } -Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) { +Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath, + const std::size_t program_index) { std::scoped_lock lock(m_mutex); // Create the render window. @@ -238,7 +242,8 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string ConfigureFilesystemProvider(filepath); // Load the ROM. - m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath); + m_load_result = + m_system.Load(EmulationSession::GetInstance().Window(), filepath, 0, program_index); if (m_load_result != Core::SystemResultStatus::Success) { return m_load_result; } @@ -248,6 +253,12 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string m_system.GetCpuManager().OnGpuReady(); m_system.RegisterExitCallback([&] { HaltEmulation(); }); + // Register an ExecuteProgram callback such that Core can execute a sub-program + m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) { + m_next_program_index = program_index_; + EmulationSession::GetInstance().HaltEmulation(); + }); + OnEmulationStarted(); return Core::SystemResultStatus::Success; } @@ -255,6 +266,11 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string void EmulationSession::ShutdownEmulation() { std::scoped_lock lock(m_mutex); + if (m_next_program_index != -1) { + ChangeProgram(m_next_program_index); + m_next_program_index = -1; + } + m_is_running = false; // Unload user input. @@ -402,6 +418,12 @@ void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) { static_cast<jint>(result)); } +void EmulationSession::ChangeProgram(std::size_t program_index) { + JNIEnv* env = IDCache::GetEnvForThread(); + env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnProgramChanged(), + static_cast<jint>(program_index)); +} + u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) { auto program_id_string = GetJString(env, jprogramId); try { @@ -411,7 +433,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) { } } -static Core::SystemResultStatus RunEmulation(const std::string& filepath) { +static Core::SystemResultStatus RunEmulation(const std::string& filepath, + const size_t program_index = 0) { MicroProfileOnThreadCreate("EmuThread"); SCOPE_EXIT({ MicroProfileShutdown(); }); @@ -424,7 +447,7 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath) { SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); }); - jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath); + jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index); if (result != Core::SystemResultStatus::Success) { return result; } @@ -521,6 +544,37 @@ jboolean JNICALL Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_supportsCustomDri #endif } +jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo( + JNIEnv* env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) { + const char* file_redirect_dir_{}; + int featureFlags{}; + std::string hook_lib_dir = GetJString(env, j_hook_lib_dir); + auto handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(), + nullptr, nullptr, file_redirect_dir_, nullptr); + auto driver_library = std::make_shared<Common::DynamicLibrary>(handle); + InputCommon::InputSubsystem input_subsystem; + auto m_window = std::make_unique<EmuWindow_Android>( + &input_subsystem, ANativeWindow_fromSurface(env, j_surf), driver_library); + + Vulkan::vk::InstanceDispatch dld; + Vulkan::vk::Instance vk_instance = Vulkan::CreateInstance( + *driver_library, dld, VK_API_VERSION_1_1, Core::Frontend::WindowSystemType::Android); + + auto surface = Vulkan::CreateSurface(vk_instance, m_window->GetWindowInfo()); + + auto device = Vulkan::CreateDevice(vk_instance, dld, *surface); + + auto driver_version = device.GetDriverVersion(); + auto version_string = + fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(driver_version), + VK_API_VERSION_MINOR(driver_version), VK_API_VERSION_PATCH(driver_version)); + + jobjectArray j_driver_info = + env->NewObjectArray(2, IDCache::GetStringClass(), ToJString(env, version_string)); + env->SetObjectArrayElement(j_driver_info, 1, ToJString(env, device.GetDriverName())); + return j_driver_info; +} + jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) { Core::Crypto::KeyManager::Instance().ReloadKeys(); return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded()); @@ -689,11 +743,11 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj Settings::LogSettings(); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2(JNIEnv* env, jclass clazz, - jstring j_path) { +void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path, + jint j_program_index) { const std::string path = GetJString(env, j_path); - const Core::SystemResultStatus result{RunEmulation(path)}; + const Core::SystemResultStatus result{RunEmulation(path, j_program_index)}; if (result != Core::SystemResultStatus::Success) { env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetExitEmulationActivity(), static_cast<int>(result)); diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index dadb138ad..bfe3fccca 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h @@ -45,7 +45,8 @@ public: const Core::PerfStatsResults& PerfStats(); void ConfigureFilesystemProvider(const std::string& filepath); void InitializeSystem(bool reload); - Core::SystemResultStatus InitializeEmulation(const std::string& filepath); + Core::SystemResultStatus InitializeEmulation(const std::string& filepath, + const std::size_t program_index = 0); bool IsHandheldOnly(); void SetDeviceType([[maybe_unused]] int index, int type); @@ -60,6 +61,7 @@ public: private: static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max); static void OnEmulationStopped(Core::SystemResultStatus result); + static void ChangeProgram(std::size_t program_index); private: // Window management @@ -84,4 +86,7 @@ private: // Synchronization std::condition_variable_any m_cv; mutable std::mutex m_mutex; + + // Program index for next boot + std::atomic<s32> m_next_program_index = -1; }; diff --git a/src/android/app/src/main/res/layout/fragment_emulation.xml b/src/android/app/src/main/res/layout/fragment_emulation.xml index c01117d14..0d2bfe8d6 100644 --- a/src/android/app/src/main/res/layout/fragment_emulation.xml +++ b/src/android/app/src/main/res/layout/fragment_emulation.xml @@ -34,8 +34,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" + android:focusable="false" android:defaultFocusHighlightEnabled="false" - android:clickable="false"> + android:clickable="false" + app:rippleColor="@android:color/transparent"> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/loading_layout" diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index e982d03be..4e4ed1789 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -210,8 +210,6 @@ add_library(audio_core STATIC sink/sink_stream.h ) -create_target_directory_groups(audio_core) - if (MSVC) target_compile_options(audio_core PRIVATE /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data @@ -267,3 +265,5 @@ endif() if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(audio_core PRIVATE precompiled_headers.h) endif() + +create_target_directory_groups(audio_core) diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp index ef301d8b4..7a76c3d0b 100644 --- a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp +++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp @@ -89,11 +89,13 @@ u32 AudioRenderer::Receive(Direction dir) { } void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit, - u64 applet_resource_user_id, bool reset) noexcept { + u64 applet_resource_user_id, Kernel::KProcess* process, + bool reset) noexcept { command_buffers[session_id].buffer = buffer; command_buffers[session_id].size = size; command_buffers[session_id].time_limit = time_limit; command_buffers[session_id].applet_resource_user_id = applet_resource_user_id; + command_buffers[session_id].process = process; command_buffers[session_id].reset_buffer = reset; } @@ -173,7 +175,8 @@ void AudioRenderer::Main(std::stop_token stop_token) { // If there are no remaining commands (from the previous list), // this is a new command list, initialize it. if (command_buffer.remaining_command_count == 0) { - command_list_processor.Initialize(system, command_buffer.buffer, + command_list_processor.Initialize(system, *command_buffer.process, + command_buffer.buffer, command_buffer.size, streams[index]); } diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h index 57b89d9fe..875266f27 100644 --- a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h +++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h @@ -19,6 +19,10 @@ namespace Core { class System; } // namespace Core +namespace Kernel { +class KProcess; +} + namespace AudioCore { namespace Sink { class Sink; @@ -69,7 +73,8 @@ public: u32 Receive(Direction dir); void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit, - u64 applet_resource_user_id, bool reset) noexcept; + u64 applet_resource_user_id, Kernel::KProcess* process, + bool reset) noexcept; u32 GetRemainCommandCount(s32 session_id) const noexcept; void ClearRemainCommandCount(s32 session_id) noexcept; u64 GetRenderingStartTick(s32 session_id) const noexcept; diff --git a/src/audio_core/adsp/apps/audio_renderer/command_buffer.h b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h index 3fd1b09dc..d6a721f34 100644 --- a/src/audio_core/adsp/apps/audio_renderer/command_buffer.h +++ b/src/audio_core/adsp/apps/audio_renderer/command_buffer.h @@ -6,6 +6,10 @@ #include "audio_core/common/common.h" #include "common/common_types.h" +namespace Kernel { +class KProcess; +} + namespace AudioCore::ADSP::AudioRenderer { struct CommandBuffer { @@ -14,6 +18,7 @@ struct CommandBuffer { u64 size{}; u64 time_limit{}; u64 applet_resource_user_id{}; + Kernel::KProcess* process{}; bool reset_buffer{}; // Set by the DSP u32 remaining_command_count{}; diff --git a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp index 24e4d0496..eef2c0b89 100644 --- a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp +++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.cpp @@ -9,14 +9,15 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hle/kernel/k_process.h" #include "core/memory.h" namespace AudioCore::ADSP::AudioRenderer { -void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size, - Sink::SinkStream* stream_) { +void CommandListProcessor::Initialize(Core::System& system_, Kernel::KProcess& process, + CpuAddr buffer, u64 size, Sink::SinkStream* stream_) { system = &system_; - memory = &system->ApplicationMemory(); + memory = &process.GetMemory(); stream = stream_; header = reinterpret_cast<Renderer::CommandListHeader*>(buffer); commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader)); diff --git a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h index 4e5fb793e..944e82505 100644 --- a/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h +++ b/src/audio_core/adsp/apps/audio_renderer/command_list_processor.h @@ -16,6 +16,10 @@ class Memory; class System; } // namespace Core +namespace Kernel { +class KProcess; +} + namespace AudioCore { namespace Sink { class SinkStream; @@ -40,7 +44,8 @@ public: * @param size - The size of the buffer. * @param stream - The stream to be used for sending the samples. */ - void Initialize(Core::System& system, CpuAddr buffer, u64 size, Sink::SinkStream* stream); + void Initialize(Core::System& system, Kernel::KProcess& process, CpuAddr buffer, u64 size, + Sink::SinkStream* stream); /** * Set the maximum processing time for this command list. diff --git a/src/audio_core/renderer/audio_renderer.cpp b/src/audio_core/renderer/audio_renderer.cpp index 09efe9be9..df03d03aa 100644 --- a/src/audio_core/renderer/audio_renderer.cpp +++ b/src/audio_core/renderer/audio_renderer.cpp @@ -6,6 +6,7 @@ #include "audio_core/renderer/audio_renderer.h" #include "audio_core/renderer/system_manager.h" #include "core/core.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/service/audio/errors.h" @@ -17,7 +18,8 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren Result Renderer::Initialize(const AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, const u64 transfer_memory_size, const u32 process_handle, - const u64 applet_resource_user_id, const s32 session_id) { + Kernel::KProcess& process, const u64 applet_resource_user_id, + const s32 session_id) { if (params.execution_mode == ExecutionMode::Auto) { if (!manager.AddSystem(system)) { LOG_ERROR(Service_Audio, @@ -28,7 +30,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params, } initialized = true; - system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, + system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process, applet_resource_user_id, session_id); return ResultSuccess; diff --git a/src/audio_core/renderer/audio_renderer.h b/src/audio_core/renderer/audio_renderer.h index 24650278b..1219f74ca 100644 --- a/src/audio_core/renderer/audio_renderer.h +++ b/src/audio_core/renderer/audio_renderer.h @@ -14,7 +14,8 @@ class System; namespace Kernel { class KTransferMemory; -} +class KProcess; +} // namespace Kernel namespace AudioCore { struct AudioRendererParameterInternal; @@ -44,7 +45,8 @@ public: */ Result Initialize(const AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, - u32 process_handle, u64 applet_resource_user_id, s32 session_id); + u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id, + s32 session_id); /** * Finalize the renderer for shutdown. diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp index 31f92087c..ca656edae 100644 --- a/src/audio_core/renderer/system.cpp +++ b/src/audio_core/renderer/system.cpp @@ -32,6 +32,7 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/memory.h" @@ -101,7 +102,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_) Result System::Initialize(const AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, - u32 process_handle_, u64 applet_resource_user_id_, s32 session_id_) { + u32 process_handle_, Kernel::KProcess& process_, + u64 applet_resource_user_id_, s32 session_id_) { if (!CheckValidRevision(params.revision)) { return Service::Audio::ResultInvalidRevision; } @@ -117,6 +119,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params, behavior.SetUserLibRevision(params.revision); process_handle = process_handle_; + process = &process_; applet_resource_user_id = applet_resource_user_id_; session_id = session_id_; @@ -129,7 +132,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params, render_device = params.rendering_device; execution_mode = params.execution_mode; - core.ApplicationMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size); + process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size); // Note: We're not actually using the transfer memory because it's a pain to code for. // Allocate the memory normally instead and hope the game doesn't try to read anything back @@ -613,7 +616,8 @@ void System::SendCommandToDsp() { static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 * (static_cast<f32>(render_time_limit_percent) / 100.0f))}; audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit, - applet_resource_user_id, reset_command_buffers); + applet_resource_user_id, process, + reset_command_buffers); reset_command_buffers = false; command_buffer_size = command_size; if (remaining_command_count == 0) { diff --git a/src/audio_core/renderer/system.h b/src/audio_core/renderer/system.h index 8a8341710..753a0b796 100644 --- a/src/audio_core/renderer/system.h +++ b/src/audio_core/renderer/system.h @@ -29,6 +29,7 @@ class System; namespace Kernel { class KEvent; +class KProcess; class KTransferMemory; } // namespace Kernel @@ -80,7 +81,8 @@ public: */ Result Initialize(const AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, - u32 process_handle, u64 applet_resource_user_id, s32 session_id); + u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id, + s32 session_id); /** * Finalize the system. @@ -275,6 +277,8 @@ private: Common::Event terminate_event{}; /// Does what locks do std::mutex lock{}; + /// Process this audio render is operating within, used for memory reads/writes. + Kernel::KProcess* process{}; /// Handle for the process for this system, unused u32 process_handle{}; /// Applet resource id for this system, unused diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 8c57d47c6..e30fea268 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -244,8 +244,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") ) endif() -create_target_directory_groups(common) - target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads) target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle) @@ -257,3 +255,5 @@ endif() if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(common PRIVATE precompiled_headers.h) endif() + +create_target_directory_groups(common) diff --git a/src/common/atomic_ops.h b/src/common/atomic_ops.h index c18bb33c4..9bf6f2f81 100644 --- a/src/common/atomic_ops.h +++ b/src/common/atomic_ops.h @@ -15,25 +15,34 @@ namespace Common { #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) { - 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) { +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 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); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 347bbf2d0..ea6b2c285 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -915,8 +915,6 @@ else() ) endif() -create_target_directory_groups(core) - target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz) target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API) if (MINGW) @@ -994,3 +992,5 @@ endif() if (YUZU_ENABLE_LTO) set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) endif() + +create_target_directory_groups(core) diff --git a/src/core/core.cpp b/src/core/core.cpp index 1b412ac98..11bf8d2f6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -200,22 +200,22 @@ struct System::Impl { system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true); std::shared_ptr<Service::PSC::Time::SystemClock> user_clock; - static_service_a->GetStandardUserSystemClock(user_clock); + static_service_a->GetStandardUserSystemClock(&user_clock); std::shared_ptr<Service::PSC::Time::SystemClock> local_clock; - static_service_a->GetStandardLocalSystemClock(local_clock); + static_service_a->GetStandardLocalSystemClock(&local_clock); std::shared_ptr<Service::PSC::Time::SystemClock> network_clock; - static_service_s->GetStandardNetworkSystemClock(network_clock); + static_service_s->GetStandardNetworkSystemClock(&network_clock); std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service; - static_service_a->GetTimeZoneService(timezone_service); + static_service_a->GetTimeZoneService(&timezone_service); Service::PSC::Time::LocationName name{}; auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); - std::memcpy(name.name.data(), new_name.data(), std::min(name.name.size(), new_name.size())); + std::memcpy(name.data(), new_name.data(), std::min(name.size(), new_name.size())); - timezone_service->SetDeviceLocation(name); + timezone_service->SetDeviceLocationName(name); u64 time_offset = 0; if (Settings::values.custom_rtc_enabled) { @@ -233,7 +233,7 @@ struct System::Impl { local_clock->SetCurrentTime(new_time); - network_clock->GetSystemClockContext(context); + network_clock->GetSystemClockContext(&context); settings_service->SetNetworkSystemClockContext(context); network_clock->SetCurrentTime(new_time); } diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 7d3421929..8a360a839 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -543,7 +543,8 @@ void KThread::Unpin() { ASSERT(m_parent != nullptr); // Resume any threads that began waiting on us while we were pinned. - for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); ++it) { + for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); + it = m_pinned_waiter_list.erase(it)) { it->EndWait(ResultSuccess); } } diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a768bdc54..38f67adcd 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -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() { diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp index 50adc7c02..e83e931c5 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.cpp +++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp @@ -59,7 +59,7 @@ void MiiEdit::Initialize() { break; } - manager = system.ServiceManager().GetService<Mii::MiiDBModule>("mii:e")->GetMiiManager(); + manager = system.ServiceManager().GetService<Mii::IStaticService>("mii:e")->GetMiiManager(); if (manager == nullptr) { manager = std::make_shared<Mii::MiiManager>(); } diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp index 66dd64fd1..3101cf447 100644 --- a/src/core/hle/service/audio/audctl.cpp +++ b/src/core/hle/service/audio/audctl.cpp @@ -4,6 +4,8 @@ #include "common/logging/log.h" #include "core/hle/service/audio/audctl.h" #include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/set/system_settings_server.h" +#include "core/hle/service/sm/sm.h" namespace Service::Audio { @@ -19,15 +21,15 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { {6, nullptr, "IsTargetConnected"}, {7, nullptr, "SetDefaultTarget"}, {8, nullptr, "GetDefaultTarget"}, - {9, nullptr, "GetAudioOutputMode"}, - {10, nullptr, "SetAudioOutputMode"}, + {9, &AudCtl::GetAudioOutputMode, "GetAudioOutputMode"}, + {10, &AudCtl::SetAudioOutputMode, "SetAudioOutputMode"}, {11, nullptr, "SetForceMutePolicy"}, {12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"}, {13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"}, - {14, nullptr, "SetOutputModeSetting"}, + {14, &AudCtl::SetOutputModeSetting, "SetOutputModeSetting"}, {15, nullptr, "SetOutputTarget"}, {16, nullptr, "SetInputTargetForceEnabled"}, - {17, nullptr, "SetHeadphoneOutputLevelMode"}, + {17, &AudCtl::SetHeadphoneOutputLevelMode, "SetHeadphoneOutputLevelMode"}, {18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"}, {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, @@ -40,7 +42,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { {27, nullptr, "SetVolumeMappingTableForDev"}, {28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, - {30, nullptr, "SetSpeakerAutoMuteEnabled"}, + {30, &AudCtl::SetSpeakerAutoMuteEnabled, "SetSpeakerAutoMuteEnabled"}, {31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"}, {32, nullptr, "GetActiveOutputTarget"}, {33, nullptr, "GetTargetDeviceInfo"}, @@ -68,6 +70,9 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { // clang-format on RegisterHandlers(functions); + + m_set_sys = + system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); } AudCtl::~AudCtl() = default; @@ -96,6 +101,33 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) { rb.Push(target_max_volume); } +void AudCtl::GetAudioOutputMode(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; + + Set::AudioOutputMode output_mode{}; + const auto result = m_set_sys->GetAudioOutputMode(output_mode, target); + + LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(result); + rb.PushEnum(output_mode); +} + +void AudCtl::SetAudioOutputMode(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; + const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()}; + + const auto result = m_set_sys->SetAudioOutputMode(target, output_mode); + + LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) { LOG_WARNING(Audio, "(STUBBED) called"); @@ -106,13 +138,31 @@ void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) { void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto value = rp.Pop<u32>(); + const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; - LOG_WARNING(Audio, "(STUBBED) called, value={}", value); + LOG_WARNING(Audio, "(STUBBED) called, target={}", target); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.PushEnum(AudioOutputMode::PcmAuto); + rb.PushEnum(Set::AudioOutputMode::ch_7_1); +} + +void AudCtl::SetOutputModeSetting(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; + const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()}; + + LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void AudCtl::SetHeadphoneOutputLevelMode(HLERequestContext& ctx) { + LOG_WARNING(Audio, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); } void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) { @@ -123,14 +173,28 @@ void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) { rb.PushEnum(HeadphoneOutputLevelMode::Normal); } +void AudCtl::SetSpeakerAutoMuteEnabled(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto is_speaker_auto_mute_enabled{rp.Pop<bool>()}; + + LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}", + is_speaker_auto_mute_enabled); + + const auto result = m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) { - const bool is_speaker_auto_mute_enabled = false; + bool is_speaker_auto_mute_enabled{}; + const auto result = m_set_sys->GetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled); LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); + rb.Push(result); rb.Push<u8>(is_speaker_auto_mute_enabled); } diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h index d57abb383..4c90ead70 100644 --- a/src/core/hle/service/audio/audctl.h +++ b/src/core/hle/service/audio/audctl.h @@ -9,6 +9,10 @@ namespace Core { class System; } +namespace Service::Set { +class ISystemSettingsServer; +} + namespace Service::Audio { class AudCtl final : public ServiceFramework<AudCtl> { @@ -17,14 +21,6 @@ public: ~AudCtl() override; private: - enum class AudioOutputMode { - Invalid, - Pcm1ch, - Pcm2ch, - Pcm6ch, - PcmAuto, - }; - enum class ForceMutePolicy { Disable, SpeakerMuteOnHeadphoneUnplugged, @@ -37,10 +33,18 @@ private: void GetTargetVolumeMin(HLERequestContext& ctx); void GetTargetVolumeMax(HLERequestContext& ctx); + void GetAudioOutputMode(HLERequestContext& ctx); + void SetAudioOutputMode(HLERequestContext& ctx); void GetForceMutePolicy(HLERequestContext& ctx); void GetOutputModeSetting(HLERequestContext& ctx); + void SetOutputModeSetting(HLERequestContext& ctx); + void SetHeadphoneOutputLevelMode(HLERequestContext& ctx); void GetHeadphoneOutputLevelMode(HLERequestContext& ctx); + void SetSpeakerAutoMuteEnabled(HLERequestContext& ctx); void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx); + void AcquireTargetNotification(HLERequestContext& ctx); + + std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; }; } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 05581e6e0..10108abc0 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -35,10 +35,11 @@ public: explicit IAudioRenderer(Core::System& system_, Manager& manager_, AudioCore::AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, - u32 process_handle, u64 applet_resource_user_id, s32 session_id) + u32 process_handle, Kernel::KProcess& process_, + u64 applet_resource_user_id, s32 session_id) : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"}, rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_}, - impl{std::make_unique<Renderer>(system_, manager, rendered_event)} { + impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} { // clang-format off static const FunctionInfo functions[] = { {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, @@ -59,13 +60,15 @@ public: // clang-format on RegisterHandlers(functions); - impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, + process.Open(); + impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process, applet_resource_user_id, session_id); } ~IAudioRenderer() override { impl->Finalize(); service_context.CloseEvent(rendered_event); + process.Close(); } private: @@ -235,6 +238,7 @@ private: Kernel::KEvent* rendered_event; Manager& manager; std::unique_ptr<Renderer> impl; + Kernel::KProcess& process; Common::ScratchBuffer<u8> output_buffer; Common::ScratchBuffer<u8> performance_buffer; }; @@ -455,7 +459,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) { return; } - auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)}; + auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()}; auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)}; const auto session_id{impl->GetSessionId()}; @@ -472,7 +476,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(), - transfer_memory_size, process_handle, + transfer_memory_size, process_handle, *process, applet_resource_user_id, session_id); } @@ -522,7 +526,7 @@ void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) { } void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) { - LOG_DEBUG(Service_Audio, "called"); + LOG_ERROR(Service_Audio, "called. Implement me!"); } void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) { diff --git a/src/core/hle/service/caps/caps_manager.cpp b/src/core/hle/service/caps/caps_manager.cpp index e3b8ecf3e..3a22b135f 100644 --- a/src/core/hle/service/caps/caps_manager.cpp +++ b/src/core/hle/service/caps/caps_manager.cpp @@ -246,10 +246,10 @@ Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; - static_service->GetStandardUserSystemClock(user_clock); + static_service->GetStandardUserSystemClock(&user_clock); s64 posix_time{}; - auto result = user_clock->GetCurrentTime(posix_time); + auto result = user_clock->GetCurrentTime(&posix_time); if (result.IsError()) { return result; @@ -268,10 +268,10 @@ Result AlbumManager::SaveEditedScreenShot(ApplicationAlbumEntry& out_entry, system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; - static_service->GetStandardUserSystemClock(user_clock); + static_service->GetStandardUserSystemClock(&user_clock); s64 posix_time{}; - auto result = user_clock->GetCurrentTime(posix_time); + auto result = user_clock->GetCurrentTime(&posix_time); if (result.IsError()) { return result; @@ -470,11 +470,11 @@ AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const { system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; - static_service->GetTimeZoneService(timezone_service); + static_service->GetTimeZoneService(&timezone_service); Service::PSC::Time::CalendarTime calendar_time{}; Service::PSC::Time::CalendarAdditionalInfo additional_info{}; - timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time); + timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time); return { .year = calendar_time.year, diff --git a/src/core/hle/service/cmif_serialization.h b/src/core/hle/service/cmif_serialization.h index 9eb10e816..9ee26400d 100644 --- a/src/core/hle/service/cmif_serialization.h +++ b/src/core/hle/service/cmif_serialization.h @@ -12,6 +12,109 @@ namespace Service { // clang-format off +template <typename T> +struct UnwrapArg { + using Type = std::remove_cvref_t<T>; +}; + +template <typename T, int A> +struct UnwrapArg<InLargeData<T, A>> { + using Type = std::remove_cv_t<typename InLargeData<T, A>::Type>; +}; + +template <typename T> +struct UnwrapArg<Out<T>> { + using Type = AutoOut<typename Out<T>::Type>; +}; + +template <typename T> +struct UnwrapArg<OutCopyHandle<T>> { + using Type = AutoOut<typename OutCopyHandle<T>::Type>; +}; + +template <typename T> +struct UnwrapArg<OutMoveHandle<T>> { + using Type = AutoOut<typename OutMoveHandle<T>::Type>; +}; + +template <typename T, int A> +struct UnwrapArg<OutLargeData<T, A>> { + using Type = AutoOut<typename OutLargeData<T, A>::Type>; +}; + +enum class ArgumentType { + InProcessId, + InData, + InInterface, + InCopyHandle, + OutData, + OutInterface, + OutCopyHandle, + OutMoveHandle, + InBuffer, + InLargeData, + OutBuffer, + OutLargeData, +}; + +template <typename T> +struct ArgumentTraits; + +template <> +struct ArgumentTraits<ClientProcessId> { + static constexpr ArgumentType Type = ArgumentType::InProcessId; +}; + +template <typename T> +struct ArgumentTraits<SharedPointer<T>> { + static constexpr ArgumentType Type = ArgumentType::InInterface; +}; + +template <typename T> +struct ArgumentTraits<InCopyHandle<T>> { + static constexpr ArgumentType Type = ArgumentType::InCopyHandle; +}; + +template <typename T> +struct ArgumentTraits<Out<SharedPointer<T>>> { + static constexpr ArgumentType Type = ArgumentType::OutInterface; +}; + +template <typename T> +struct ArgumentTraits<Out<T>> { + static constexpr ArgumentType Type = ArgumentType::OutData; +}; + +template <typename T> +struct ArgumentTraits<OutCopyHandle<T>> { + static constexpr ArgumentType Type = ArgumentType::OutCopyHandle; +}; + +template <typename T> +struct ArgumentTraits<OutMoveHandle<T>> { + static constexpr ArgumentType Type = ArgumentType::OutMoveHandle; +}; + +template <typename T, int A> +struct ArgumentTraits<Buffer<T, A>> { + static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer; +}; + +template <typename T, int A> +struct ArgumentTraits<InLargeData<T, A>> { + static constexpr ArgumentType Type = ArgumentType::InLargeData; +}; + +template <typename T, int A> +struct ArgumentTraits<OutLargeData<T, A>> { + static constexpr ArgumentType Type = ArgumentType::OutLargeData; +}; + +template <typename T> +struct ArgumentTraits { + static constexpr ArgumentType Type = ArgumentType::InData; +}; + struct RequestLayout { u32 copy_handle_count; u32 move_handle_count; @@ -122,6 +225,8 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE static_assert(PrevAlign <= ArgAlign, "Input argument is not ordered by alignment"); static_assert(!RawDataFinished, "All input interface arguments must appear after raw data"); + static_assert(!std::is_pointer_v<ArgType>, "Input raw data must not be a pointer"); + static_assert(std::is_trivially_copyable_v<ArgType>, "Input raw data must be trivially copyable"); constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); constexpr size_t ArgEnd = ArgOffset + ArgSize; @@ -198,7 +303,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE constexpr size_t BufferSize = sizeof(ArgType); // Clear the existing data. - std::memset(&std::get<ArgIndex>(args), 0, BufferSize); + std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize); return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) { @@ -237,27 +342,29 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment"); static_assert(!RawDataFinished, "All output interface arguments must appear after raw data"); + static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer"); + static_assert(std::is_trivially_copyable_v<decltype(std::get<ArgIndex>(args).raw)>, "Output raw data must be trivially copyable"); constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); constexpr size_t ArgEnd = ArgOffset + ArgSize; - std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args), ArgSize); + std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args).raw, ArgSize); return WriteOutArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) { if (is_domain) { - ctx.AddDomainObject(std::get<ArgIndex>(args)); + ctx.AddDomainObject(std::get<ArgIndex>(args).raw); } else { - ctx.AddMoveInterface(std::get<ArgIndex>(args)); + ctx.AddMoveInterface(std::get<ArgIndex>(args).raw); } return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) { - ctx.AddCopyObject(std::get<ArgIndex>(args)); + ctx.AddCopyObject(std::get<ArgIndex>(args).raw); return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) { - ctx.AddMoveObject(std::get<ArgIndex>(args)); + ctx.AddMoveObject(std::get<ArgIndex>(args).raw); return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { @@ -302,10 +409,10 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) { } const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false; - using MethodArguments = std::tuple<std::remove_reference_t<A>...>; + using MethodArguments = std::tuple<std::remove_cvref_t<A>...>; OutTemporaryBuffers buffers{}; - auto call_arguments = std::tuple<typename RemoveOut<A>::Type...>(); + auto call_arguments = std::tuple<typename UnwrapArg<A>::Type...>(); // Read inputs. const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2; diff --git a/src/core/hle/service/cmif_types.h b/src/core/hle/service/cmif_types.h index 2610c49f3..dc06169f4 100644 --- a/src/core/hle/service/cmif_types.h +++ b/src/core/hle/service/cmif_types.h @@ -13,21 +13,30 @@ namespace Service { // clang-format off template <typename T> +struct AutoOut { + T raw; +}; + +template <typename T> class Out { public: using Type = T; - /* implicit */ Out(Type& t) : raw(&t) {} - ~Out() = default; + /* implicit */ Out(AutoOut<Type>& t) : raw(&t.raw) {} + /* implicit */ Out(Type* t) : raw(t) {} Type* Get() const { return raw; } - Type& operator*() { + Type& operator*() const { return *raw; } + Type* operator->() const { + return raw; + } + private: Type* raw; }; @@ -35,6 +44,9 @@ private: template <typename T> using SharedPointer = std::shared_ptr<T>; +template <typename T> +using OutInterface = Out<SharedPointer<T>>; + struct ClientProcessId { explicit operator bool() const { return pid != 0; @@ -101,17 +113,21 @@ class OutCopyHandle { public: using Type = T*; - /* implicit */ OutCopyHandle(Type& t) : raw(&t) {} - ~OutCopyHandle() = default; + /* implicit */ OutCopyHandle(AutoOut<Type>& t) : raw(&t.raw) {} + /* implicit */ OutCopyHandle(Type* t) : raw(t) {} Type* Get() const { return raw; } - Type& operator*() { + Type& operator*() const { return *raw; } + Type* operator->() const { + return raw; + } + private: Type* raw; }; @@ -121,30 +137,34 @@ class OutMoveHandle { public: using Type = T*; - /* implicit */ OutMoveHandle(Type& t) : raw(&t) {} - ~OutMoveHandle() = default; + /* implicit */ OutMoveHandle(AutoOut<Type>& t) : raw(&t.raw) {} + /* implicit */ OutMoveHandle(Type* t) : raw(t) {} Type* Get() const { return raw; } - Type& operator*() { + Type& operator*() const { return *raw; } + Type* operator->() const { + return raw; + } + private: Type* raw; }; enum BufferAttr : int { - BufferAttr_In = (1U << 0), - BufferAttr_Out = (1U << 1), - BufferAttr_HipcMapAlias = (1U << 2), - BufferAttr_HipcPointer = (1U << 3), - BufferAttr_FixedSize = (1U << 4), - BufferAttr_HipcAutoSelect = (1U << 5), - BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6), - BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7), + /* 0x01 */ BufferAttr_In = (1U << 0), + /* 0x02 */ BufferAttr_Out = (1U << 1), + /* 0x04 */ BufferAttr_HipcMapAlias = (1U << 2), + /* 0x08 */ BufferAttr_HipcPointer = (1U << 3), + /* 0x10 */ BufferAttr_FixedSize = (1U << 4), + /* 0x20 */ BufferAttr_HipcAutoSelect = (1U << 5), + /* 0x40 */ BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6), + /* 0x80 */ BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7), }; template <typename T, int A> @@ -172,123 +192,80 @@ struct Buffer : public std::span<T> { } }; -template <BufferAttr A> +template <int A> using InBuffer = Buffer<const u8, BufferAttr_In | A>; -template <typename T, BufferAttr A> +template <typename T, int A> using InArray = Buffer<T, BufferAttr_In | A>; -template <BufferAttr A> +template <int A> using OutBuffer = Buffer<u8, BufferAttr_Out | A>; -template <typename T, BufferAttr A> +template <typename T, int A> using OutArray = Buffer<T, BufferAttr_Out | A>; template <typename T, int A> -struct LargeData : public T { +class InLargeData { +public: static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable"); - static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize"); - static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out"); - static constexpr BufferAttr Attr = static_cast<BufferAttr>(A); - using Type = T; - - /* implicit */ LargeData(const T& rhs) : T(rhs) {} - /* implicit */ LargeData() = default; -}; - -template <typename T, BufferAttr A> -using InLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_In | A>; - -template <typename T, BufferAttr A> -using OutLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_Out | A>; + static_assert((A & BufferAttr_Out) == 0, "InLargeData attr must not be Out"); + static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize); + using Type = const T; -template <typename T> -struct RemoveOut { - using Type = std::remove_reference_t<T>; -}; - -template <typename T> -struct RemoveOut<Out<T>> { - using Type = typename Out<T>::Type; -}; + /* implicit */ InLargeData(Type& t) : raw(&t) {} + ~InLargeData() = default; -template <typename T> -struct RemoveOut<OutCopyHandle<T>> { - using Type = typename OutCopyHandle<T>::Type; -}; - -template <typename T> -struct RemoveOut<OutMoveHandle<T>> { - using Type = typename OutMoveHandle<T>::Type; -}; - -enum class ArgumentType { - InProcessId, - InData, - InInterface, - InCopyHandle, - OutData, - OutInterface, - OutCopyHandle, - OutMoveHandle, - InBuffer, - InLargeData, - OutBuffer, - OutLargeData, -}; + InLargeData& operator=(Type* rhs) { + raw = rhs; + return *this; + } -template <typename T> -struct ArgumentTraits; + Type* Get() const { + return raw; + } -template <> -struct ArgumentTraits<ClientProcessId> { - static constexpr ArgumentType Type = ArgumentType::InProcessId; -}; + Type& operator*() const { + return *raw; + } -template <typename T> -struct ArgumentTraits<SharedPointer<T>> { - static constexpr ArgumentType Type = ArgumentType::InInterface; -}; + Type* operator->() const { + return raw; + } -template <typename T> -struct ArgumentTraits<InCopyHandle<T>> { - static constexpr ArgumentType Type = ArgumentType::InCopyHandle; -}; + explicit operator bool() const { + return raw != nullptr; + } -template <typename T> -struct ArgumentTraits<Out<SharedPointer<T>>> { - static constexpr ArgumentType Type = ArgumentType::OutInterface; +private: + Type* raw; }; -template <typename T> -struct ArgumentTraits<Out<T>> { - static constexpr ArgumentType Type = ArgumentType::OutData; -}; +template <typename T, int A> +class OutLargeData { +public: + static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable"); + static_assert((A & BufferAttr_In) == 0, "OutLargeData attr must not be In"); + static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize); + using Type = T; -template <typename T> -struct ArgumentTraits<OutCopyHandle<T>> { - static constexpr ArgumentType Type = ArgumentType::OutCopyHandle; -}; + /* implicit */ OutLargeData(Type* t) : raw(t) {} + /* implicit */ OutLargeData(AutoOut<T>& t) : raw(&t.raw) {} -template <typename T> -struct ArgumentTraits<OutMoveHandle<T>> { - static constexpr ArgumentType Type = ArgumentType::OutMoveHandle; -}; + Type* Get() const { + return raw; + } -template <typename T, int A> -struct ArgumentTraits<Buffer<T, A>> { - static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer; -}; + Type& operator*() const { + return *raw; + } -template <typename T, int A> -struct ArgumentTraits<LargeData<T, A>> { - static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutLargeData : ArgumentType::InLargeData; -}; + Type* operator->() const { + return raw; + } -template <typename T> -struct ArgumentTraits { - static constexpr ArgumentType Type = ArgumentType::InData; +private: + Type* raw; }; // clang-format on -} // namespace Service +} // namespace Service
\ No newline at end of file diff --git a/src/core/hle/service/glue/time/alarm_worker.cpp b/src/core/hle/service/glue/time/alarm_worker.cpp index f549ed00a..3ff071f4a 100644 --- a/src/core/hle/service/glue/time/alarm_worker.cpp +++ b/src/core/hle/service/glue/time/alarm_worker.cpp @@ -41,7 +41,7 @@ bool AlarmWorker::GetClosestAlarmInfo(Service::PSC::Time::AlarmInfo& out_alarm_i Service::PSC::Time::AlarmInfo alarm_info{}; s64 closest_time{}; - auto res = m_time_m->GetClosestAlarmInfo(is_valid, alarm_info, closest_time); + auto res = m_time_m->GetClosestAlarmInfo(&is_valid, &alarm_info, &closest_time); ASSERT(res == ResultSuccess); if (is_valid) { @@ -76,6 +76,7 @@ void AlarmWorker::OnPowerStateChanged() { Result AlarmWorker::AttachToClosestAlarmEvent() { m_time_m->GetClosestAlarmUpdatedEvent(&m_event); + R_SUCCEED(); } diff --git a/src/core/hle/service/glue/time/alarm_worker.h b/src/core/hle/service/glue/time/alarm_worker.h index f269cffdb..131d012a6 100644 --- a/src/core/hle/service/glue/time/alarm_worker.h +++ b/src/core/hle/service/glue/time/alarm_worker.h @@ -26,7 +26,7 @@ public: void Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m); - Kernel::KEvent& GetEvent() { + Kernel::KReadableEvent& GetEvent() { return *m_event; } @@ -44,7 +44,7 @@ private: KernelHelpers::ServiceContext m_ctx; std::shared_ptr<Service::PSC::Time::ServiceManager> m_time_m; - Kernel::KEvent* m_event{}; + Kernel::KReadableEvent* m_event{}; Kernel::KEvent* m_timer_event{}; std::shared_ptr<Core::Timing::EventType> m_timer_timing_event; StandardSteadyClockResource& m_steady_clock_resource; diff --git a/src/core/hle/service/glue/time/file_timestamp_worker.cpp b/src/core/hle/service/glue/time/file_timestamp_worker.cpp index 5a6309549..048ff174c 100644 --- a/src/core/hle/service/glue/time/file_timestamp_worker.cpp +++ b/src/core/hle/service/glue/time/file_timestamp_worker.cpp @@ -13,8 +13,8 @@ void FileTimestampWorker::SetFilesystemPosixTime() { Service::PSC::Time::CalendarTime calendar_time{}; Service::PSC::Time::CalendarAdditionalInfo additional_info{}; - if (m_initialized && m_system_clock->GetCurrentTime(time) == ResultSuccess && - m_time_zone->ToCalendarTimeWithMyRule(calendar_time, additional_info, time) == + if (m_initialized && m_system_clock->GetCurrentTime(&time) == ResultSuccess && + m_time_zone->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, time) == ResultSuccess) { // TODO IFileSystemProxy::SetCurrentPosixTime } diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp index b56762941..0c27e8029 100644 --- a/src/core/hle/service/glue/time/manager.cpp +++ b/src/core/hle/service/glue/time/manager.cpp @@ -79,18 +79,18 @@ Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationN auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); Service::PSC::Time::LocationName configured_name{}; - std::memcpy(configured_name.name.data(), configured_zone.data(), - std::min(configured_name.name.size(), configured_zone.size())); + std::memcpy(configured_name.data(), configured_zone.data(), + std::min(configured_name.size(), configured_zone.size())); if (!IsTimeZoneBinaryValid(configured_name)) { configured_zone = Common::TimeZone::FindSystemTimeZone(); configured_name = {}; - std::memcpy(configured_name.name.data(), configured_zone.data(), - std::min(configured_name.name.size(), configured_zone.size())); + std::memcpy(configured_name.data(), configured_zone.data(), + std::min(configured_name.size(), configured_zone.size())); } ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!", - configured_name.name.data()); + configured_name.data()); return configured_name; } @@ -103,7 +103,7 @@ TimeManager::TimeManager(Core::System& system) m_time_m = system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true); - auto res = m_time_m->GetStaticServiceAsServiceManager(m_time_sm); + auto res = m_time_m->GetStaticServiceAsServiceManager(&m_time_sm); ASSERT(res == ResultSuccess); m_set_sys = @@ -114,10 +114,10 @@ TimeManager::TimeManager(Core::System& system) m_worker.Initialize(m_time_sm, m_set_sys); - res = m_time_sm->GetStandardUserSystemClock(m_file_timestamp_worker.m_system_clock); + res = m_time_sm->GetStandardUserSystemClock(&m_file_timestamp_worker.m_system_clock); ASSERT(res == ResultSuccess); - res = m_time_sm->GetTimeZoneService(m_file_timestamp_worker.m_time_zone); + res = m_time_sm->GetTimeZoneService(&m_file_timestamp_worker.m_time_zone); ASSERT(res == ResultSuccess); res = SetupStandardSteadyClockCore(); @@ -161,8 +161,8 @@ TimeManager::TimeManager(Core::System& system) automatic_correction_time_point); ASSERT(res == ResultSuccess); - res = m_time_m->SetupStandardUserSystemClockCore(automatic_correction_time_point, - is_automatic_correction_enabled); + res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled, + automatic_correction_time_point); ASSERT(res == ResultSuccess); res = m_time_m->SetupEphemeralNetworkSystemClockCore(); @@ -184,12 +184,12 @@ TimeManager::TimeManager(Core::System& system) m_file_timestamp_worker.m_initialized = true; s64 system_clock_time{}; - if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(system_clock_time) == + if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(&system_clock_time) == ResultSuccess) { Service::PSC::Time::CalendarTime calendar_time{}; Service::PSC::Time::CalendarAdditionalInfo calendar_additional{}; if (m_file_timestamp_worker.m_time_zone->ToCalendarTimeWithMyRule( - calendar_time, calendar_additional, system_clock_time) == ResultSuccess) { + &calendar_time, &calendar_additional, system_clock_time) == ResultSuccess) { // TODO IFileSystemProxy::SetCurrentPosixTime(system_clock_time, // calendar_additional.ut_offset) } @@ -228,10 +228,9 @@ Result TimeManager::SetupStandardSteadyClockCore() { m_set_sys->SetExternalSteadyClockSourceId(clock_source_id); } - res = m_time_m->SetupStandardSteadyClockCore(clock_source_id, m_steady_clock_resource.GetTime(), - external_steady_clock_internal_offset_ns, - standard_steady_clock_test_offset_ns, - reset_detected); + res = m_time_m->SetupStandardSteadyClockCore( + reset_detected, clock_source_id, m_steady_clock_resource.GetTime(), + external_steady_clock_internal_offset_ns, standard_steady_clock_test_offset_ns); ASSERT(res == ResultSuccess); R_SUCCEED(); } @@ -243,14 +242,15 @@ Result TimeManager::SetupTimeZoneServiceCore() { auto configured_zone = GetTimeZoneString(name); - if (configured_zone.name != name.name) { + if (configured_zone != name) { m_set_sys->SetDeviceTimeZoneLocationName(configured_zone); name = configured_zone; std::shared_ptr<Service::PSC::Time::SystemClock> local_clock; - m_time_sm->GetStandardLocalSystemClock(local_clock); + m_time_sm->GetStandardLocalSystemClock(&local_clock); + Service::PSC::Time::SystemClockContext context{}; - local_clock->GetSystemClockContext(context); + local_clock->GetSystemClockContext(&context); m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(context.steady_time_point); } @@ -267,7 +267,7 @@ Result TimeManager::SetupTimeZoneServiceCore() { res = GetTimeZoneRule(rule_buffer, rule_size, name); ASSERT(res == ResultSuccess); - res = m_time_m->SetupTimeZoneServiceCore(name, time_point, rule_version, location_count, + res = m_time_m->SetupTimeZoneServiceCore(name, rule_version, location_count, time_point, rule_buffer); ASSERT(res == ResultSuccess); diff --git a/src/core/hle/service/glue/time/static.cpp b/src/core/hle/service/glue/time/static.cpp index 63b7d91da..f56db76e1 100644 --- a/src/core/hle/service/glue/time/static.cpp +++ b/src/core/hle/service/glue/time/static.cpp @@ -3,9 +3,11 @@ #include <chrono> +#include "common/scope_exit.h" #include "core/core.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/svc.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/glue/time/file_timestamp_worker.h" #include "core/hle/service/glue/time/static.h" #include "core/hle/service/psc/time/errors.h" @@ -41,25 +43,25 @@ StaticService::StaticService(Core::System& system_, time->m_steady_clock_resource} { // clang-format off static const FunctionInfo functions[] = { - {0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"}, - {1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, - {2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"}, - {3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"}, - {4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, - {5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"}, - {20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, - {50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"}, - {51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"}, - {100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, - {101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, - {102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"}, - {200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"}, - {201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, - {300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"}, - {400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"}, - {401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"}, - {500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"}, - {501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"}, + {0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"}, + {1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"}, + {2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"}, + {3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"}, + {4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"}, + {5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"}, + {20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"}, + {50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"}, + {51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"}, + {100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, + {101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, + {102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"}, + {200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"}, + {201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, + {300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"}, + {400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"}, + {401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"}, + {500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"}, + {501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"}, }; // clang-format on @@ -71,314 +73,80 @@ StaticService::StaticService(Core::System& system_, if (m_setup_info.can_write_local_clock && m_setup_info.can_write_user_clock && !m_setup_info.can_write_network_clock && m_setup_info.can_write_timezone_device_location && !m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { - m_time_m->GetStaticServiceAsAdmin(m_wrapped_service); + m_time_m->GetStaticServiceAsAdmin(&m_wrapped_service); } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock && !m_setup_info.can_write_network_clock && !m_setup_info.can_write_timezone_device_location && !m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { - m_time_m->GetStaticServiceAsUser(m_wrapped_service); + m_time_m->GetStaticServiceAsUser(&m_wrapped_service); } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock && !m_setup_info.can_write_network_clock && !m_setup_info.can_write_timezone_device_location && m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { - m_time_m->GetStaticServiceAsRepair(m_wrapped_service); + m_time_m->GetStaticServiceAsRepair(&m_wrapped_service); } else { UNREACHABLE(); } - auto res = m_wrapped_service->GetTimeZoneService(m_time_zone); + auto res = m_wrapped_service->GetTimeZoneService(&m_time_zone); ASSERT(res == ResultSuccess); } -void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<Service::PSC::Time::SystemClock> service{}; - auto res = GetStandardUserSystemClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service)); -} - -void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<Service::PSC::Time::SystemClock> service{}; - auto res = GetStandardNetworkSystemClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service)); -} - -void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<Service::PSC::Time::SteadyClock> service{}; - auto res = GetStandardSteadyClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface(std::move(service)); -} - -void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<TimeZoneService> service{}; - auto res = GetTimeZoneService(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface(std::move(service)); -} - -void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<Service::PSC::Time::SystemClock> service{}; - auto res = GetStandardLocalSystemClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service)); -} - -void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<Service::PSC::Time::SystemClock> service{}; - auto res = GetEphemeralNetworkSystemClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service)); -} - -void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Kernel::KSharedMemory* shared_memory{}; - auto res = GetSharedMemoryNativeHandle(&shared_memory); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(res); - rb.PushCopyObjects(shared_memory); -} - -void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto offset_ns{rp.Pop<s64>()}; - - auto res = SetStandardSteadyClockInternalOffset(offset_ns); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - s64 rtc_value{}; - auto res = GetStandardSteadyClockRtcValue(rtc_value); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push(rtc_value); -} - -void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled( - HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - bool is_enabled{}; - auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push<bool>(is_enabled); -} - -void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled( - HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto automatic_correction{rp.Pop<bool>()}; - - auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - s32 initial_year{}; - auto res = GetStandardUserSystemClockInitialYear(initial_year); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(initial_year); -} - -void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) { +Result StaticService::GetStandardUserSystemClock( + OutInterface<Service::PSC::Time::SystemClock> out_service) { LOG_DEBUG(Service_Time, "called."); - bool is_sufficient{}; - auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push<bool>(is_sufficient); + R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service)); } -void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( - HLERequestContext& ctx) { +Result StaticService::GetStandardNetworkSystemClock( + OutInterface<Service::PSC::Time::SystemClock> out_service) { LOG_DEBUG(Service_Time, "called."); - Service::PSC::Time::SteadyClockTimePoint time_point{}; - auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point); - - IPC::ResponseBuilder rb{ctx, - 2 + sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point); + R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service)); } -void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) { +Result StaticService::GetStandardSteadyClock( + OutInterface<Service::PSC::Time::SteadyClock> out_service) { LOG_DEBUG(Service_Time, "called."); - IPC::RequestParser rp{ctx}; - auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()}; - - s64 time{}; - auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push<s64>(time); + R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service)); } -void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) { +Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) { LOG_DEBUG(Service_Time, "called."); - IPC::RequestParser rp{ctx}; - auto type{rp.PopEnum<Service::PSC::Time::TimeType>()}; - - Service::PSC::Time::ClockSnapshot snapshot{}; - auto res = GetClockSnapshot(snapshot, type); - - ctx.WriteBuffer(snapshot); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + *out_service = std::make_shared<TimeZoneService>( + m_system, m_file_timestamp_worker, m_setup_info.can_write_timezone_device_location, + m_time_zone); + R_SUCCEED(); } -void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) { +Result StaticService::GetStandardLocalSystemClock( + OutInterface<Service::PSC::Time::SystemClock> out_service) { LOG_DEBUG(Service_Time, "called."); - IPC::RequestParser rp{ctx}; - auto clock_type{rp.PopEnum<Service::PSC::Time::TimeType>()}; - [[maybe_unused]] auto alignment{rp.Pop<u32>()}; - auto user_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()}; - auto network_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()}; - - Service::PSC::Time::ClockSnapshot snapshot{}; - auto res = - GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type); - - ctx.WriteBuffer(snapshot); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service)); } -void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser( - HLERequestContext& ctx) { +Result StaticService::GetEphemeralNetworkSystemClock( + OutInterface<Service::PSC::Time::SystemClock> out_service) { LOG_DEBUG(Service_Time, "called."); - Service::PSC::Time::ClockSnapshot a{}; - Service::PSC::Time::ClockSnapshot b{}; - - auto a_buffer{ctx.ReadBuffer(0)}; - auto b_buffer{ctx.ReadBuffer(1)}; - - std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot)); - std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot)); - - s64 difference{}; - auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push(difference); + R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service)); } -void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) { +Result StaticService::GetSharedMemoryNativeHandle( + OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) { LOG_DEBUG(Service_Time, "called."); - Service::PSC::Time::ClockSnapshot a{}; - Service::PSC::Time::ClockSnapshot b{}; - - auto a_buffer{ctx.ReadBuffer(0)}; - auto b_buffer{ctx.ReadBuffer(1)}; - - std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot)); - std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot)); - - s64 time{}; - auto res = CalculateSpanBetween(time, a, b); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push(time); -} - -// =============================== Implementations =========================== - -Result StaticService::GetStandardUserSystemClock( - std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) { - R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service)); -} - -Result StaticService::GetStandardNetworkSystemClock( - std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) { - R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service)); -} - -Result StaticService::GetStandardSteadyClock( - std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service) { - R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service)); -} - -Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) { - out_service = std::make_shared<TimeZoneService>(m_system, m_file_timestamp_worker, - m_setup_info.can_write_timezone_device_location, - m_time_zone); - R_SUCCEED(); -} - -Result StaticService::GetStandardLocalSystemClock( - std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) { - R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service)); -} - -Result StaticService::GetEphemeralNetworkSystemClock( - std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) { - R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service)); -} - -Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) { R_RETURN(m_wrapped_service->GetSharedMemoryNativeHandle(out_shared_memory)); } Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { + LOG_DEBUG(Service_Time, "called. offset_ns={}", offset_ns); + R_UNLESS(m_setup_info.can_write_steady_clock, Service::PSC::Time::ResultPermissionDenied); R_RETURN(m_set_sys->SetExternalSteadyClockInternalOffset( @@ -386,62 +154,92 @@ Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count())); } -Result StaticService::GetStandardSteadyClockRtcValue(s64& out_rtc_value) { - R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(out_rtc_value)); +Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); }); + + R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(*out_rtc_value)); } Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled( - bool& out_automatic_correction) { + Out<bool> out_automatic_correction) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, "called. out_automatic_correction={}", *out_automatic_correction); + }); + R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled( out_automatic_correction)); } Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( bool automatic_correction) { + LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction); + R_RETURN(m_wrapped_service->SetStandardUserSystemClockAutomaticCorrectionEnabled( automatic_correction)); } -Result StaticService::GetStandardUserSystemClockInitialYear(s32& out_year) { - out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year"); +Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); }); + + *out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year"); R_SUCCEED(); } -Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) { +Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); }); + R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient)); } Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( - Service::PSC::Time::SteadyClockTimePoint& out_time_point) { + Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); + R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( out_time_point)); } Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( - s64& out_time, Service::PSC::Time::SystemClockContext& context) { + Out<s64> out_time, Service::PSC::Time::SystemClockContext& context) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); + R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context)); } -Result StaticService::GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot, +Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, Service::PSC::Time::TimeType type) { + SCOPE_EXIT( + { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); }); + R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type)); } Result StaticService::GetClockSnapshotFromSystemClockContext( - Service::PSC::Time::ClockSnapshot& out_snapshot, + Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot, Service::PSC::Time::SystemClockContext& user_context, - Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type) { - R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(out_snapshot, user_context, - network_context, type)); + Service::PSC::Time::SystemClockContext& network_context) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, + "called. type={} out_snapshot={} user_context={} network_context={}", type, + *out_snapshot, user_context, network_context); + }); + + R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext( + type, out_snapshot, user_context, network_context)); } -Result StaticService::CalculateStandardUserSystemClockDifferenceByUser( - s64& out_time, Service::PSC::Time::ClockSnapshot& a, Service::PSC::Time::ClockSnapshot& b) { +Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_time, + InClockSnapshot a, + InClockSnapshot b) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); + R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b)); } -Result StaticService::CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a, - Service::PSC::Time::ClockSnapshot& b) { +Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, + InClockSnapshot b) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); + R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b)); } diff --git a/src/core/hle/service/glue/time/static.h b/src/core/hle/service/glue/time/static.h index 75fe4e2cd..d3cc0fdd6 100644 --- a/src/core/hle/service/glue/time/static.h +++ b/src/core/hle/service/glue/time/static.h @@ -4,6 +4,7 @@ #pragma once #include "common/common_types.h" +#include "core/hle/service/cmif_types.h" #include "core/hle/service/glue/time/manager.h" #include "core/hle/service/glue/time/time_zone.h" #include "core/hle/service/psc/time/common.h" @@ -29,6 +30,10 @@ class FileTimestampWorker; class StandardSteadyClockResource; class StaticService final : public ServiceFramework<StaticService> { + using InClockSnapshot = InLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>; + using OutClockSnapshot = + OutLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>; + public: explicit StaticService(Core::System& system, Service::PSC::Time::StaticServiceSetupInfo setup_info, @@ -36,65 +41,34 @@ public: ~StaticService() override = default; - Result GetStandardUserSystemClock( - std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); - Result GetStandardNetworkSystemClock( - std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); - Result GetStandardSteadyClock(std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service); - Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service); - Result GetStandardLocalSystemClock( - std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); + Result GetStandardUserSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service); + Result GetStandardNetworkSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service); + Result GetStandardSteadyClock(OutInterface<Service::PSC::Time::SteadyClock> out_service); + Result GetTimeZoneService(OutInterface<TimeZoneService> out_service); + Result GetStandardLocalSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service); Result GetEphemeralNetworkSystemClock( - std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); - Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory); - Result SetStandardSteadyClockInternalOffset(s64 offset); - Result GetStandardSteadyClockRtcValue(s64& out_rtc_value); - Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_automatic_correction); + OutInterface<Service::PSC::Time::SystemClock> out_service); + Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory); + Result SetStandardSteadyClockInternalOffset(s64 offset_ns); + Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value); + Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled); Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); - Result GetStandardUserSystemClockInitialYear(s32& out_year); - Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient); + Result GetStandardUserSystemClockInitialYear(Out<s32> out_year); + Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient); Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( - Service::PSC::Time::SteadyClockTimePoint& out_time_point); + Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); Result CalculateMonotonicSystemClockBaseTimePoint( - s64& out_time, Service::PSC::Time::SystemClockContext& context); - Result GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot, - Service::PSC::Time::TimeType type); + Out<s64> out_time, Service::PSC::Time::SystemClockContext& context); + Result GetClockSnapshot(OutClockSnapshot out_snapshot, Service::PSC::Time::TimeType type); Result GetClockSnapshotFromSystemClockContext( - Service::PSC::Time::ClockSnapshot& out_snapshot, + Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot, Service::PSC::Time::SystemClockContext& user_context, - Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type); - Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, - Service::PSC::Time::ClockSnapshot& a, - Service::PSC::Time::ClockSnapshot& b); - Result CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a, - Service::PSC::Time::ClockSnapshot& b); + Service::PSC::Time::SystemClockContext& network_context); + Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, + InClockSnapshot a, InClockSnapshot b); + Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b); private: - Result GetClockSnapshotImpl(Service::PSC::Time::ClockSnapshot& out_snapshot, - Service::PSC::Time::SystemClockContext& user_context, - Service::PSC::Time::SystemClockContext& network_context, - Service::PSC::Time::TimeType type); - - void Handle_GetStandardUserSystemClock(HLERequestContext& ctx); - void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx); - void Handle_GetStandardSteadyClock(HLERequestContext& ctx); - void Handle_GetTimeZoneService(HLERequestContext& ctx); - void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx); - void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx); - void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx); - void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx); - void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx); - void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); - void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); - void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx); - void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx); - void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); - void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx); - void Handle_GetClockSnapshot(HLERequestContext& ctx); - void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx); - void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx); - void Handle_CalculateSpanBetween(HLERequestContext& ctx); - Core::System& m_system; std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index 503c327dd..5dc1187cb 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp @@ -3,8 +3,10 @@ #include <chrono> +#include "common/scope_exit.h" #include "core/core.h" #include "core/hle/kernel/svc.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/glue/time/file_timestamp_worker.h" #include "core/hle/service/glue/time/time_zone.h" #include "core/hle/service/glue/time/time_zone_binary.h" @@ -28,20 +30,20 @@ TimeZoneService::TimeZoneService( m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} { // clang-format off static const FunctionInfo functions[] = { - {0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"}, - {1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"}, - {2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"}, - {3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"}, - {4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"}, - {5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"}, - {6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"}, - {7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"}, - {8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"}, - {20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"}, - {100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"}, - {101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, - {201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"}, - {202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"}, + {0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"}, + {1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"}, + {2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"}, + {3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"}, + {4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"}, + {5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"}, + {6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"}, + {7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"}, + {8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"}, + {20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"}, + {100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"}, + {101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"}, + {201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"}, + {202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"}, }; // clang-format on RegisterHandlers(functions); @@ -53,220 +55,16 @@ TimeZoneService::TimeZoneService( TimeZoneService::~TimeZoneService() = default; -void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Service::PSC::Time::LocationName name{}; - auto res = GetDeviceLocationName(name); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::LocationName) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<Service::PSC::Time::LocationName>(name); -} - -void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto name{rp.PopRaw<Service::PSC::Time::LocationName>()}; - - auto res = SetDeviceLocation(name); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - u32 count{}; - auto res = GetTotalLocationNameCount(count); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(count); -} - -void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto index{rp.Pop<u32>()}; - - auto max_names{ctx.GetWriteBufferSize() / sizeof(Service::PSC::Time::LocationName)}; - - std::vector<Service::PSC::Time::LocationName> names{}; - u32 count{}; - auto res = LoadLocationNameList(count, names, max_names, index); - - ctx.WriteBuffer(names); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(count); -} - -void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto name{rp.PopRaw<Service::PSC::Time::LocationName>()}; - - Tz::Rule rule{}; - auto res = LoadTimeZoneRule(rule, name); - - ctx.WriteBuffer(rule); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Service::PSC::Time::RuleVersion rule_version{}; - auto res = GetTimeZoneRuleVersion(rule_version); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::RuleVersion) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<Service::PSC::Time::RuleVersion>(rule_version); -} - -void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Service::PSC::Time::LocationName name{}; - Service::PSC::Time::SteadyClockTimePoint time_point{}; - auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name); - - IPC::ResponseBuilder rb{ctx, - 2 + (sizeof(Service::PSC::Time::LocationName) / sizeof(u32)) + - (sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32))}; - rb.Push(res); - rb.PushRaw<Service::PSC::Time::LocationName>(name); - rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point); -} - -void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - auto res = SetDeviceLocationNameWithTimeZoneRule(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(Service::PSC::Time::ResultNotImplemented); -} - -void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle( - HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Kernel::KEvent* event{}; - auto res = GetDeviceLocationNameOperationEventReadableHandle(&event); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(res); - rb.PushCopyObjects(event->GetReadableEvent()); -} - -void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto time{rp.Pop<s64>()}; - - auto rule_buffer{ctx.ReadBuffer()}; - Tz::Rule rule{}; - std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule)); - - Service::PSC::Time::CalendarTime calendar_time{}; - Service::PSC::Time::CalendarAdditionalInfo additional_info{}; - auto res = ToCalendarTime(calendar_time, additional_info, time, rule); - - IPC::ResponseBuilder rb{ctx, - 2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) + - (sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))}; - rb.Push(res); - rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time); - rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info); -} - -void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - auto time{rp.Pop<s64>()}; - - LOG_DEBUG(Service_Time, "called. time={}", time); - - Service::PSC::Time::CalendarTime calendar_time{}; - Service::PSC::Time::CalendarAdditionalInfo additional_info{}; - auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time); - - IPC::ResponseBuilder rb{ctx, - 2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) + - (sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))}; - rb.Push(res); - rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time); - rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info); -} - -void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()}; - - LOG_DEBUG(Service_Time, "called. calendar year {} month {} day {} hour {} minute {} second {}", - calendar.year, calendar.month, calendar.day, calendar.hour, calendar.minute, - calendar.second); - - auto binary{ctx.ReadBuffer()}; - - Tz::Rule rule{}; - std::memcpy(&rule, binary.data(), sizeof(Tz::Rule)); - - u32 count{}; - std::array<s64, 2> times{}; - u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))}; - - auto res = ToPosixTime(count, times, times_count, calendar, rule); - - ctx.WriteBuffer(times); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(count); -} - -void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()}; - - u32 count{}; - std::array<s64, 2> times{}; - u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))}; - - auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar); - - ctx.WriteBuffer(times); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(count); -} +Result TimeZoneService::GetDeviceLocationName( + Out<Service::PSC::Time::LocationName> out_location_name) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); }); -// =============================== Implementations =========================== - -Result TimeZoneService::GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name) { R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name)); } -Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& location_name) { +Result TimeZoneService::SetDeviceLocationName(Service::PSC::Time::LocationName& location_name) { + LOG_DEBUG(Service_Time, "called. location_name={}", location_name); + R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound); @@ -282,7 +80,7 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca Service::PSC::Time::SteadyClockTimePoint time_point{}; Service::PSC::Time::LocationName name{}; - R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(time_point, name)); + R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(&name, &time_point)); m_set_sys->SetDeviceTimeZoneLocationName(name); m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point); @@ -294,19 +92,27 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca R_SUCCEED(); } -Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) { +Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); }); + R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count)); } Result TimeZoneService::LoadLocationNameList( - u32& out_count, std::vector<Service::PSC::Time::LocationName>& out_names, size_t max_names, - u32 index) { + Out<u32> out_count, + OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}", + index, *out_count, out_names[0], out_names[1]); + }); + std::scoped_lock l{m_mutex}; - R_RETURN(GetTimeZoneLocationList(out_count, out_names, max_names, index)); + R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index)); } -Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule, - Service::PSC::Time::LocationName& name) { +Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& name) { + LOG_DEBUG(Service_Time, "called. name={}", name); + std::scoped_lock l{m_mutex}; std::span<const u8> binary{}; size_t binary_size{}; @@ -314,23 +120,43 @@ Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule, R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary)); } -Result TimeZoneService::GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version) { +Result TimeZoneService::GetTimeZoneRuleVersion( + Out<Service::PSC::Time::RuleVersion> out_rule_version) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); }); + R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version)); } Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( - Service::PSC::Time::SteadyClockTimePoint& out_time_point, - Service::PSC::Time::LocationName& location_name) { - R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(out_time_point, location_name)); + Out<Service::PSC::Time::LocationName> location_name, + Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, "called. location_name={} out_time_point={}", *location_name, + *out_time_point); + }); + + R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(location_name, out_time_point)); } -Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule() { +Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule( + Service::PSC::Time::LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) { + LOG_DEBUG(Service_Time, "called. location_name={}", location_name); + R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); R_RETURN(Service::PSC::Time::ResultNotImplemented); } +Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule, + InBuffer<BufferAttr_HipcAutoSelect> binary) { + LOG_DEBUG(Service_Time, "called."); + + R_RETURN(Service::PSC::Time::ResultNotImplemented); +} + Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( - Kernel::KEvent** out_event) { + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_Time, "called."); + if (!operation_event_initialized) { operation_event_initialized = false; @@ -342,34 +168,59 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( g_list_nodes.push_back(m_operation_event); } - *out_event = m_operation_event.m_event; + *out_event = &m_operation_event.m_event->GetReadableEvent(); R_SUCCEED(); } Result TimeZoneService::ToCalendarTime( - Service::PSC::Time::CalendarTime& out_calendar_time, - Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule) { + Out<Service::PSC::Time::CalendarTime> out_calendar_time, + Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, + *out_calendar_time, *out_additional_info); + }); + R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule)); } Result TimeZoneService::ToCalendarTimeWithMyRule( - Service::PSC::Time::CalendarTime& out_calendar_time, - Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time) { + Out<Service::PSC::Time::CalendarTime> out_calendar_time, + Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, + *out_calendar_time, *out_additional_info); + }); + R_RETURN( m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time)); } -Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, - u32 out_times_count, - Service::PSC::Time::CalendarTime& calendar_time, - Tz::Rule& rule) { +Result TimeZoneService::ToPosixTime(Out<u32> out_count, + OutArray<s64, BufferAttr_HipcPointer> out_times, + Out<u32> out_times_count, + Service::PSC::Time::CalendarTime& calendar_time, InRule rule) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, + "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} " + "out_times_count={}", + calendar_time, *out_count, out_times[0], out_times[1], *out_times_count); + }); + R_RETURN( m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule)); } -Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, - u32 out_times_count, +Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count, + OutArray<s64, BufferAttr_HipcPointer> out_times, + Out<u32> out_times_count, Service::PSC::Time::CalendarTime& calendar_time) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, + "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} " + "out_times_count={}", + calendar_time, *out_count, out_times[0], out_times[1], *out_times_count); + }); + R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count, calendar_time)); } diff --git a/src/core/hle/service/glue/time/time_zone.h b/src/core/hle/service/glue/time/time_zone.h index 3c8ae4bf8..bf12adbdc 100644 --- a/src/core/hle/service/glue/time/time_zone.h +++ b/src/core/hle/service/glue/time/time_zone.h @@ -8,6 +8,7 @@ #include <span> #include <vector> +#include "core/hle/service/cmif_types.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/psc/time/common.h" #include "core/hle/service/server_manager.h" @@ -33,6 +34,9 @@ namespace Service::Glue::Time { class FileTimestampWorker; class TimeZoneService final : public ServiceFramework<TimeZoneService> { + using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>; + using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>; + public: explicit TimeZoneService( Core::System& system, FileTimestampWorker& file_timestamp_worker, @@ -41,46 +45,37 @@ public: ~TimeZoneService() override; - Result GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name); - Result SetDeviceLocation(Service::PSC::Time::LocationName& location_name); - Result GetTotalLocationNameCount(u32& out_count); - Result LoadLocationNameList(u32& out_count, - std::vector<Service::PSC::Time::LocationName>& out_names, - size_t max_names, u32 index); - Result LoadTimeZoneRule(Tz::Rule& out_rule, Service::PSC::Time::LocationName& name); - Result GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version); + Result GetDeviceLocationName(Out<Service::PSC::Time::LocationName> out_location_name); + Result SetDeviceLocationName(Service::PSC::Time::LocationName& location_name); + Result GetTotalLocationNameCount(Out<u32> out_count); + Result LoadLocationNameList( + Out<u32> out_count, + OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index); + Result LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& location_name); + Result GetTimeZoneRuleVersion(Out<Service::PSC::Time::RuleVersion> out_rule_version); Result GetDeviceLocationNameAndUpdatedTime( - Service::PSC::Time::SteadyClockTimePoint& out_time_point, - Service::PSC::Time::LocationName& location_name); - Result SetDeviceLocationNameWithTimeZoneRule(); - Result GetDeviceLocationNameOperationEventReadableHandle(Kernel::KEvent** out_event); - Result ToCalendarTime(Service::PSC::Time::CalendarTime& out_calendar_time, - Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time, - Tz::Rule& rule); - Result ToCalendarTimeWithMyRule(Service::PSC::Time::CalendarTime& out_calendar_time, - Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, - s64 time); - Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, - Service::PSC::Time::CalendarTime& calendar_time, Tz::Rule& rule); - Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, + Out<Service::PSC::Time::LocationName> location_name, + Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); + Result SetDeviceLocationNameWithTimeZoneRule(Service::PSC::Time::LocationName& location_name, + InBuffer<BufferAttr_HipcAutoSelect> binary); + Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary); + Result GetDeviceLocationNameOperationEventReadableHandle( + OutCopyHandle<Kernel::KReadableEvent> out_event); + Result ToCalendarTime(Out<Service::PSC::Time::CalendarTime> out_calendar_time, + Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, + s64 time, InRule rule); + Result ToCalendarTimeWithMyRule( + Out<Service::PSC::Time::CalendarTime> out_calendar_time, + Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time); + Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, + Out<u32> out_times_count, Service::PSC::Time::CalendarTime& calendar_time, + InRule rule); + Result ToPosixTimeWithMyRule(Out<u32> out_count, + OutArray<s64, BufferAttr_HipcPointer> out_times, + Out<u32> out_times_count, Service::PSC::Time::CalendarTime& calendar_time); private: - void Handle_GetDeviceLocationName(HLERequestContext& ctx); - void Handle_SetDeviceLocationName(HLERequestContext& ctx); - void Handle_GetTotalLocationNameCount(HLERequestContext& ctx); - void Handle_LoadLocationNameList(HLERequestContext& ctx); - void Handle_LoadTimeZoneRule(HLERequestContext& ctx); - void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx); - void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx); - void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx); - void Handle_ParseTimeZoneBinary(HLERequestContext& ctx); - void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx); - void Handle_ToCalendarTime(HLERequestContext& ctx); - void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx); - void Handle_ToPosixTime(HLERequestContext& ctx); - void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx); - Core::System& m_system; std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; diff --git a/src/core/hle/service/glue/time/time_zone_binary.cpp b/src/core/hle/service/glue/time/time_zone_binary.cpp index d33f784c0..cc50b6b7b 100644 --- a/src/core/hle/service/glue/time/time_zone_binary.cpp +++ b/src/core/hle/service/glue/time/time_zone_binary.cpp @@ -103,7 +103,7 @@ void GetTimeZoneZonePath(std::string& out_path, Service::PSC::Time::LocationName return; } // out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name); - out_path = fmt::format("/zoneinfo/{}", name.name.data()); + out_path = fmt::format("/zoneinfo/{}", name.data()); } bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) { @@ -169,7 +169,7 @@ Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size, } Result GetTimeZoneLocationList(u32& out_count, - std::vector<Service::PSC::Time::LocationName>& out_names, + std::span<Service::PSC::Time::LocationName> out_names, size_t max_names, u32 index) { std::string path{}; GetTimeZoneBinaryListPath(path); @@ -193,7 +193,7 @@ Result GetTimeZoneLocationList(u32& out_count, if (chr == '\n') { if (name_count >= index) { - out_names.push_back(current_name); + out_names[out_count] = current_name; out_count++; if (out_count >= max_names) { break; @@ -209,10 +209,9 @@ Result GetTimeZoneLocationList(u32& out_count, break; } - R_UNLESS(current_name_len <= current_name.name.size() - 2, - Service::PSC::Time::ResultFailed); + R_UNLESS(current_name_len <= current_name.size() - 2, Service::PSC::Time::ResultFailed); - current_name.name[current_name_len++] = chr; + current_name[current_name_len++] = chr; } R_SUCCEED(); diff --git a/src/core/hle/service/glue/time/time_zone_binary.h b/src/core/hle/service/glue/time/time_zone_binary.h index 2cad6b458..461f4577e 100644 --- a/src/core/hle/service/glue/time/time_zone_binary.h +++ b/src/core/hle/service/glue/time/time_zone_binary.h @@ -26,7 +26,7 @@ Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version); Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size, Service::PSC::Time::LocationName& name); Result GetTimeZoneLocationList(u32& out_count, - std::vector<Service::PSC::Time::LocationName>& out_names, + std::span<Service::PSC::Time::LocationName> out_names, size_t max_names, u32 index); } // namespace Service::Glue::Time diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp index ea0e49b90..f44f3077e 100644 --- a/src/core/hle/service/glue/time/worker.cpp +++ b/src/core/hle/service/glue/time/worker.cpp @@ -38,11 +38,12 @@ T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource, FileTimestampWorker& file_timestamp_worker) - : m_system{system}, m_ctx{m_system, "Glue:58"}, m_event{m_ctx.CreateEvent("Glue:58:Event")}, + : m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent( + "Glue:TimeWorker:Event")}, m_steady_clock_resource{steady_clock_resource}, m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent( - "Glue:58:SteadyClockTimerEvent")}, - m_timer_file_system{m_ctx.CreateEvent("Glue:58:FileTimeTimerEvent")}, + "Glue:TimeWorker:SteadyClockTimerEvent")}, + m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")}, m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} { g_ig_report_network_clock_context_set = false; g_report_network_clock_context = {}; @@ -113,17 +114,17 @@ void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> t std::chrono::nanoseconds(fs_notify_time_ns), m_timer_file_system_timing_event); - auto res = m_time_sm->GetStandardLocalSystemClock(m_local_clock); + auto res = m_time_sm->GetStandardLocalSystemClock(&m_local_clock); ASSERT(res == ResultSuccess); res = m_time_m->GetStandardLocalClockOperationEvent(&m_local_clock_event); ASSERT(res == ResultSuccess); - res = m_time_sm->GetStandardNetworkSystemClock(m_network_clock); + res = m_time_sm->GetStandardNetworkSystemClock(&m_network_clock); ASSERT(res == ResultSuccess); res = m_time_m->GetStandardNetworkClockOperationEventForServiceManager(&m_network_clock_event); ASSERT(res == ResultSuccess); - res = m_time_sm->GetEphemeralNetworkSystemClock(m_ephemeral_clock); + res = m_time_sm->GetEphemeralNetworkSystemClock(&m_ephemeral_clock); ASSERT(res == ResultSuccess); res = m_time_m->GetEphemeralNetworkClockOperationEventForServiceManager(&m_ephemeral_clock_event); @@ -183,22 +184,19 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); // TODO // AddWaiter(gIPmModuleService::GetEvent(), 1); - AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange); + AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange); } else { AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); // TODO // AddWaiter(gIPmModuleService::GetEvent(), 1); - AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange); + AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange); AddWaiter(&m_alarm_worker.GetTimerEvent().GetReadableEvent(), EventType::SignalAlarms); - AddWaiter(&m_local_clock_event->GetReadableEvent(), EventType::UpdateLocalSystemClock); - AddWaiter(&m_network_clock_event->GetReadableEvent(), - EventType::UpdateNetworkSystemClock); - AddWaiter(&m_ephemeral_clock_event->GetReadableEvent(), - EventType::UpdateEphemeralSystemClock); + AddWaiter(m_local_clock_event, EventType::UpdateLocalSystemClock); + AddWaiter(m_network_clock_event, EventType::UpdateNetworkSystemClock); + AddWaiter(m_ephemeral_clock_event, EventType::UpdateEphemeralSystemClock); AddWaiter(&m_timer_steady_clock->GetReadableEvent(), EventType::UpdateSteadyClock); AddWaiter(&m_timer_file_system->GetReadableEvent(), EventType::UpdateFileTimestamp); - AddWaiter(&m_standard_user_auto_correct_clock_event->GetReadableEvent(), - EventType::AutoCorrect); + AddWaiter(m_standard_user_auto_correct_clock_event, EventType::AutoCorrect); } s32 out_index{-1}; @@ -237,7 +235,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { m_local_clock_event->Clear(); Service::PSC::Time::SystemClockContext context{}; - auto res = m_local_clock->GetSystemClockContext(context); + auto res = m_local_clock->GetSystemClockContext(&context); ASSERT(res == ResultSuccess); m_set_sys->SetUserSystemClockContext(context); @@ -248,12 +246,12 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { case EventType::UpdateNetworkSystemClock: { m_network_clock_event->Clear(); Service::PSC::Time::SystemClockContext context{}; - auto res = m_network_clock->GetSystemClockContext(context); + auto res = m_network_clock->GetSystemClockContext(&context); ASSERT(res == ResultSuccess); m_set_sys->SetNetworkSystemClockContext(context); s64 time{}; - if (m_network_clock->GetCurrentTime(time) != ResultSuccess) { + if (m_network_clock->GetCurrentTime(&time) != ResultSuccess) { break; } @@ -275,13 +273,13 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { m_ephemeral_clock_event->Clear(); Service::PSC::Time::SystemClockContext context{}; - auto res = m_ephemeral_clock->GetSystemClockContext(context); + auto res = m_ephemeral_clock->GetSystemClockContext(&context); if (res != ResultSuccess) { break; } s64 time{}; - res = m_ephemeral_clock->GetCurrentTime(time); + res = m_ephemeral_clock->GetCurrentTime(&time); if (res != ResultSuccess) { break; } @@ -317,11 +315,11 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { bool automatic_correction{}; auto res = m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled( - automatic_correction); + &automatic_correction); ASSERT(res == ResultSuccess); Service::PSC::Time::SteadyClockTimePoint time_point{}; - res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point); + res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(&time_point); ASSERT(res == ResultSuccess); m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction); diff --git a/src/core/hle/service/glue/time/worker.h b/src/core/hle/service/glue/time/worker.h index adbbe6b6d..75e5c4d0f 100644 --- a/src/core/hle/service/glue/time/worker.h +++ b/src/core/hle/service/glue/time/worker.h @@ -49,10 +49,10 @@ private: std::shared_ptr<Service::PSC::Time::SystemClock> m_ephemeral_clock; StandardSteadyClockResource& m_steady_clock_resource; FileTimestampWorker& m_file_timestamp_worker; - Kernel::KEvent* m_local_clock_event{}; - Kernel::KEvent* m_network_clock_event{}; - Kernel::KEvent* m_ephemeral_clock_event{}; - Kernel::KEvent* m_standard_user_auto_correct_clock_event{}; + Kernel::KReadableEvent* m_local_clock_event{}; + Kernel::KReadableEvent* m_network_clock_event{}; + Kernel::KReadableEvent* m_ephemeral_clock_event{}; + Kernel::KReadableEvent* m_standard_user_auto_correct_clock_event{}; Kernel::KEvent* m_timer_steady_clock{}; std::shared_ptr<Core::Timing::EventType> m_timer_steady_clock_timing_event; Kernel::KEvent* m_timer_file_system{}; diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index c28eed926..b4d16fed5 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp @@ -4,15 +4,18 @@ #include <memory> #include "common/logging/log.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/mii/mii.h" #include "core/hle/service/mii/mii_manager.h" #include "core/hle/service/mii/mii_result.h" #include "core/hle/service/mii/types/char_info.h" +#include "core/hle/service/mii/types/raw_data.h" #include "core/hle/service/mii/types/store_data.h" #include "core/hle/service/mii/types/ver3_store_data.h" #include "core/hle/service/server_manager.h" -#include "core/hle/service/service.h" +#include "core/hle/service/set/system_settings_server.h" +#include "core/hle/service/sm/sm.h" namespace Service::Mii { @@ -24,549 +27,302 @@ public: is_system_} { // clang-format off static const FunctionInfo functions[] = { - {0, &IDatabaseService::IsUpdated, "IsUpdated"}, - {1, &IDatabaseService::IsFullDatabase, "IsFullDatabase"}, - {2, &IDatabaseService::GetCount, "GetCount"}, - {3, &IDatabaseService::Get, "Get"}, - {4, &IDatabaseService::Get1, "Get1"}, - {5, &IDatabaseService::UpdateLatest, "UpdateLatest"}, - {6, &IDatabaseService::BuildRandom, "BuildRandom"}, - {7, &IDatabaseService::BuildDefault, "BuildDefault"}, - {8, &IDatabaseService::Get2, "Get2"}, - {9, &IDatabaseService::Get3, "Get3"}, - {10, &IDatabaseService::UpdateLatest1, "UpdateLatest1"}, - {11, &IDatabaseService::FindIndex, "FindIndex"}, - {12, &IDatabaseService::Move, "Move"}, - {13, &IDatabaseService::AddOrReplace, "AddOrReplace"}, - {14, &IDatabaseService::Delete, "Delete"}, - {15, &IDatabaseService::DestroyFile, "DestroyFile"}, - {16, &IDatabaseService::DeleteFile, "DeleteFile"}, - {17, &IDatabaseService::Format, "Format"}, + {0, D<&IDatabaseService::IsUpdated>, "IsUpdated"}, + {1, D<&IDatabaseService::IsFullDatabase>, "IsFullDatabase"}, + {2, D<&IDatabaseService::GetCount>, "GetCount"}, + {3, D<&IDatabaseService::Get>, "Get"}, + {4, D<&IDatabaseService::Get1>, "Get1"}, + {5, D<&IDatabaseService::UpdateLatest>, "UpdateLatest"}, + {6, D<&IDatabaseService::BuildRandom>, "BuildRandom"}, + {7, D<&IDatabaseService::BuildDefault>, "BuildDefault"}, + {8, D<&IDatabaseService::Get2>, "Get2"}, + {9, D<&IDatabaseService::Get3>, "Get3"}, + {10, D<&IDatabaseService::UpdateLatest1>, "UpdateLatest1"}, + {11, D<&IDatabaseService::FindIndex>, "FindIndex"}, + {12, D<&IDatabaseService::Move>, "Move"}, + {13, D<&IDatabaseService::AddOrReplace>, "AddOrReplace"}, + {14, D<&IDatabaseService::Delete>, "Delete"}, + {15, D<&IDatabaseService::DestroyFile>, "DestroyFile"}, + {16, D<&IDatabaseService::DeleteFile>, "DeleteFile"}, + {17, D<&IDatabaseService::Format>, "Format"}, {18, nullptr, "Import"}, {19, nullptr, "Export"}, - {20, &IDatabaseService::IsBrokenDatabaseWithClearFlag, "IsBrokenDatabaseWithClearFlag"}, - {21, &IDatabaseService::GetIndex, "GetIndex"}, - {22, &IDatabaseService::SetInterfaceVersion, "SetInterfaceVersion"}, - {23, &IDatabaseService::Convert, "Convert"}, - {24, &IDatabaseService::ConvertCoreDataToCharInfo, "ConvertCoreDataToCharInfo"}, - {25, &IDatabaseService::ConvertCharInfoToCoreData, "ConvertCharInfoToCoreData"}, - {26, &IDatabaseService::Append, "Append"}, + {20, D<&IDatabaseService::IsBrokenDatabaseWithClearFlag>, "IsBrokenDatabaseWithClearFlag"}, + {21, D<&IDatabaseService::GetIndex>, "GetIndex"}, + {22, D<&IDatabaseService::SetInterfaceVersion>, "SetInterfaceVersion"}, + {23, D<&IDatabaseService::Convert>, "Convert"}, + {24, D<&IDatabaseService::ConvertCoreDataToCharInfo>, "ConvertCoreDataToCharInfo"}, + {25, D<&IDatabaseService::ConvertCharInfoToCoreData>, "ConvertCharInfoToCoreData"}, + {26, D<&IDatabaseService::Append>, "Append"}, }; // clang-format on RegisterHandlers(functions); + m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>( + "set:sys", true); manager->Initialize(metadata); } private: - void IsUpdated(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto source_flag{rp.PopRaw<SourceFlag>()}; - + Result IsUpdated(Out<bool> out_is_updated, SourceFlag source_flag) { LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); - const bool is_updated = manager->IsUpdated(metadata, source_flag); + *out_is_updated = manager->IsUpdated(metadata, source_flag); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(is_updated); + R_SUCCEED(); } - void IsFullDatabase(HLERequestContext& ctx) { + Result IsFullDatabase(Out<bool> out_is_full_database) { LOG_DEBUG(Service_Mii, "called"); - const bool is_full_database = manager->IsFullDatabase(); + *out_is_full_database = manager->IsFullDatabase(); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(is_full_database); + R_SUCCEED(); } - void GetCount(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto source_flag{rp.PopRaw<SourceFlag>()}; - - const u32 mii_count = manager->GetCount(metadata, source_flag); + Result GetCount(Out<u32> out_mii_count, SourceFlag source_flag) { + *out_mii_count = manager->GetCount(metadata, source_flag); - LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, mii_count); + LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, + *out_mii_count); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(mii_count); + R_SUCCEED(); } - void Get(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto source_flag{rp.PopRaw<SourceFlag>()}; - const auto output_size{ctx.GetWriteBufferNumElements<CharInfoElement>()}; - - u32 mii_count{}; - std::vector<CharInfoElement> char_info_elements(output_size); - const auto result = manager->Get(metadata, char_info_elements, mii_count, source_flag); - - if (mii_count != 0) { - ctx.WriteBuffer(char_info_elements); - } + Result Get(Out<u32> out_mii_count, SourceFlag source_flag, + OutArray<CharInfoElement, BufferAttr_HipcMapAlias> char_info_element_buffer) { + const auto result = + manager->Get(metadata, char_info_element_buffer, *out_mii_count, source_flag); - LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag, - output_size, mii_count); + LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, + *out_mii_count); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push(mii_count); + R_RETURN(result); } - void Get1(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto source_flag{rp.PopRaw<SourceFlag>()}; - const auto output_size{ctx.GetWriteBufferNumElements<CharInfo>()}; + Result Get1(Out<u32> out_mii_count, SourceFlag source_flag, + OutArray<CharInfo, BufferAttr_HipcMapAlias> char_info_buffer) { + const auto result = manager->Get(metadata, char_info_buffer, *out_mii_count, source_flag); - u32 mii_count{}; - std::vector<CharInfo> char_info(output_size); - const auto result = manager->Get(metadata, char_info, mii_count, source_flag); + LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, + *out_mii_count); - if (mii_count != 0) { - ctx.WriteBuffer(char_info); - } - - LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag, - output_size, mii_count); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push(mii_count); + R_RETURN(result); } - void UpdateLatest(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto char_info{rp.PopRaw<CharInfo>()}; - const auto source_flag{rp.PopRaw<SourceFlag>()}; - + Result UpdateLatest(Out<CharInfo> out_char_info, CharInfo& char_info, SourceFlag source_flag) { LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); - CharInfo new_char_info{}; - const auto result = manager->UpdateLatest(metadata, new_char_info, char_info, source_flag); - if (result.IsFailure()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - return; - } - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; - rb.Push(ResultSuccess); - rb.PushRaw(new_char_info); + R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag)); } - void BuildRandom(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto age{rp.PopRaw<Age>()}; - const auto gender{rp.PopRaw<Gender>()}; - const auto race{rp.PopRaw<Race>()}; - + Result BuildRandom(Out<CharInfo> out_char_info, Age age, Gender gender, Race race) { LOG_DEBUG(Service_Mii, "called with age={}, gender={}, race={}", age, gender, race); - if (age > Age::All) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultInvalidArgument); - return; - } - - if (gender > Gender::All) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultInvalidArgument); - return; - } - - if (race > Race::All) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultInvalidArgument); - return; - } - - CharInfo char_info{}; - manager->BuildRandom(char_info, age, gender, race); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; - rb.Push(ResultSuccess); - rb.PushRaw(char_info); - } + R_UNLESS(age <= Age::All, ResultInvalidArgument); + R_UNLESS(gender <= Gender::All, ResultInvalidArgument); + R_UNLESS(race <= Race::All, ResultInvalidArgument); - void BuildDefault(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto index{rp.Pop<u32>()}; + manager->BuildRandom(*out_char_info, age, gender, race); - LOG_DEBUG(Service_Mii, "called with index={}", index); + R_SUCCEED(); + } - if (index > 5) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultInvalidArgument); - return; - } + Result BuildDefault(Out<CharInfo> out_char_info, s32 index) { + LOG_DEBUG(Service_Mii, "called with index={}", index); + R_UNLESS(index < static_cast<s32>(RawData::DefaultMii.size()), ResultInvalidArgument); - CharInfo char_info{}; - manager->BuildDefault(char_info, index); + manager->BuildDefault(*out_char_info, index); - IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; - rb.Push(ResultSuccess); - rb.PushRaw(char_info); + R_SUCCEED(); } - void Get2(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto source_flag{rp.PopRaw<SourceFlag>()}; - const auto output_size{ctx.GetWriteBufferNumElements<StoreDataElement>()}; + Result Get2(Out<u32> out_mii_count, SourceFlag source_flag, + OutArray<StoreDataElement, BufferAttr_HipcMapAlias> store_data_element_buffer) { + const auto result = + manager->Get(metadata, store_data_element_buffer, *out_mii_count, source_flag); - u32 mii_count{}; - std::vector<StoreDataElement> store_data_elements(output_size); - const auto result = manager->Get(metadata, store_data_elements, mii_count, source_flag); + LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, + *out_mii_count); - if (mii_count != 0) { - ctx.WriteBuffer(store_data_elements); - } - - LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag, - output_size, mii_count); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push(mii_count); + R_RETURN(result); } - void Get3(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto source_flag{rp.PopRaw<SourceFlag>()}; - const auto output_size{ctx.GetWriteBufferNumElements<StoreData>()}; - - u32 mii_count{}; - std::vector<StoreData> store_data(output_size); - const auto result = manager->Get(metadata, store_data, mii_count, source_flag); + Result Get3(Out<u32> out_mii_count, SourceFlag source_flag, + OutArray<StoreData, BufferAttr_HipcMapAlias> store_data_buffer) { + const auto result = manager->Get(metadata, store_data_buffer, *out_mii_count, source_flag); - if (mii_count != 0) { - ctx.WriteBuffer(store_data); - } + LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, + *out_mii_count); - LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag, - output_size, mii_count); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push(mii_count); + R_RETURN(result); } - void UpdateLatest1(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto store_data{rp.PopRaw<StoreData>()}; - const auto source_flag{rp.PopRaw<SourceFlag>()}; - + Result UpdateLatest1(Out<StoreData> out_store_data, StoreData& store_data, + SourceFlag source_flag) { LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); + R_UNLESS(is_system, ResultPermissionDenied); - Result result = ResultSuccess; - if (!is_system) { - result = ResultPermissionDenied; - } - - StoreData new_store_data{}; - if (result.IsSuccess()) { - result = manager->UpdateLatest(metadata, new_store_data, store_data, source_flag); - } - - if (result.IsFailure()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - return; - } - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(StoreData) / sizeof(u32)}; - rb.Push(ResultSuccess); - rb.PushRaw<StoreData>(new_store_data); + R_RETURN(manager->UpdateLatest(metadata, *out_store_data, store_data, source_flag)); } - void FindIndex(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto create_id{rp.PopRaw<Common::UUID>()}; - const auto is_special{rp.PopRaw<bool>()}; - + Result FindIndex(Out<s32> out_index, Common::UUID create_id, bool is_special) { LOG_INFO(Service_Mii, "called with create_id={}, is_special={}", create_id.FormattedString(), is_special); - const s32 index = manager->FindIndex(create_id, is_special); + *out_index = manager->FindIndex(create_id, is_special); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(index); + R_SUCCEED(); } - void Move(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto create_id{rp.PopRaw<Common::UUID>()}; - const auto new_index{rp.PopRaw<s32>()}; - + Result Move(Common::UUID create_id, s32 new_index) { LOG_INFO(Service_Mii, "called with create_id={}, new_index={}", create_id.FormattedString(), new_index); + R_UNLESS(is_system, ResultPermissionDenied); - Result result = ResultSuccess; - if (!is_system) { - result = ResultPermissionDenied; - } + const u32 count = manager->GetCount(metadata, SourceFlag::Database); - if (result.IsSuccess()) { - const u32 count = manager->GetCount(metadata, SourceFlag::Database); - if (new_index < 0 || new_index >= static_cast<s32>(count)) { - result = ResultInvalidArgument; - } - } + R_UNLESS(new_index >= 0 && new_index < static_cast<s32>(count), ResultInvalidArgument); - if (result.IsSuccess()) { - result = manager->Move(metadata, new_index, create_id); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(manager->Move(metadata, new_index, create_id)); } - void AddOrReplace(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto store_data{rp.PopRaw<StoreData>()}; - + Result AddOrReplace(StoreData& store_data) { LOG_INFO(Service_Mii, "called"); + R_UNLESS(is_system, ResultPermissionDenied); - Result result = ResultSuccess; - - if (!is_system) { - result = ResultPermissionDenied; - } + const auto result = manager->AddOrReplace(metadata, store_data); - if (result.IsSuccess()) { - result = manager->AddOrReplace(metadata, store_data); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(result); } - void Delete(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto create_id{rp.PopRaw<Common::UUID>()}; - + Result Delete(Common::UUID create_id) { LOG_INFO(Service_Mii, "called, create_id={}", create_id.FormattedString()); + R_UNLESS(is_system, ResultPermissionDenied); - Result result = ResultSuccess; - - if (!is_system) { - result = ResultPermissionDenied; - } - - if (result.IsSuccess()) { - result = manager->Delete(metadata, create_id); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(manager->Delete(metadata, create_id)); } - void DestroyFile(HLERequestContext& ctx) { - // This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled"); - const bool is_db_test_mode_enabled = false; + Result DestroyFile() { + bool is_db_test_mode_enabled{}; + m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled"); LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); + R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly); - Result result = ResultSuccess; - - if (!is_db_test_mode_enabled) { - result = ResultTestModeOnly; - } - - if (result.IsSuccess()) { - result = manager->DestroyFile(metadata); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(manager->DestroyFile(metadata)); } - void DeleteFile(HLERequestContext& ctx) { - // This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled"); - const bool is_db_test_mode_enabled = false; + Result DeleteFile() { + bool is_db_test_mode_enabled{}; + m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled"); LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); + R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly); - Result result = ResultSuccess; - - if (!is_db_test_mode_enabled) { - result = ResultTestModeOnly; - } - - if (result.IsSuccess()) { - result = manager->DeleteFile(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(manager->DeleteFile()); } - void Format(HLERequestContext& ctx) { - // This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled"); - const bool is_db_test_mode_enabled = false; + Result Format() { + bool is_db_test_mode_enabled{}; + m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled"); LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); + R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly); - Result result = ResultSuccess; - - if (!is_db_test_mode_enabled) { - result = ResultTestModeOnly; - } - - if (result.IsSuccess()) { - result = manager->Format(metadata); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(manager->Format(metadata)); } - void IsBrokenDatabaseWithClearFlag(HLERequestContext& ctx) { + Result IsBrokenDatabaseWithClearFlag(Out<bool> out_is_broken_with_clear_flag) { LOG_DEBUG(Service_Mii, "called"); + R_UNLESS(is_system, ResultPermissionDenied); - bool is_broken_with_clear_flag = false; - Result result = ResultSuccess; + *out_is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata); - if (!is_system) { - result = ResultPermissionDenied; - } - - if (result.IsSuccess()) { - is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata); - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push<u8>(is_broken_with_clear_flag); + R_SUCCEED(); } - void GetIndex(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto info{rp.PopRaw<CharInfo>()}; - + Result GetIndex(Out<s32> out_index, CharInfo& char_info) { LOG_DEBUG(Service_Mii, "called"); - s32 index{}; - const auto result = manager->GetIndex(metadata, info, index); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push(index); + R_RETURN(manager->GetIndex(metadata, char_info, *out_index)); } - void SetInterfaceVersion(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto interface_version{rp.PopRaw<u32>()}; - + Result SetInterfaceVersion(u32 interface_version) { LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version); manager->SetInterfaceVersion(metadata, interface_version); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } - void Convert(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto mii_v3{rp.PopRaw<Ver3StoreData>()}; - + Result Convert(Out<CharInfo> out_char_info, Ver3StoreData& mii_v3) { LOG_INFO(Service_Mii, "called"); - CharInfo char_info{}; - const auto result = manager->ConvertV3ToCharInfo(char_info, mii_v3); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; - rb.Push(result); - rb.PushRaw<CharInfo>(char_info); + R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3)); } - void ConvertCoreDataToCharInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto core_data{rp.PopRaw<CoreData>()}; - + Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, CoreData& core_data) { LOG_INFO(Service_Mii, "called"); - CharInfo char_info{}; - const auto result = manager->ConvertCoreDataToCharInfo(char_info, core_data); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; - rb.Push(result); - rb.PushRaw<CharInfo>(char_info); + R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data)); } - void ConvertCharInfoToCoreData(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto char_info{rp.PopRaw<CharInfo>()}; - + Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, CharInfo& char_info) { LOG_INFO(Service_Mii, "called"); - CoreData core_data{}; - const auto result = manager->ConvertCharInfoToCoreData(core_data, char_info); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(CoreData) / sizeof(u32)}; - rb.Push(result); - rb.PushRaw<CoreData>(core_data); + R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info)); } - void Append(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto char_info{rp.PopRaw<CharInfo>()}; - + Result Append(CharInfo& char_info) { LOG_INFO(Service_Mii, "called"); - const auto result = manager->Append(metadata, char_info); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(manager->Append(metadata, char_info)); } std::shared_ptr<MiiManager> manager = nullptr; DatabaseSessionMetadata metadata{}; bool is_system{}; + + std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; }; -MiiDBModule::MiiDBModule(Core::System& system_, const char* name_, - std::shared_ptr<MiiManager> mii_manager, bool is_system_) +IStaticService::IStaticService(Core::System& system_, const char* name_, + std::shared_ptr<MiiManager> mii_manager, bool is_system_) : ServiceFramework{system_, name_}, manager{mii_manager}, is_system{is_system_} { // clang-format off static const FunctionInfo functions[] = { - {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, + {0, D<&IStaticService::GetDatabaseService>, "GetDatabaseService"}, }; // clang-format on RegisterHandlers(functions); - - if (manager == nullptr) { - manager = std::make_shared<MiiManager>(); - } } -MiiDBModule::~MiiDBModule() = default; - -void MiiDBModule::GetDatabaseService(HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IDatabaseService>(system, manager, is_system); +IStaticService::~IStaticService() = default; +Result IStaticService::GetDatabaseService( + Out<SharedPointer<IDatabaseService>> out_database_service) { LOG_DEBUG(Service_Mii, "called"); + + *out_database_service = std::make_shared<IDatabaseService>(system, manager, is_system); + + R_SUCCEED(); } -std::shared_ptr<MiiManager> MiiDBModule::GetMiiManager() { +std::shared_ptr<MiiManager> IStaticService::GetMiiManager() { return manager; } -class MiiImg final : public ServiceFramework<MiiImg> { +class IImageDatabaseService final : public ServiceFramework<IImageDatabaseService> { public: - explicit MiiImg(Core::System& system_) : ServiceFramework{system_, "miiimg"} { + explicit IImageDatabaseService(Core::System& system_) : ServiceFramework{system_, "miiimg"} { // clang-format off static const FunctionInfo functions[] = { - {0, &MiiImg::Initialize, "Initialize"}, + {0, D<&IImageDatabaseService::Initialize>, "Initialize"}, {10, nullptr, "Reload"}, - {11, &MiiImg::GetCount, "GetCount"}, + {11, D<&IImageDatabaseService::GetCount>, "GetCount"}, {12, nullptr, "IsEmpty"}, {13, nullptr, "IsFull"}, {14, nullptr, "GetAttribute"}, @@ -585,31 +341,30 @@ public: } private: - void Initialize(HLERequestContext& ctx) { + Result Initialize() { LOG_INFO(Service_Mii, "called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } - void GetCount(HLERequestContext& ctx) { + Result GetCount(Out<u32> out_count) { LOG_DEBUG(Service_Mii, "called"); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(0); + *out_count = 0; + + R_SUCCEED(); } }; void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - std::shared_ptr<MiiManager> manager = nullptr; + std::shared_ptr<MiiManager> manager = std::make_shared<MiiManager>(); server_manager->RegisterNamedService( - "mii:e", std::make_shared<MiiDBModule>(system, "mii:e", manager, true)); + "mii:e", std::make_shared<IStaticService>(system, "mii:e", manager, true)); server_manager->RegisterNamedService( - "mii:u", std::make_shared<MiiDBModule>(system, "mii:u", manager, false)); - server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system)); + "mii:u", std::make_shared<IStaticService>(system, "mii:u", manager, false)); + server_manager->RegisterNamedService("miiimg", std::make_shared<IImageDatabaseService>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/mii/mii.h b/src/core/hle/service/mii/mii.h index 9aa4426f6..8683ac1a5 100644 --- a/src/core/hle/service/mii/mii.h +++ b/src/core/hle/service/mii/mii.h @@ -3,7 +3,7 @@ #pragma once -#include "core/hle/service/service.h" +#include "core/hle/service/cmif_types.h" namespace Core { class System; @@ -11,19 +11,20 @@ class System; namespace Service::Mii { class MiiManager; +class IDatabaseService; -class MiiDBModule final : public ServiceFramework<MiiDBModule> { +class IStaticService final : public ServiceFramework<IStaticService> { public: - explicit MiiDBModule(Core::System& system_, const char* name_, - std::shared_ptr<MiiManager> mii_manager, bool is_system_); - ~MiiDBModule() override; + explicit IStaticService(Core::System& system_, const char* name_, + std::shared_ptr<MiiManager> mii_manager, bool is_system_); + ~IStaticService() override; std::shared_ptr<MiiManager> GetMiiManager(); private: - void GetDatabaseService(HLERequestContext& ctx); + Result GetDatabaseService(Out<SharedPointer<IDatabaseService>> out_database_service); - std::shared_ptr<MiiManager> manager = nullptr; + std::shared_ptr<MiiManager> manager{nullptr}; bool is_system{}; }; diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 1e2d2d212..28e3000bd 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -1405,7 +1405,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const { system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; - static_service->GetTimeZoneService(timezone_service); + static_service->GetTimeZoneService(&timezone_service); Service::PSC::Time::CalendarTime calendar_time{}; Service::PSC::Time::CalendarAdditionalInfo additional_info{}; @@ -1416,7 +1416,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const { amiibo_date.SetMonth(1); amiibo_date.SetDay(1); - if (timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time) == + if (timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time) == ResultSuccess) { amiibo_date.SetYear(calendar_time.year); amiibo_date.SetMonth(calendar_time.month); @@ -1431,10 +1431,10 @@ s64 NfcDevice::GetCurrentPosixTime() const { system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; - static_service->GetStandardSteadyClock(steady_clock); + static_service->GetStandardSteadyClock(&steady_clock); Service::PSC::Time::SteadyClockTimePoint time_point{}; - R_ASSERT(steady_clock->GetCurrentTimePoint(time_point)); + R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point)); return time_point.time_point; } diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp index b60699c45..94a8243b5 100644 --- a/src/core/hle/service/nfc/common/device_manager.cpp +++ b/src/core/hle/service/nfc/common/device_manager.cpp @@ -91,10 +91,10 @@ Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max true); std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; - static_service->GetStandardSteadyClock(steady_clock); + static_service->GetStandardSteadyClock(&steady_clock); Service::PSC::Time::SteadyClockTimePoint time_point{}; - R_ASSERT(steady_clock->GetCurrentTimePoint(time_point)); + R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point)); const s64 elapsed_time = time_point.time_point - time_since_last_error; if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) { @@ -754,10 +754,10 @@ Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device, system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; - static_service->GetStandardSteadyClock(steady_clock); + static_service->GetStandardSteadyClock(&steady_clock); Service::PSC::Time::SteadyClockTimePoint time_point{}; - R_ASSERT(steady_clock->GetCurrentTimePoint(time_point)); + R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point)); time_since_last_error = time_point.time_point; } diff --git a/src/core/hle/service/psc/time/common.h b/src/core/hle/service/psc/time/common.h index d17b31143..596828b8b 100644 --- a/src/core/hle/service/psc/time/common.h +++ b/src/core/hle/service/psc/time/common.h @@ -5,6 +5,7 @@ #include <array> #include <chrono> +#include <fmt/format.h> #include "common/common_types.h" #include "common/intrusive_list.h" @@ -21,8 +22,14 @@ class System; namespace Service::PSC::Time { using ClockSourceId = Common::UUID; +enum class TimeType : u8 { + UserSystemClock = 0, + NetworkSystemClock = 1, + LocalSystemClock = 2, +}; + struct SteadyClockTimePoint { - constexpr bool IdMatches(SteadyClockTimePoint& other) { + constexpr bool IdMatches(const SteadyClockTimePoint& other) const { return clock_source_id == other.clock_source_id; } bool operator==(const SteadyClockTimePoint& other) const = default; @@ -42,12 +49,6 @@ struct SystemClockContext { static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!"); static_assert(std::is_trivial_v<SystemClockContext>); -enum class TimeType : u8 { - UserSystemClock, - NetworkSystemClock, - LocalSystemClock, -}; - struct CalendarTime { s16 year; s8 month; @@ -67,14 +68,10 @@ struct CalendarAdditionalInfo { }; static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!"); -struct LocationName { - std::array<char, 36> name; -}; +using LocationName = std::array<char, 0x24>; static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!"); -struct RuleVersion { - std::array<char, 16> version; -}; +using RuleVersion = std::array<char, 0x10>; static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!"); struct ClockSnapshot { @@ -152,8 +149,8 @@ constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) { return std::chrono::nanoseconds(a + b); } -constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTimePoint& a, - SteadyClockTimePoint& b) { +constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, const SteadyClockTimePoint& a, + const SteadyClockTimePoint& b) { R_UNLESS(out_seconds, ResultInvalidArgument); R_UNLESS(a.IdMatches(b), ResultInvalidArgument); R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(), @@ -166,3 +163,111 @@ constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTi } } // namespace Service::PSC::Time + +template <> +struct fmt::formatter<Service::PSC::Time::TimeType> : fmt::formatter<fmt::string_view> { + template <typename FormatContext> + auto format(Service::PSC::Time::TimeType type, FormatContext& ctx) { + const string_view name = [type] { + using Service::PSC::Time::TimeType; + switch (type) { + case TimeType::UserSystemClock: + return "UserSystemClock"; + case TimeType::NetworkSystemClock: + return "NetworkSystemClock"; + case TimeType::LocalSystemClock: + return "LocalSystemClock"; + } + return "Invalid"; + }(); + return formatter<string_view>::format(name, ctx); + } +}; + +template <> +struct fmt::formatter<Service::PSC::Time::SteadyClockTimePoint> : fmt::formatter<fmt::string_view> { + template <typename FormatContext> + auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point, + FormatContext& ctx) const { + return fmt::format_to(ctx.out(), "time_point={}", time_point.time_point); + } +}; + +template <> +struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> { + template <typename FormatContext> + auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const { + return fmt::format_to(ctx.out(), "offset={} steady_time_point={}", context.offset, + context.steady_time_point.time_point); + } +}; + +template <> +struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> { + template <typename FormatContext> + auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const { + return fmt::format_to(ctx.out(), "{}/{}/{} {}:{}:{}", calendar.day, calendar.month, + calendar.year, calendar.hour, calendar.minute, calendar.second); + } +}; + +template <> +struct fmt::formatter<Service::PSC::Time::CalendarAdditionalInfo> + : fmt::formatter<fmt::string_view> { + template <typename FormatContext> + auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional, + FormatContext& ctx) const { + return fmt::format_to(ctx.out(), "weekday={} yearday={} name={} is_dst={} ut_offset={}", + additional.day_of_week, additional.day_of_year, + additional.name.data(), additional.is_dst, additional.ut_offset); + } +}; + +template <> +struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> { + template <typename FormatContext> + auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const { + std::string_view n{name.data(), name.size()}; + return formatter<string_view>::format(n, ctx); + } +}; + +template <> +struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> { + template <typename FormatContext> + auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const { + std::string_view v{version.data(), version.size()}; + return formatter<string_view>::format(v, ctx); + } +}; + +template <> +struct fmt::formatter<Service::PSC::Time::ClockSnapshot> : fmt::formatter<fmt::string_view> { + template <typename FormatContext> + auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const { + return fmt::format_to( + ctx.out(), + "user_context={} network_context={} user_time={} network_time={} user_calendar_time={} " + "network_calendar_time={} user_calendar_additional_time={} " + "network_calendar_additional_time={} steady_clock_time_point={} location={} " + "is_automatic_correction_enabled={} type={}", + snapshot.user_context, snapshot.network_context, snapshot.user_time, + snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time, + snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time, + snapshot.steady_clock_time_point, snapshot.location_name, + snapshot.is_automatic_correction_enabled, snapshot.type); + } +}; + +template <> +struct fmt::formatter<Service::PSC::Time::ContinuousAdjustmentTimePoint> + : fmt::formatter<fmt::string_view> { + template <typename FormatContext> + auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point, + FormatContext& ctx) const { + return fmt::format_to(ctx.out(), + "rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}", + time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount, + time_point.lower, time_point.upper); + } +};
\ No newline at end of file diff --git a/src/core/hle/service/psc/time/power_state_service.cpp b/src/core/hle/service/psc/time/power_state_service.cpp index b0ae71bf9..ab1d32c70 100644 --- a/src/core/hle/service/psc/time/power_state_service.cpp +++ b/src/core/hle/service/psc/time/power_state_service.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/psc/time/power_state_service.h" namespace Service::PSC::Time { @@ -11,39 +12,34 @@ IPowerStateRequestHandler::IPowerStateRequestHandler( power_state_request_manager} { // clang-format off static const FunctionInfo functions[] = { - {0, &IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle, "GetPowerStateRequestEventReadableHandle"}, - {1, &IPowerStateRequestHandler::GetAndClearPowerStateRequest, "GetAndClearPowerStateRequest"}, + {0, D<&IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle>, "GetPowerStateRequestEventReadableHandle"}, + {1, D<&IPowerStateRequestHandler::GetAndClearPowerStateRequest>, "GetAndClearPowerStateRequest"}, }; // clang-format on RegisterHandlers(functions); } -void IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx) { +Result IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle( + OutCopyHandle<Kernel::KReadableEvent> out_event) { LOG_DEBUG(Service_Time, "called."); - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(m_power_state_request_manager.GetReadableEvent()); + *out_event = &m_power_state_request_manager.GetReadableEvent(); + R_SUCCEED(); } -void IPowerStateRequestHandler::GetAndClearPowerStateRequest(HLERequestContext& ctx) { +Result IPowerStateRequestHandler::GetAndClearPowerStateRequest(Out<bool> out_cleared, + Out<u32> out_priority) { LOG_DEBUG(Service_Time, "called."); u32 priority{}; auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority); + *out_cleared = cleared; if (cleared) { - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(priority); - rb.Push(cleared); - return; + *out_priority = priority; } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(cleared); + R_SUCCEED(); } } // namespace Service::PSC::Time diff --git a/src/core/hle/service/psc/time/power_state_service.h b/src/core/hle/service/psc/time/power_state_service.h index 3ebfddb79..56e2c4b87 100644 --- a/src/core/hle/service/psc/time/power_state_service.h +++ b/src/core/hle/service/psc/time/power_state_service.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/service/cmif_types.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/psc/time/power_state_request_manager.h" #include "core/hle/service/server_manager.h" @@ -21,10 +22,10 @@ public: ~IPowerStateRequestHandler() override = default; -private: - void GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx); - void GetAndClearPowerStateRequest(HLERequestContext& ctx); + Result GetPowerStateRequestEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetAndClearPowerStateRequest(Out<bool> out_cleared, Out<u32> out_priority); +private: Core::System& m_system; PowerStateRequestManager& m_power_state_request_manager; }; diff --git a/src/core/hle/service/psc/time/service_manager.cpp b/src/core/hle/service/psc/time/service_manager.cpp index 60820aa9b..ec906b723 100644 --- a/src/core/hle/service/psc/time/service_manager.cpp +++ b/src/core/hle/service/psc/time/service_manager.cpp @@ -3,6 +3,7 @@ #include "core/core.h" #include "core/core_timing.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/psc/time/power_state_service.h" #include "core/hle/service/psc/time/service_manager.h" #include "core/hle/service/psc/time/static.h" @@ -25,24 +26,24 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage m_local_operation{m_system}, m_network_operation{m_system}, m_ephemeral_operation{m_system} { // clang-format off static const FunctionInfo functions[] = { - {0, &ServiceManager::Handle_GetStaticServiceAsUser, "GetStaticServiceAsUser"}, - {5, &ServiceManager::Handle_GetStaticServiceAsAdmin, "GetStaticServiceAsAdmin"}, - {6, &ServiceManager::Handle_GetStaticServiceAsRepair, "GetStaticServiceAsRepair"}, - {9, &ServiceManager::Handle_GetStaticServiceAsServiceManager, "GetStaticServiceAsServiceManager"}, - {10, &ServiceManager::Handle_SetupStandardSteadyClockCore, "SetupStandardSteadyClockCore"}, - {11, &ServiceManager::Handle_SetupStandardLocalSystemClockCore, "SetupStandardLocalSystemClockCore"}, - {12, &ServiceManager::Handle_SetupStandardNetworkSystemClockCore, "SetupStandardNetworkSystemClockCore"}, - {13, &ServiceManager::Handle_SetupStandardUserSystemClockCore, "SetupStandardUserSystemClockCore"}, - {14, &ServiceManager::Handle_SetupTimeZoneServiceCore, "SetupTimeZoneServiceCore"}, - {15, &ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore, "SetupEphemeralNetworkSystemClockCore"}, - {50, &ServiceManager::Handle_GetStandardLocalClockOperationEvent, "GetStandardLocalClockOperationEvent"}, - {51, &ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager, "GetStandardNetworkClockOperationEventForServiceManager"}, - {52, &ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager, "GetEphemeralNetworkClockOperationEventForServiceManager"}, - {60, &ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"}, - {100, &ServiceManager::Handle_SetStandardSteadyClockBaseTime, "SetStandardSteadyClockBaseTime"}, - {200, &ServiceManager::Handle_GetClosestAlarmUpdatedEvent, "GetClosestAlarmUpdatedEvent"}, - {201, &ServiceManager::Handle_CheckAndSignalAlarms, "CheckAndSignalAlarms"}, - {202, &ServiceManager::Handle_GetClosestAlarmInfo, "GetClosestAlarmInfo "}, + {0, D<&ServiceManager::GetStaticServiceAsUser>, "GetStaticServiceAsUser"}, + {5, D<&ServiceManager::GetStaticServiceAsAdmin>, "GetStaticServiceAsAdmin"}, + {6, D<&ServiceManager::GetStaticServiceAsRepair>, "GetStaticServiceAsRepair"}, + {9, D<&ServiceManager::GetStaticServiceAsServiceManager>, "GetStaticServiceAsServiceManager"}, + {10, D<&ServiceManager::SetupStandardSteadyClockCore>, "SetupStandardSteadyClockCore"}, + {11, D<&ServiceManager::SetupStandardLocalSystemClockCore>, "SetupStandardLocalSystemClockCore"}, + {12, D<&ServiceManager::SetupStandardNetworkSystemClockCore>, "SetupStandardNetworkSystemClockCore"}, + {13, D<&ServiceManager::SetupStandardUserSystemClockCore>, "SetupStandardUserSystemClockCore"}, + {14, D<&ServiceManager::SetupTimeZoneServiceCore>, "SetupTimeZoneServiceCore"}, + {15, D<&ServiceManager::SetupEphemeralNetworkSystemClockCore>, "SetupEphemeralNetworkSystemClockCore"}, + {50, D<&ServiceManager::GetStandardLocalClockOperationEvent>, "GetStandardLocalClockOperationEvent"}, + {51, D<&ServiceManager::GetStandardNetworkClockOperationEventForServiceManager>, "GetStandardNetworkClockOperationEventForServiceManager"}, + {52, D<&ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager>, "GetEphemeralNetworkClockOperationEventForServiceManager"}, + {60, D<&ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"}, + {100, D<&ServiceManager::SetStandardSteadyClockBaseTime>, "SetStandardSteadyClockBaseTime"}, + {200, D<&ServiceManager::GetClosestAlarmUpdatedEvent>, "GetClosestAlarmUpdatedEvent"}, + {201, D<&ServiceManager::CheckAndSignalAlarms>, "CheckAndSignalAlarms"}, + {202, D<&ServiceManager::GetClosestAlarmInfo>, "GetClosestAlarmInfo "}, }; // clang-format on RegisterHandlers(functions); @@ -52,302 +53,39 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage m_ephemeral_system_context_writer.Link(m_ephemeral_operation); } -void ServiceManager::SetupSAndP() { - if (!m_is_s_and_p_setup) { - m_is_s_and_p_setup = true; - m_server_manager.RegisterNamedService( - "time:s", std::make_shared<StaticService>( - m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s")); - m_server_manager.RegisterNamedService("time:p", - std::make_shared<IPowerStateRequestHandler>( - m_system, m_time->m_power_state_request_manager)); - } -} - -void ServiceManager::CheckAndSetupServicesSAndP() { - if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() && - m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() && - m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) { - SetupSAndP(); - } -} - -void ServiceManager::Handle_GetStaticServiceAsUser(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<StaticService> service{}; - auto res = GetStaticServiceAsUser(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<StaticService>(std::move(service)); -} - -void ServiceManager::Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<StaticService> service{}; - auto res = GetStaticServiceAsAdmin(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<StaticService>(std::move(service)); -} - -void ServiceManager::Handle_GetStaticServiceAsRepair(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<StaticService> service{}; - auto res = GetStaticServiceAsRepair(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<StaticService>(std::move(service)); -} - -void ServiceManager::Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<StaticService> service{}; - auto res = GetStaticServiceAsServiceManager(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<StaticService>(std::move(service)); -} - -void ServiceManager::Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - struct Parameters { - bool reset_detected; - Common::UUID clock_source_id; - s64 rtc_offset; - s64 internal_offset; - s64 test_offset; - }; - static_assert(sizeof(Parameters) == 0x30); - - IPC::RequestParser rp{ctx}; - auto params{rp.PopRaw<Parameters>()}; - - auto res = SetupStandardSteadyClockCore(params.clock_source_id, params.rtc_offset, - params.internal_offset, params.test_offset, - params.reset_detected); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void ServiceManager::Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto context{rp.PopRaw<SystemClockContext>()}; - auto time{rp.Pop<s64>()}; - - auto res = SetupStandardLocalSystemClockCore(context, time); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void ServiceManager::Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto context{rp.PopRaw<SystemClockContext>()}; - auto accuracy{rp.Pop<s64>()}; - - auto res = SetupStandardNetworkSystemClockCore(context, accuracy); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void ServiceManager::Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - struct Parameters { - bool automatic_correction; - SteadyClockTimePoint time_point; - }; - static_assert(sizeof(Parameters) == 0x20); - - IPC::RequestParser rp{ctx}; - auto params{rp.PopRaw<Parameters>()}; - - auto res = SetupStandardUserSystemClockCore(params.time_point, params.automatic_correction); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void ServiceManager::Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - struct Parameters { - u32 location_count; - LocationName name; - SteadyClockTimePoint time_point; - RuleVersion rule_version; - }; - static_assert(sizeof(Parameters) == 0x50); - - IPC::RequestParser rp{ctx}; - auto params{rp.PopRaw<Parameters>()}; - - auto rule_buffer{ctx.ReadBuffer()}; - - auto res = SetupTimeZoneServiceCore(params.name, params.time_point, params.rule_version, - params.location_count, rule_buffer); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - auto res = SetupEphemeralNetworkSystemClockCore(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void ServiceManager::Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Kernel::KEvent* event{}; - auto res = GetStandardLocalClockOperationEvent(&event); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(res); - rb.PushCopyObjects(event->GetReadableEvent()); -} - -void ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager( - HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Kernel::KEvent* event{}; - auto res = GetStandardNetworkClockOperationEventForServiceManager(&event); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(res); - rb.PushCopyObjects(event); -} - -void ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager( - HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Kernel::KEvent* event{}; - auto res = GetEphemeralNetworkClockOperationEventForServiceManager(&event); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(res); - rb.PushCopyObjects(event); -} - -void ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent( - HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Kernel::KEvent* event{}; - auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(&event); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(res); - rb.PushCopyObjects(event); -} - -void ServiceManager::Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx) { +Result ServiceManager::GetStaticServiceAsUser(OutInterface<StaticService> out_service) { LOG_DEBUG(Service_Time, "called."); - IPC::RequestParser rp{ctx}; - auto base_time{rp.Pop<s64>()}; - - auto res = SetStandardSteadyClockBaseTime(base_time); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u")); } -void ServiceManager::Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx) { +Result ServiceManager::GetStaticServiceAsAdmin(OutInterface<StaticService> out_service) { LOG_DEBUG(Service_Time, "called."); - Kernel::KEvent* event{}; - auto res = GetClosestAlarmUpdatedEvent(&event); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.PushCopyObjects(event->GetReadableEvent()); + R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a")); } -void ServiceManager::Handle_CheckAndSignalAlarms(HLERequestContext& ctx) { +Result ServiceManager::GetStaticServiceAsRepair(OutInterface<StaticService> out_service) { LOG_DEBUG(Service_Time, "called."); - auto res = CheckAndSignalAlarms(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r")); } -void ServiceManager::Handle_GetClosestAlarmInfo(HLERequestContext& ctx) { +Result ServiceManager::GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service) { LOG_DEBUG(Service_Time, "called."); - AlarmInfo alarm_info{}; - bool is_valid{}; - s64 time{}; - auto res = GetClosestAlarmInfo(is_valid, alarm_info, time); - - struct OutParameters { - bool is_valid; - AlarmInfo alarm_info; - s64 time; - }; - static_assert(sizeof(OutParameters) == 0x20); - - OutParameters out_params{ - .is_valid = is_valid, - .alarm_info = alarm_info, - .time = time, - }; - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(OutParameters) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<OutParameters>(out_params); -} - -// =============================== Implementations =========================== - -Result ServiceManager::GetStaticService(std::shared_ptr<StaticService>& out_service, - StaticServiceSetupInfo setup_info, const char* name) { - out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name); - R_SUCCEED(); -} - -Result ServiceManager::GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service) { - R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u")); -} - -Result ServiceManager::GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service) { - R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a")); -} - -Result ServiceManager::GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service) { - R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r")); -} - -Result ServiceManager::GetStaticServiceAsServiceManager( - std::shared_ptr<StaticService>& out_service) { R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm")); } -Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset, - s64 internal_offset, s64 test_offset, - bool is_rtc_reset_detected) { +Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected, + Common::UUID& clock_source_id, s64 rtc_offset, + s64 internal_offset, s64 test_offset) { + LOG_DEBUG(Service_Time, + "called. is_rtc_reset_detected={} clock_source_id={} rtc_offset={} " + "internal_offset={} test_offset={}", + is_rtc_reset_detected, clock_source_id.RawString(), rtc_offset, internal_offset, + test_offset); + m_steady_clock.Initialize(clock_source_id, rtc_offset, internal_offset, test_offset, is_rtc_reset_detected); auto time = m_steady_clock.GetRawTime(); @@ -365,6 +103,10 @@ Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_i } Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) { + LOG_DEBUG(Service_Time, + "called. context={} context.steady_time_point.clock_source_id={} time={}", context, + context.steady_time_point.clock_source_id.RawString(), time); + m_local_system_clock.SetContextWriter(m_local_system_context_writer); m_local_system_clock.Initialize(context, time); @@ -374,6 +116,9 @@ Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& con Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy) { + LOG_DEBUG(Service_Time, "called. context={} steady_time_point.clock_source_id={} accuracy={}", + context, context.steady_time_point.clock_source_id.RawString(), accuracy); + // TODO this is a hack! The network clock should be updated independently, from the ntc service // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot // to avoid it being stuck at 0. @@ -388,8 +133,11 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c R_SUCCEED(); } -Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point, - bool automatic_correction) { +Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correction, + SteadyClockTimePoint& time_point) { + LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}", + automatic_correction, time_point, time_point.clock_source_id.RawString()); + // TODO this is a hack! The user clock should be updated independently, from the ntc service // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot // to avoid it being stuck at 0. @@ -406,10 +154,16 @@ Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& ti R_SUCCEED(); } -Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, +Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version, + u32 location_count, SteadyClockTimePoint& time_point, - RuleVersion& rule_version, u32 location_count, - std::span<const u8> rule_buffer) { + InBuffer<BufferAttr_HipcAutoSelect> rule_buffer) { + LOG_DEBUG(Service_Time, + "called. name={} rule_version={} location_count={} time_point={} " + "clock_source_id={}", + name, rule_version, location_count, time_point, + time_point.clock_source_id.RawString()); + if (m_time_zone.ParseBinary(name, rule_buffer) != ResultSuccess) { LOG_ERROR(Service_Time, "Failed to parse time zone binary!"); } @@ -424,6 +178,8 @@ Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, } Result ServiceManager::SetupEphemeralNetworkSystemClockCore() { + LOG_DEBUG(Service_Time, "called."); + m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer); m_ephemeral_network_clock.SetInitialized(); @@ -431,30 +187,41 @@ Result ServiceManager::SetupEphemeralNetworkSystemClockCore() { R_SUCCEED(); } -Result ServiceManager::GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event) { - *out_event = m_local_operation.m_event; +Result ServiceManager::GetStandardLocalClockOperationEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_Time, "called."); + + *out_event = &m_local_operation.m_event->GetReadableEvent(); R_SUCCEED(); } Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager( - Kernel::KEvent** out_event) { - *out_event = m_network_operation.m_event; + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_Time, "called."); + + *out_event = &m_network_operation.m_event->GetReadableEvent(); R_SUCCEED(); } Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager( - Kernel::KEvent** out_event) { - *out_event = m_ephemeral_operation.m_event; + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_Time, "called."); + + *out_event = &m_ephemeral_operation.m_event->GetReadableEvent(); R_SUCCEED(); } Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent( - Kernel::KEvent** out_event) { - *out_event = &m_user_system_clock.GetEvent(); + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_Time, "called."); + + *out_event = &m_user_system_clock.GetEvent().GetReadableEvent(); R_SUCCEED(); } Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) { + LOG_DEBUG(Service_Time, "called. base_time={}", base_time); + m_steady_clock.SetRtcOffset(base_time); auto time = m_steady_clock.GetRawTime(); auto ticks = m_system.CoreTiming().GetClockTicks(); @@ -468,26 +235,63 @@ Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) { R_SUCCEED(); } -Result ServiceManager::GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event) { - *out_event = &m_alarms.GetEvent(); +Result ServiceManager::GetClosestAlarmUpdatedEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_Time, "called."); + + *out_event = &m_alarms.GetEvent().GetReadableEvent(); R_SUCCEED(); } Result ServiceManager::CheckAndSignalAlarms() { + LOG_DEBUG(Service_Time, "called."); + m_alarms.CheckAndSignal(); R_SUCCEED(); } -Result ServiceManager::GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time) { +Result ServiceManager::GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, + Out<s64> out_time) { Alarm* alarm{nullptr}; - out_is_valid = m_alarms.GetClosestAlarm(&alarm); - if (out_is_valid) { - out_info = { + *out_is_valid = m_alarms.GetClosestAlarm(&alarm); + if (*out_is_valid) { + *out_info = { .alert_time = alarm->GetAlertTime(), .priority = alarm->GetPriority(), }; - out_time = m_alarms.GetRawTime(); + *out_time = m_alarms.GetRawTime(); + } + + LOG_DEBUG(Service_Time, + "called. out_is_valid={} out_info.alert_time={} out_info.priority={}, out_time={}", + *out_is_valid, out_info->alert_time, out_info->priority, *out_time); + + R_SUCCEED(); +} + +void ServiceManager::CheckAndSetupServicesSAndP() { + if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() && + m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() && + m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) { + SetupSAndP(); + } +} + +void ServiceManager::SetupSAndP() { + if (!m_is_s_and_p_setup) { + m_is_s_and_p_setup = true; + m_server_manager.RegisterNamedService( + "time:s", std::make_shared<StaticService>( + m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s")); + m_server_manager.RegisterNamedService("time:p", + std::make_shared<IPowerStateRequestHandler>( + m_system, m_time->m_power_state_request_manager)); } +} + +Result ServiceManager::GetStaticService(OutInterface<StaticService> out_service, + StaticServiceSetupInfo setup_info, const char* name) { + *out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name); R_SUCCEED(); } diff --git a/src/core/hle/service/psc/time/service_manager.h b/src/core/hle/service/psc/time/service_manager.h index 1d9952317..25d361d4f 100644 --- a/src/core/hle/service/psc/time/service_manager.h +++ b/src/core/hle/service/psc/time/service_manager.h @@ -6,6 +6,7 @@ #include <list> #include <memory> +#include "core/hle/service/cmif_types.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/manager.h" @@ -29,55 +30,38 @@ public: ServerManager* server_manager); ~ServiceManager() override = default; - Result GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service); - Result GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service); - Result GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service); - Result GetStaticServiceAsServiceManager(std::shared_ptr<StaticService>& out_service); - Result SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset, - s64 internal_offset, s64 test_offset, - bool is_rtc_reset_detected); + Result GetStaticServiceAsUser(OutInterface<StaticService> out_service); + Result GetStaticServiceAsAdmin(OutInterface<StaticService> out_service); + Result GetStaticServiceAsRepair(OutInterface<StaticService> out_service); + Result GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service); + Result SetupStandardSteadyClockCore(bool is_rtc_reset_detected, Common::UUID& clock_source_id, + s64 rtc_offset, s64 internal_offset, s64 test_offset); Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time); Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy); - Result SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point, - bool automatic_correction); - Result SetupTimeZoneServiceCore(LocationName& name, SteadyClockTimePoint& time_point, - RuleVersion& rule_version, u32 location_count, - std::span<const u8> rule_buffer); + Result SetupStandardUserSystemClockCore(bool automatic_correction, + SteadyClockTimePoint& time_point); + Result SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version, + u32 location_count, SteadyClockTimePoint& time_point, + InBuffer<BufferAttr_HipcAutoSelect> rule_buffer); Result SetupEphemeralNetworkSystemClockCore(); - Result GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event); - Result GetStandardNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event); - Result GetEphemeralNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event); - Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(Kernel::KEvent** out_event); + Result GetStandardLocalClockOperationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetStandardNetworkClockOperationEventForServiceManager( + OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetEphemeralNetworkClockOperationEventForServiceManager( + OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event); Result SetStandardSteadyClockBaseTime(s64 base_time); - Result GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event); + Result GetClosestAlarmUpdatedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result CheckAndSignalAlarms(); - Result GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time); + Result GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, Out<s64> out_time); private: void CheckAndSetupServicesSAndP(); void SetupSAndP(); - Result GetStaticService(std::shared_ptr<StaticService>& out_service, + Result GetStaticService(OutInterface<StaticService> out_service, StaticServiceSetupInfo setup_info, const char* name); - void Handle_GetStaticServiceAsUser(HLERequestContext& ctx); - void Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx); - void Handle_GetStaticServiceAsRepair(HLERequestContext& ctx); - void Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx); - void Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx); - void Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx); - void Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx); - void Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx); - void Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx); - void Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx); - void Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx); - void Handle_GetStandardNetworkClockOperationEventForServiceManager(HLERequestContext& ctx); - void Handle_GetEphemeralNetworkClockOperationEventForServiceManager(HLERequestContext& ctx); - void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(HLERequestContext& ctx); - void Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx); - void Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx); - void Handle_CheckAndSignalAlarms(HLERequestContext& ctx); - void Handle_GetClosestAlarmInfo(HLERequestContext& ctx); - Core::System& m_system; std::shared_ptr<TimeManager> m_time; ServerManager& m_server_manager; diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp index 6f8cf3f88..3ca3311af 100644 --- a/src/core/hle/service/psc/time/static.cpp +++ b/src/core/hle/service/psc/time/static.cpp @@ -1,9 +1,11 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/scope_exit.h" #include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/k_shared_memory.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/psc/time/clocks/ephemeral_network_system_clock_core.h" #include "core/hle/service/psc/time/clocks/standard_local_system_clock_core.h" #include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h" @@ -39,358 +41,122 @@ StaticService::StaticService(Core::System& system_, StaticServiceSetupInfo setup m_time->m_shared_memory} { // clang-format off static const FunctionInfo functions[] = { - {0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"}, - {1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, - {2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"}, - {3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"}, - {4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, - {5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"}, - {20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, - {50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"}, - {51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"}, - {100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, - {101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, - {102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"}, - {200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"}, - {201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, - {300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"}, - {400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"}, - {401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"}, - {500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"}, - {501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"}, + {0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"}, + {1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"}, + {2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"}, + {3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"}, + {4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"}, + {5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"}, + {20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"}, + {50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"}, + {51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"}, + {100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, + {101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, + {102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"}, + {200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"}, + {201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, + {300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"}, + {400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"}, + {401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"}, + {500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"}, + {501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"}, }; // clang-format on RegisterHandlers(functions); } -Result StaticService::GetClockSnapshotImpl(ClockSnapshot& out_snapshot, - SystemClockContext& user_context, - SystemClockContext& network_context, TimeType type) { - out_snapshot.user_context = user_context; - out_snapshot.network_context = network_context; - - R_TRY( - m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot.steady_clock_time_point)); - - out_snapshot.is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection(); - - R_TRY(m_time_zone.GetLocationName(out_snapshot.location_name)); - - R_TRY(GetTimeFromTimePointAndContext( - &out_snapshot.user_time, out_snapshot.steady_clock_time_point, out_snapshot.user_context)); - - R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.user_calendar_time, - out_snapshot.user_calendar_additional_time, - out_snapshot.user_time)); - - if (GetTimeFromTimePointAndContext(&out_snapshot.network_time, - out_snapshot.steady_clock_time_point, - out_snapshot.network_context) != ResultSuccess) { - out_snapshot.network_time = 0; - } - - R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.network_calendar_time, - out_snapshot.network_calendar_additional_time, - out_snapshot.network_time)); - out_snapshot.type = type; - out_snapshot.unk_CE = 0; - R_SUCCEED(); -} - -void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<SystemClock> service{}; - auto res = GetStandardUserSystemClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<SystemClock>(std::move(service)); -} - -void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) { +Result StaticService::GetStandardUserSystemClock(OutInterface<SystemClock> out_service) { LOG_DEBUG(Service_Time, "called."); - std::shared_ptr<SystemClock> service{}; - auto res = GetStandardNetworkSystemClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<SystemClock>(std::move(service)); -} - -void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<SteadyClock> service{}; - auto res = GetStandardSteadyClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface(std::move(service)); -} - -void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<TimeZoneService> service{}; - auto res = GetTimeZoneService(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface(std::move(service)); -} - -void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<SystemClock> service{}; - auto res = GetStandardLocalSystemClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<SystemClock>(std::move(service)); -} - -void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - std::shared_ptr<SystemClock> service{}; - auto res = GetEphemeralNetworkSystemClock(service); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface<SystemClock>(std::move(service)); -} - -void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Kernel::KSharedMemory* shared_memory{}; - auto res = GetSharedMemoryNativeHandle(&shared_memory); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(res); - rb.PushCopyObjects(shared_memory); -} - -void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(m_setup_info.can_write_steady_clock ? ResultNotImplemented : ResultPermissionDenied); -} - -void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotImplemented); -} - -void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled( - HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - bool is_enabled{}; - auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push<bool>(is_enabled); -} - -void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled( - HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto automatic_correction{rp.Pop<bool>()}; - - auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotImplemented); -} - -void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - bool is_sufficient{}; - auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push<bool>(is_sufficient); + *out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock, + m_setup_info.can_write_user_clock, + m_setup_info.can_write_uninitialized_clock); + R_SUCCEED(); } -void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( - HLERequestContext& ctx) { +Result StaticService::GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service) { LOG_DEBUG(Service_Time, "called."); - SteadyClockTimePoint time_point{}; - auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<SteadyClockTimePoint>(time_point); + *out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock, + m_setup_info.can_write_network_clock, + m_setup_info.can_write_uninitialized_clock); + R_SUCCEED(); } -void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) { +Result StaticService::GetStandardSteadyClock(OutInterface<SteadyClock> out_service) { LOG_DEBUG(Service_Time, "called."); - IPC::RequestParser rp{ctx}; - auto context{rp.PopRaw<SystemClockContext>()}; - - s64 time{}; - auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push<s64>(time); + *out_service = + std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock, + m_setup_info.can_write_uninitialized_clock); + R_SUCCEED(); } -void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) { +Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) { LOG_DEBUG(Service_Time, "called."); - IPC::RequestParser rp{ctx}; - auto type{rp.PopEnum<TimeType>()}; - - ClockSnapshot snapshot{}; - auto res = GetClockSnapshot(snapshot, type); - - ctx.WriteBuffer(snapshot); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + *out_service = + std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone, + m_setup_info.can_write_timezone_device_location); + R_SUCCEED(); } -void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) { +Result StaticService::GetStandardLocalSystemClock(OutInterface<SystemClock> out_service) { LOG_DEBUG(Service_Time, "called."); - IPC::RequestParser rp{ctx}; - auto clock_type{rp.PopEnum<TimeType>()}; - [[maybe_unused]] auto alignment{rp.Pop<u32>()}; - auto user_context{rp.PopRaw<SystemClockContext>()}; - auto network_context{rp.PopRaw<SystemClockContext>()}; - - ClockSnapshot snapshot{}; - auto res = - GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type); - - ctx.WriteBuffer(snapshot); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + *out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock, + m_setup_info.can_write_local_clock, + m_setup_info.can_write_uninitialized_clock); + R_SUCCEED(); } -void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser( - HLERequestContext& ctx) { +Result StaticService::GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service) { LOG_DEBUG(Service_Time, "called."); - ClockSnapshot a{}; - ClockSnapshot b{}; - - auto a_buffer{ctx.ReadBuffer(0)}; - auto b_buffer{ctx.ReadBuffer(1)}; - - std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot)); - std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot)); - - s64 difference{}; - auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push(difference); + *out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock, + m_setup_info.can_write_network_clock, + m_setup_info.can_write_uninitialized_clock); + R_SUCCEED(); } -void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) { +Result StaticService::GetSharedMemoryNativeHandle( + OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) { LOG_DEBUG(Service_Time, "called."); - ClockSnapshot a{}; - ClockSnapshot b{}; - - auto a_buffer{ctx.ReadBuffer(0)}; - auto b_buffer{ctx.ReadBuffer(1)}; - - std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot)); - std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot)); - - s64 time{}; - auto res = CalculateSpanBetween(time, a, b); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push(time); -} - -// =============================== Implementations =========================== - -Result StaticService::GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service) { - out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock, - m_setup_info.can_write_user_clock, - m_setup_info.can_write_uninitialized_clock); + *out_shared_memory = &m_shared_memory.GetKSharedMemory(); R_SUCCEED(); } -Result StaticService::GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) { - out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock, - m_setup_info.can_write_network_clock, - m_setup_info.can_write_uninitialized_clock); - R_SUCCEED(); -} +Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { + LOG_DEBUG(Service_Time, "called. This function is not implemented!"); -Result StaticService::GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service) { - out_service = - std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock, - m_setup_info.can_write_uninitialized_clock); - R_SUCCEED(); -} + R_UNLESS(m_setup_info.can_write_steady_clock, ResultPermissionDenied); -Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) { - out_service = - std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone, - m_setup_info.can_write_timezone_device_location); - R_SUCCEED(); + R_RETURN(ResultNotImplemented); } -Result StaticService::GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service) { - out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock, - m_setup_info.can_write_local_clock, - m_setup_info.can_write_uninitialized_clock); - R_SUCCEED(); -} +Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) { + LOG_DEBUG(Service_Time, "called. This function is not implemented!"); -Result StaticService::GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) { - out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock, - m_setup_info.can_write_network_clock, - m_setup_info.can_write_uninitialized_clock); - R_SUCCEED(); + R_RETURN(ResultNotImplemented); } -Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) { - *out_shared_memory = &m_shared_memory.GetKSharedMemory(); - R_SUCCEED(); -} +Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled( + Out<bool> out_is_enabled) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); }); -Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled) { R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); - out_is_enabled = m_user_system_clock.GetAutomaticCorrection(); + *out_is_enabled = m_user_system_clock.GetAutomaticCorrection(); + R_SUCCEED(); } Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( bool automatic_correction) { + LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction); + R_UNLESS(m_user_system_clock.IsInitialized() && m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized); R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied); @@ -407,22 +173,35 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( R_SUCCEED(); } -Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) { - out_is_sufficient = m_network_system_clock.IsAccuracySufficient(); +Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { + LOG_DEBUG(Service_Time, "called. This function is not implemented!"); + + R_RETURN(ResultNotImplemented); +} + +Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); }); + + *out_is_sufficient = m_network_system_clock.IsAccuracySufficient(); + R_SUCCEED(); } Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( - SteadyClockTimePoint& out_time_point) { + Out<SteadyClockTimePoint> out_time_point) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); + R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); - m_user_system_clock.GetTimePoint(out_time_point); + m_user_system_clock.GetTimePoint(*out_time_point); R_SUCCEED(); } -Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, +Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time, SystemClockContext& context) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); + R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized); SteadyClockTimePoint time_point{}; @@ -433,12 +212,16 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, auto one_second_ns{ std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()}; auto ticks{m_system.CoreTiming().GetClockTicks()}; - auto current_time{ConvertToTimeSpan(ticks).count()}; - out_time = ((context.offset + time_point.time_point) - (current_time / one_second_ns)); + auto current_time_ns{ConvertToTimeSpan(ticks).count()}; + *out_time = ((context.offset + time_point.time_point) - (current_time_ns / one_second_ns)); + R_SUCCEED(); } -Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type) { +Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) { + SCOPE_EXIT( + { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); }); + SystemClockContext user_context{}; R_TRY(m_user_system_clock.GetContext(user_context)); @@ -448,53 +231,101 @@ Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType typ R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); } -Result StaticService::GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot, +Result StaticService::GetClockSnapshotFromSystemClockContext(TimeType type, + OutClockSnapshot out_snapshot, SystemClockContext& user_context, - SystemClockContext& network_context, - TimeType type) { + SystemClockContext& network_context) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, + "called. type={} user_context={} network_context={} out_snapshot={}", type, + user_context, network_context, *out_snapshot); + }); + R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); } -Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, - ClockSnapshot& a, - ClockSnapshot& b) { +Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, + InClockSnapshot a, + InClockSnapshot b) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference); + }); + auto diff_s = - std::chrono::seconds(b.user_context.offset) - std::chrono::seconds(a.user_context.offset); + std::chrono::seconds(b->user_context.offset) - std::chrono::seconds(a->user_context.offset); - if (a.user_context == b.user_context || - !a.user_context.steady_time_point.IdMatches(b.user_context.steady_time_point)) { - out_time = 0; + if (a->user_context == b->user_context || + !a->user_context.steady_time_point.IdMatches(b->user_context.steady_time_point)) { + *out_difference = 0; R_SUCCEED(); } - if (!a.is_automatic_correction_enabled || !b.is_automatic_correction_enabled) { - out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); + if (!a->is_automatic_correction_enabled || !b->is_automatic_correction_enabled) { + *out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); R_SUCCEED(); } - if (a.network_context.steady_time_point.IdMatches(a.steady_clock_time_point) || - b.network_context.steady_time_point.IdMatches(b.steady_clock_time_point)) { - out_time = 0; + if (a->network_context.steady_time_point.IdMatches(a->steady_clock_time_point) || + b->network_context.steady_time_point.IdMatches(b->steady_clock_time_point)) { + *out_difference = 0; R_SUCCEED(); } - out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); + *out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); R_SUCCEED(); } -Result StaticService::CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b) { +Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, + InClockSnapshot b) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); + s64 time_s{}; auto res = - GetSpanBetweenTimePoints(&time_s, a.steady_clock_time_point, b.steady_clock_time_point); + GetSpanBetweenTimePoints(&time_s, a->steady_clock_time_point, b->steady_clock_time_point); if (res != ResultSuccess) { - R_UNLESS(a.network_time != 0 && b.network_time != 0, ResultTimeNotFound); - time_s = b.network_time - a.network_time; + R_UNLESS(a->network_time != 0 && b->network_time != 0, ResultTimeNotFound); + time_s = b->network_time - a->network_time; } - out_time = + *out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(time_s)).count(); R_SUCCEED(); } +Result StaticService::GetClockSnapshotImpl(OutClockSnapshot out_snapshot, + SystemClockContext& user_context, + SystemClockContext& network_context, TimeType type) { + out_snapshot->user_context = user_context; + out_snapshot->network_context = network_context; + + R_TRY( + m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot->steady_clock_time_point)); + + out_snapshot->is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection(); + + R_TRY(m_time_zone.GetLocationName(out_snapshot->location_name)); + + R_TRY(GetTimeFromTimePointAndContext(&out_snapshot->user_time, + out_snapshot->steady_clock_time_point, + out_snapshot->user_context)); + + R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->user_calendar_time, + out_snapshot->user_calendar_additional_time, + out_snapshot->user_time)); + + if (GetTimeFromTimePointAndContext(&out_snapshot->network_time, + out_snapshot->steady_clock_time_point, + out_snapshot->network_context) != ResultSuccess) { + out_snapshot->network_time = 0; + } + + R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->network_calendar_time, + out_snapshot->network_calendar_additional_time, + out_snapshot->network_time)); + out_snapshot->type = type; + out_snapshot->unk_CE = 0; + R_SUCCEED(); +} + } // namespace Service::PSC::Time diff --git a/src/core/hle/service/psc/time/static.h b/src/core/hle/service/psc/time/static.h index 498cd5ab5..120bab259 100644 --- a/src/core/hle/service/psc/time/static.h +++ b/src/core/hle/service/psc/time/static.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/service/cmif_types.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/psc/time/common.h" #include "core/hle/service/server_manager.h" @@ -29,58 +30,44 @@ class EphemeralNetworkSystemClockCore; class SharedMemory; class StaticService final : public ServiceFramework<StaticService> { + using InClockSnapshot = InLargeData<ClockSnapshot, BufferAttr_HipcPointer>; + using OutClockSnapshot = OutLargeData<ClockSnapshot, BufferAttr_HipcPointer>; + public: explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info, std::shared_ptr<TimeManager> time, const char* name); ~StaticService() override = default; - Result GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service); - Result GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service); - Result GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service); - Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service); - Result GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service); - Result GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service); - Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory); - Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled); + Result GetStandardUserSystemClock(OutInterface<SystemClock> out_service); + Result GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service); + Result GetStandardSteadyClock(OutInterface<SteadyClock> out_service); + Result GetTimeZoneService(OutInterface<TimeZoneService> out_service); + Result GetStandardLocalSystemClock(OutInterface<SystemClock> out_service); + Result GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service); + Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory); + Result SetStandardSteadyClockInternalOffset(s64 offset_ns); + Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value); + Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled); Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); - Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient); + Result GetStandardUserSystemClockInitialYear(Out<s32> out_year); + Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient); Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( - SteadyClockTimePoint& out_time_point); - Result CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, SystemClockContext& context); - Result GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type); - Result GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot, + Out<SteadyClockTimePoint> out_time_point); + Result CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time, + SystemClockContext& context); + Result GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type); + Result GetClockSnapshotFromSystemClockContext(TimeType type, OutClockSnapshot out_snapshot, SystemClockContext& user_context, - SystemClockContext& network_context, - TimeType type); - Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, ClockSnapshot& a, - ClockSnapshot& b); - Result CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b); + SystemClockContext& network_context); + Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, + InClockSnapshot a, InClockSnapshot b); + Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b); private: - Result GetClockSnapshotImpl(ClockSnapshot& out_snapshot, SystemClockContext& user_context, + Result GetClockSnapshotImpl(OutClockSnapshot out_snapshot, SystemClockContext& user_context, SystemClockContext& network_context, TimeType type); - void Handle_GetStandardUserSystemClock(HLERequestContext& ctx); - void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx); - void Handle_GetStandardSteadyClock(HLERequestContext& ctx); - void Handle_GetTimeZoneService(HLERequestContext& ctx); - void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx); - void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx); - void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx); - void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx); - void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx); - void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); - void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); - void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx); - void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx); - void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); - void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx); - void Handle_GetClockSnapshot(HLERequestContext& ctx); - void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx); - void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx); - void Handle_CalculateSpanBetween(HLERequestContext& ctx); - Core::System& m_system; StaticServiceSetupInfo m_setup_info; std::shared_ptr<TimeManager> m_time; diff --git a/src/core/hle/service/psc/time/steady_clock.cpp b/src/core/hle/service/psc/time/steady_clock.cpp index 1ed5c7679..948610a2b 100644 --- a/src/core/hle/service/psc/time/steady_clock.cpp +++ b/src/core/hle/service/psc/time/steady_clock.cpp @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/scope_exit.h" #include "core/core.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/psc/time/steady_clock.h" namespace Service::PSC::Time { @@ -14,114 +16,40 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man can_write_uninitialized_clock} { // clang-format off static const FunctionInfo functions[] = { - {0, &SteadyClock::Handle_GetCurrentTimePoint, "GetCurrentTimePoint"}, - {2, &SteadyClock::Handle_GetTestOffset, "GetTestOffset"}, - {3, &SteadyClock::Handle_SetTestOffset, "SetTestOffset"}, - {100, &SteadyClock::Handle_GetRtcValue, "GetRtcValue"}, - {101, &SteadyClock::Handle_IsRtcResetDetected, "IsRtcResetDetected"}, - {102, &SteadyClock::Handle_GetSetupResultValue, "GetSetupResultValue"}, - {200, &SteadyClock::Handle_GetInternalOffset, "GetInternalOffset"}, + {0, D<&SteadyClock::GetCurrentTimePoint>, "GetCurrentTimePoint"}, + {2, D<&SteadyClock::GetTestOffset>, "GetTestOffset"}, + {3, D<&SteadyClock::SetTestOffset>, "SetTestOffset"}, + {100, D<&SteadyClock::GetRtcValue>, "GetRtcValue"}, + {101, D<&SteadyClock::IsRtcResetDetected>, "IsRtcResetDetected"}, + {102, D<&SteadyClock::GetSetupResultValue>, "GetSetupResultValue"}, + {200, D<&SteadyClock::GetInternalOffset>, "GetInternalOffset"}, }; // clang-format on RegisterHandlers(functions); } -void SteadyClock::Handle_GetCurrentTimePoint(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); +Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); - SteadyClockTimePoint time_point{}; - auto res = GetCurrentTimePoint(time_point); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<SteadyClockTimePoint>(time_point); -} - -void SteadyClock::Handle_GetTestOffset(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - s64 test_offset{}; - auto res = GetTestOffset(test_offset); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push(test_offset); -} - -void SteadyClock::Handle_SetTestOffset(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto test_offset{rp.Pop<s64>()}; - - auto res = SetTestOffset(test_offset); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void SteadyClock::Handle_GetRtcValue(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - s64 rtc_value{}; - auto res = GetRtcValue(rtc_value); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push(rtc_value); -} - -void SteadyClock::Handle_IsRtcResetDetected(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - bool reset_detected{false}; - auto res = IsRtcResetDetected(reset_detected); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(reset_detected); -} - -void SteadyClock::Handle_GetSetupResultValue(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Result result_value{ResultSuccess}; - auto res = GetSetupResultValue(result_value); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(result_value); -} - -void SteadyClock::Handle_GetInternalOffset(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - s64 internal_offset{}; - auto res = GetInternalOffset(internal_offset); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push(internal_offset); -} - -// =============================== Implementations =========================== - -Result SteadyClock::GetCurrentTimePoint(SteadyClockTimePoint& out_time_point) { R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); - R_RETURN(m_clock_core.GetCurrentTimePoint(out_time_point)); + R_RETURN(m_clock_core.GetCurrentTimePoint(*out_time_point)); } -Result SteadyClock::GetTestOffset(s64& out_test_offset) { +Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); }); + R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); - out_test_offset = m_clock_core.GetTestOffset(); + *out_test_offset = m_clock_core.GetTestOffset(); R_SUCCEED(); } Result SteadyClock::SetTestOffset(s64 test_offset) { + LOG_DEBUG(Service_Time, "called. test_offset={}", test_offset); + R_UNLESS(m_can_write_steady_clock, ResultPermissionDenied); R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); @@ -130,34 +58,43 @@ Result SteadyClock::SetTestOffset(s64 test_offset) { R_SUCCEED(); } -Result SteadyClock::GetRtcValue(s64& out_rtc_value) { +Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); }); + R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); - R_RETURN(m_clock_core.GetRtcValue(out_rtc_value)); + R_RETURN(m_clock_core.GetRtcValue(*out_rtc_value)); } -Result SteadyClock::IsRtcResetDetected(bool& out_is_detected) { +Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); }); + R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); - out_is_detected = m_clock_core.IsResetDetected(); + *out_is_detected = m_clock_core.IsResetDetected(); R_SUCCEED(); } -Result SteadyClock::GetSetupResultValue(Result& out_result) { +Result SteadyClock::GetSetupResultValue(Out<Result> out_result) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); }); + R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); - out_result = m_clock_core.GetSetupResultValue(); + *out_result = m_clock_core.GetSetupResultValue(); R_SUCCEED(); } -Result SteadyClock::GetInternalOffset(s64& out_internal_offset) { +Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) { + SCOPE_EXIT( + { LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); }); + R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); - out_internal_offset = m_clock_core.GetInternalOffset(); + *out_internal_offset = m_clock_core.GetInternalOffset(); R_SUCCEED(); } diff --git a/src/core/hle/service/psc/time/steady_clock.h b/src/core/hle/service/psc/time/steady_clock.h index 115e9b138..025d758a6 100644 --- a/src/core/hle/service/psc/time/steady_clock.h +++ b/src/core/hle/service/psc/time/steady_clock.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/service/cmif_types.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/manager.h" @@ -22,23 +23,15 @@ public: ~SteadyClock() override = default; - Result GetCurrentTimePoint(SteadyClockTimePoint& out_time_point); - Result GetTestOffset(s64& out_test_offset); + Result GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point); + Result GetTestOffset(Out<s64> out_test_offset); Result SetTestOffset(s64 test_offset); - Result GetRtcValue(s64& out_rtc_value); - Result IsRtcResetDetected(bool& out_is_detected); - Result GetSetupResultValue(Result& out_result); - Result GetInternalOffset(s64& out_internal_offset); + Result GetRtcValue(Out<s64> out_rtc_value); + Result IsRtcResetDetected(Out<bool> out_is_detected); + Result GetSetupResultValue(Out<Result> out_result); + Result GetInternalOffset(Out<s64> out_internal_offset); private: - void Handle_GetCurrentTimePoint(HLERequestContext& ctx); - void Handle_GetTestOffset(HLERequestContext& ctx); - void Handle_SetTestOffset(HLERequestContext& ctx); - void Handle_GetRtcValue(HLERequestContext& ctx); - void Handle_IsRtcResetDetected(HLERequestContext& ctx); - void Handle_GetSetupResultValue(HLERequestContext& ctx); - void Handle_GetInternalOffset(HLERequestContext& ctx); - Core::System& m_system; StandardSteadyClockCore& m_clock_core; diff --git a/src/core/hle/service/psc/time/system_clock.cpp b/src/core/hle/service/psc/time/system_clock.cpp index 13d2f1d11..0695502d5 100644 --- a/src/core/hle/service/psc/time/system_clock.cpp +++ b/src/core/hle/service/psc/time/system_clock.cpp @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/scope_exit.h" #include "core/core.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/psc/time/system_clock.h" namespace Service::PSC::Time { @@ -13,83 +15,28 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo can_write_uninitialized_clock} { // clang-format off static const FunctionInfo functions[] = { - {0, &SystemClock::Handle_GetCurrentTime, "GetCurrentTime"}, - {1, &SystemClock::Handle_SetCurrentTime, "SetCurrentTime"}, - {2, &SystemClock::Handle_GetSystemClockContext, "GetSystemClockContext"}, - {3, &SystemClock::Handle_SetSystemClockContext, "SetSystemClockContext"}, - {4, &SystemClock::Handle_GetOperationEventReadableHandle, "GetOperationEventReadableHandle"}, + {0, D<&SystemClock::GetCurrentTime>, "GetCurrentTime"}, + {1, D<&SystemClock::SetCurrentTime>, "SetCurrentTime"}, + {2, D<&SystemClock::GetSystemClockContext>, "GetSystemClockContext"}, + {3, D<&SystemClock::SetSystemClockContext>, "SetSystemClockContext"}, + {4, D<&SystemClock::GetOperationEventReadableHandle>, "GetOperationEventReadableHandle"}, }; // clang-format on RegisterHandlers(functions); } -void SystemClock::Handle_GetCurrentTime(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - s64 time{}; - auto res = GetCurrentTime(time); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push<s64>(time); -} - -void SystemClock::Handle_SetCurrentTime(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto time{rp.Pop<s64>()}; - - auto res = SetCurrentTime(time); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void SystemClock::Handle_GetSystemClockContext(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - SystemClockContext context{}; - auto res = GetSystemClockContext(context); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(SystemClockContext) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<SystemClockContext>(context); -} - -void SystemClock::Handle_SetSystemClockContext(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto context{rp.PopRaw<SystemClockContext>()}; - - auto res = SetSystemClockContext(context); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void SystemClock::Handle_GetOperationEventReadableHandle(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - Kernel::KEvent* event{}; - auto res = GetOperationEventReadableHandle(&event); +Result SystemClock::GetCurrentTime(Out<s64> out_time) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); }); - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(res); - rb.PushCopyObjects(event->GetReadableEvent()); -} - -// =============================== Implementations =========================== - -Result SystemClock::GetCurrentTime(s64& out_time) { R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); - R_RETURN(m_clock_core.GetCurrentTime(&out_time)); + R_RETURN(m_clock_core.GetCurrentTime(out_time.Get())); } Result SystemClock::SetCurrentTime(s64 time) { + LOG_DEBUG(Service_Time, "called. time={}", time); + R_UNLESS(m_can_write_clock, ResultPermissionDenied); R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); @@ -97,14 +44,18 @@ Result SystemClock::SetCurrentTime(s64 time) { R_RETURN(m_clock_core.SetCurrentTime(time)); } -Result SystemClock::GetSystemClockContext(SystemClockContext& out_context) { +Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); }); + R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); - R_RETURN(m_clock_core.GetContext(out_context)); + R_RETURN(m_clock_core.GetContext(*out_context)); } Result SystemClock::SetSystemClockContext(SystemClockContext& context) { + LOG_DEBUG(Service_Time, "called. context={}", context); + R_UNLESS(m_can_write_clock, ResultPermissionDenied); R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); @@ -112,7 +63,10 @@ Result SystemClock::SetSystemClockContext(SystemClockContext& context) { R_RETURN(m_clock_core.SetContextAndWrite(context)); } -Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event) { +Result SystemClock::GetOperationEventReadableHandle( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_Time, "called."); + if (!m_operation_event) { m_operation_event = std::make_unique<OperationEvent>(m_system); R_UNLESS(m_operation_event != nullptr, ResultFailed); @@ -120,7 +74,7 @@ Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event) m_clock_core.LinkOperationEvent(*m_operation_event); } - *out_event = m_operation_event->m_event; + *out_event = &m_operation_event->m_event->GetReadableEvent(); R_SUCCEED(); } diff --git a/src/core/hle/service/psc/time/system_clock.h b/src/core/hle/service/psc/time/system_clock.h index f30027e7b..b40d73595 100644 --- a/src/core/hle/service/psc/time/system_clock.h +++ b/src/core/hle/service/psc/time/system_clock.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/service/cmif_types.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/manager.h" @@ -22,19 +23,13 @@ public: ~SystemClock() override = default; - Result GetCurrentTime(s64& out_time); + Result GetCurrentTime(Out<s64> out_time); Result SetCurrentTime(s64 time); - Result GetSystemClockContext(SystemClockContext& out_context); + Result GetSystemClockContext(Out<SystemClockContext> out_context); Result SetSystemClockContext(SystemClockContext& context); - Result GetOperationEventReadableHandle(Kernel::KEvent** out_event); + Result GetOperationEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event); private: - void Handle_GetCurrentTime(HLERequestContext& ctx); - void Handle_SetCurrentTime(HLERequestContext& ctx); - void Handle_GetSystemClockContext(HLERequestContext& ctx); - void Handle_SetSystemClockContext(HLERequestContext& ctx); - void Handle_GetOperationEventReadableHandle(HLERequestContext& ctx); - Core::System& m_system; SystemClockCore& m_clock_core; diff --git a/src/core/hle/service/psc/time/time_zone.cpp b/src/core/hle/service/psc/time/time_zone.cpp index cfee8f866..82ddba42f 100644 --- a/src/core/hle/service/psc/time/time_zone.cpp +++ b/src/core/hle/service/psc/time/time_zone.cpp @@ -5,7 +5,7 @@ namespace Service::PSC::Time { namespace { -constexpr Result ValidateRule(Tz::Rule& rule) { +constexpr Result ValidateRule(const Tz::Rule& rule) { if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) || rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) || rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) { @@ -26,7 +26,7 @@ constexpr Result ValidateRule(Tz::Rule& rule) { R_SUCCEED(); } -constexpr bool GetTimeZoneTime(s64& out_time, Tz::Rule& rule, s64 time, s32 index, +constexpr bool GetTimeZoneTime(s64& out_time, const Tz::Rule& rule, s64 time, s32 index, s32 index_offset) { s32 found_idx{}; s32 expected_index{index + index_offset}; @@ -107,7 +107,7 @@ Result TimeZone::GetTimePoint(SteadyClockTimePoint& out_time_point) { Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time, CalendarAdditionalInfo& out_additional_info, s64 time, - Tz::Rule& rule) { + const Tz::Rule& rule) { std::scoped_lock l{m_mutex}; R_RETURN(ToCalendarTimeImpl(out_calendar_time, out_additional_info, time, rule)); } @@ -140,8 +140,8 @@ Result TimeZone::ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary) R_RETURN(ParseBinaryImpl(out_rule, binary)); } -Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, - CalendarTime& calendar, Tz::Rule& rule) { +Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count, + CalendarTime& calendar, const Tz::Rule& rule) { std::scoped_lock l{m_mutex}; auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1); @@ -157,7 +157,7 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 ou R_RETURN(res); } -Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, +Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, u32 out_times_count, CalendarTime& calendar) { std::scoped_lock l{m_mutex}; @@ -183,7 +183,7 @@ Result TimeZone::ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary) Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time, CalendarAdditionalInfo& out_additional_info, s64 time, - Tz::Rule& rule) { + const Tz::Rule& rule) { R_TRY(ValidateRule(rule)); Tz::CalendarTimeInternal calendar_internal{}; @@ -212,8 +212,8 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time, R_SUCCEED(); } -Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, - CalendarTime& calendar, Tz::Rule& rule, s32 is_dst) { +Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count, + CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst) { R_TRY(ValidateRule(rule)); calendar.month -= 1; diff --git a/src/core/hle/service/psc/time/time_zone.h b/src/core/hle/service/psc/time/time_zone.h index ce2acca17..6bd8f2fda 100644 --- a/src/core/hle/service/psc/time/time_zone.h +++ b/src/core/hle/service/psc/time/time_zone.h @@ -32,23 +32,24 @@ public: Result GetTimePoint(SteadyClockTimePoint& out_time_point); Result ToCalendarTime(CalendarTime& out_calendar_time, - CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule); + CalendarAdditionalInfo& out_additional_info, s64 time, + const Tz::Rule& rule); Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time, CalendarAdditionalInfo& calendar_additional, s64 time); Result ParseBinary(LocationName& name, std::span<const u8> binary); Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary); - Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, - CalendarTime& calendar, Tz::Rule& rule); - Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, + Result ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count, + CalendarTime& calendar, const Tz::Rule& rule); + Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, u32 out_times_count, CalendarTime& calendar); private: Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary); Result ToCalendarTimeImpl(CalendarTime& out_calendar_time, CalendarAdditionalInfo& out_additional_info, s64 time, - Tz::Rule& rule); - Result ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, - CalendarTime& calendar, Tz::Rule& rule, s32 is_dst); + const Tz::Rule& rule); + Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count, + CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst); bool m_initialized{}; std::recursive_mutex m_mutex; diff --git a/src/core/hle/service/psc/time/time_zone_service.cpp b/src/core/hle/service/psc/time/time_zone_service.cpp index e304c8387..9376a0324 100644 --- a/src/core/hle/service/psc/time/time_zone_service.cpp +++ b/src/core/hle/service/psc/time/time_zone_service.cpp @@ -2,7 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <tz/tz.h> + +#include "common/scope_exit.h" #include "core/core.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/psc/time/time_zone_service.h" namespace Service::PSC::Time { @@ -14,276 +17,153 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore& can_write_timezone_device_location} { // clang-format off static const FunctionInfo functions[] = { - {0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"}, - {1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"}, - {2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"}, - {3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"}, - {4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"}, - {5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"}, - {6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"}, - {7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"}, - {8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"}, - {20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"}, - {100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"}, - {101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, - {201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"}, - {202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"}, + {0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"}, + {1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"}, + {2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"}, + {3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"}, + {4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"}, + {5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"}, + {6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"}, + {7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"}, + {8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"}, + {20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"}, + {100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"}, + {101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"}, + {201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"}, + {202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"}, }; // clang-format on RegisterHandlers(functions); } -void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - LocationName name{}; - auto res = GetDeviceLocationName(name); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(LocationName) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<LocationName>(name); -} - -void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - [[maybe_unused]] auto name{rp.PopRaw<LocationName>()}; - - if (!m_can_write_timezone_device_location) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultPermissionDenied); - return; - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotImplemented); -} - -void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - u32 count{}; - auto res = GetTotalLocationNameCount(count); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(count); -} - -void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); +Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); }); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotImplemented); + R_RETURN(m_time_zone.GetLocationName(*out_location_name)); } -void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); +Result TimeZoneService::SetDeviceLocationName(LocationName& location_name) { + LOG_DEBUG(Service_Time, "called. This function is not implemented!"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotImplemented); + R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); + R_RETURN(ResultNotImplemented); } -void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - RuleVersion rule_version{}; - auto res = GetTimeZoneRuleVersion(rule_version); +Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); }); - IPC::ResponseBuilder rb{ctx, 2 + sizeof(RuleVersion) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<RuleVersion>(rule_version); + R_RETURN(m_time_zone.GetTotalLocationCount(*out_count)); } -void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - LocationName name{}; - SteadyClockTimePoint time_point{}; - auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name); +Result TimeZoneService::LoadLocationNameList( + Out<u32> out_count, OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) { + LOG_DEBUG(Service_Time, "called. This function is not implemented!"); - IPC::ResponseBuilder rb{ctx, 2 + (sizeof(LocationName) / sizeof(u32)) + - (sizeof(SteadyClockTimePoint) / sizeof(u32))}; - rb.Push(res); - rb.PushRaw<LocationName>(name); - rb.PushRaw<SteadyClockTimePoint>(time_point); + R_RETURN(ResultNotImplemented); } -void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto name{rp.PopRaw<LocationName>()}; - - auto binary{ctx.ReadBuffer()}; - auto res = SetDeviceLocationNameWithTimeZoneRule(name, binary); +Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, LocationName& location_name) { + LOG_DEBUG(Service_Time, "called. This function is not implemented!"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + R_RETURN(ResultNotImplemented); } -void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - auto binary{ctx.ReadBuffer()}; +Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) { + SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); }); - Tz::Rule rule{}; - auto res = ParseTimeZoneBinary(rule, binary); - - ctx.WriteBuffer(rule); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + R_RETURN(m_time_zone.GetRuleVersion(*out_rule_version)); } -void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle( - HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); +Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( + Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}", + *out_location_name, *out_time_point); + }); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotImplemented); + R_TRY(m_time_zone.GetLocationName(*out_location_name)); + R_RETURN(m_time_zone.GetTimePoint(*out_time_point)); } -void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto time{rp.Pop<s64>()}; +Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule( + LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) { + LOG_DEBUG(Service_Time, "called. location_name={}", location_name); - auto rule_buffer{ctx.ReadBuffer()}; - Tz::Rule rule{}; - std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule)); - - CalendarTime calendar_time{}; - CalendarAdditionalInfo additional_info{}; - auto res = ToCalendarTime(calendar_time, additional_info, time, rule); - - IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) + - (sizeof(CalendarAdditionalInfo) / sizeof(u32))}; - rb.Push(res); - rb.PushRaw<CalendarTime>(calendar_time); - rb.PushRaw<CalendarAdditionalInfo>(additional_info); -} - -void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto time{rp.Pop<s64>()}; + R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); + R_TRY(m_time_zone.ParseBinary(location_name, binary)); - CalendarTime calendar_time{}; - CalendarAdditionalInfo additional_info{}; - auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time); + SteadyClockTimePoint time_point{}; + R_TRY(m_clock_core.GetCurrentTimePoint(time_point)); - IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) + - (sizeof(CalendarAdditionalInfo) / sizeof(u32))}; - rb.Push(res); - rb.PushRaw<CalendarTime>(calendar_time); - rb.PushRaw<CalendarAdditionalInfo>(additional_info); + m_time_zone.SetTimePoint(time_point); + R_SUCCEED(); } -void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) { +Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule, + InBuffer<BufferAttr_HipcAutoSelect> binary) { LOG_DEBUG(Service_Time, "called."); - IPC::RequestParser rp{ctx}; - auto calendar{rp.PopRaw<CalendarTime>()}; - - auto binary{ctx.ReadBuffer()}; - - Tz::Rule rule{}; - std::memcpy(&rule, binary.data(), sizeof(Tz::Rule)); - - u32 count{}; - std::array<s64, 2> times{}; - u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))}; - - auto res = ToPosixTime(count, times, times_count, calendar, rule); - - ctx.WriteBuffer(times); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(count); + R_RETURN(m_time_zone.ParseBinaryInto(*out_rule, binary)); } -void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) { - LOG_DEBUG(Service_Time, "called."); - - IPC::RequestParser rp{ctx}; - auto calendar{rp.PopRaw<CalendarTime>()}; +Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_Time, "called. This function is not implemented!"); - u32 count{}; - std::array<s64, 2> times{}; - u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))}; - - auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar); - - ctx.WriteBuffer(times); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.Push(count); + R_RETURN(ResultNotImplemented); } -// =============================== Implementations =========================== - -Result TimeZoneService::GetDeviceLocationName(LocationName& out_location_name) { - R_RETURN(m_time_zone.GetLocationName(out_location_name)); -} +Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time, + Out<CalendarAdditionalInfo> out_additional_info, s64 time, + InRule rule) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, + *out_calendar_time, *out_additional_info); + }); -Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) { - R_RETURN(m_time_zone.GetTotalLocationCount(out_count)); -} - -Result TimeZoneService::GetTimeZoneRuleVersion(RuleVersion& out_rule_version) { - R_RETURN(m_time_zone.GetRuleVersion(out_rule_version)); -} - -Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point, - LocationName& location_name) { - R_TRY(m_time_zone.GetLocationName(location_name)); - R_RETURN(m_time_zone.GetTimePoint(out_time_point)); + R_RETURN( + m_time_zone.ToCalendarTime(*out_calendar_time, *out_additional_info, time, *rule.Get())); } -Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name, - std::span<const u8> binary) { - R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); - R_TRY(m_time_zone.ParseBinary(location_name, binary)); - - SteadyClockTimePoint time_point{}; - R_TRY(m_clock_core.GetCurrentTimePoint(time_point)); +Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time, + Out<CalendarAdditionalInfo> out_additional_info, + s64 time) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, + *out_calendar_time, *out_additional_info); + }); - m_time_zone.SetTimePoint(time_point); - R_SUCCEED(); + R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(*out_calendar_time, *out_additional_info, time)); } -Result TimeZoneService::ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary) { - R_RETURN(m_time_zone.ParseBinaryInto(out_rule, binary)); -} +Result TimeZoneService::ToPosixTime(Out<u32> out_count, + OutArray<s64, BufferAttr_HipcPointer> out_times, + Out<u32> out_times_count, CalendarTime& calendar_time, + InRule rule) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, + "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} " + "out_times_count={}", + calendar_time, *out_count, out_times[0], out_times[1], *out_times_count); + }); -Result TimeZoneService::ToCalendarTime(CalendarTime& out_calendar_time, - CalendarAdditionalInfo& out_additional_info, s64 time, - Tz::Rule& rule) { - R_RETURN(m_time_zone.ToCalendarTime(out_calendar_time, out_additional_info, time, rule)); -} - -Result TimeZoneService::ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time, - CalendarAdditionalInfo& out_additional_info, - s64 time) { - R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time)); + R_RETURN( + m_time_zone.ToPosixTime(*out_count, out_times, *out_times_count, calendar_time, *rule)); } -Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, - u32 out_times_count, CalendarTime& calendar_time, - Tz::Rule& rule) { - R_RETURN(m_time_zone.ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule)); -} +Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count, + OutArray<s64, BufferAttr_HipcPointer> out_times, + Out<u32> out_times_count, + CalendarTime& calendar_time) { + SCOPE_EXIT({ + LOG_DEBUG(Service_Time, + "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} " + "out_times_count={}", + calendar_time, *out_count, out_times[0], out_times[1], *out_times_count); + }); -Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, - u32 out_times_count, CalendarTime& calendar_time) { R_RETURN( - m_time_zone.ToPosixTimeWithMyRule(out_count, out_times, out_times_count, calendar_time)); + m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, *out_times_count, calendar_time)); } } // namespace Service::PSC::Time diff --git a/src/core/hle/service/psc/time/time_zone_service.h b/src/core/hle/service/psc/time/time_zone_service.h index 074c1d4ae..084e3f907 100644 --- a/src/core/hle/service/psc/time/time_zone_service.h +++ b/src/core/hle/service/psc/time/time_zone_service.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/service/cmif_types.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/manager.h" @@ -20,45 +21,41 @@ struct Rule; namespace Service::PSC::Time { class TimeZoneService final : public ServiceFramework<TimeZoneService> { + using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>; + using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>; + public: explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core, TimeZone& time_zone, bool can_write_timezone_device_location); ~TimeZoneService() override = default; - Result GetDeviceLocationName(LocationName& out_location_name); - Result GetTotalLocationNameCount(u32& out_count); - Result GetTimeZoneRuleVersion(RuleVersion& out_rule_version); - Result GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point, - LocationName& location_name); + Result GetDeviceLocationName(Out<LocationName> out_location_name); + Result SetDeviceLocationName(LocationName& location_name); + Result GetTotalLocationNameCount(Out<u32> out_count); + Result LoadLocationNameList(Out<u32> out_count, + OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, + u32 index); + Result LoadTimeZoneRule(OutRule out_rule, LocationName& location_name); + Result GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version); + Result GetDeviceLocationNameAndUpdatedTime(Out<LocationName> location_name, + Out<SteadyClockTimePoint> out_time_point); Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name, - std::span<const u8> binary); - Result ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary); - Result ToCalendarTime(CalendarTime& out_calendar_time, - CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule); - Result ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time, - CalendarAdditionalInfo& out_additional_info, s64 time); - Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, - CalendarTime& calendar_time, Tz::Rule& rule); - Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, - CalendarTime& calendar_time); + InBuffer<BufferAttr_HipcAutoSelect> binary); + Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary); + Result GetDeviceLocationNameOperationEventReadableHandle( + OutCopyHandle<Kernel::KReadableEvent> out_event); + Result ToCalendarTime(Out<CalendarTime> out_calendar_time, + Out<CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule); + Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time, + Out<CalendarAdditionalInfo> out_additional_info, s64 time); + Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, + Out<u32> out_times_count, CalendarTime& calendar_time, InRule rule); + Result ToPosixTimeWithMyRule(Out<u32> out_count, + OutArray<s64, BufferAttr_HipcPointer> out_times, + Out<u32> out_times_count, CalendarTime& calendar_time); private: - void Handle_GetDeviceLocationName(HLERequestContext& ctx); - void Handle_SetDeviceLocationName(HLERequestContext& ctx); - void Handle_GetTotalLocationNameCount(HLERequestContext& ctx); - void Handle_LoadLocationNameList(HLERequestContext& ctx); - void Handle_LoadTimeZoneRule(HLERequestContext& ctx); - void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx); - void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx); - void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx); - void Handle_ParseTimeZoneBinary(HLERequestContext& ctx); - void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx); - void Handle_ToCalendarTime(HLERequestContext& ctx); - void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx); - void Handle_ToPosixTime(HLERequestContext& ctx); - void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx); - Core::System& m_system; StandardSteadyClockCore& m_clock_core; diff --git a/src/core/hle/service/set/setting_formats/system_settings.cpp b/src/core/hle/service/set/setting_formats/system_settings.cpp index 88a305f03..7231ff78e 100644 --- a/src/core/hle/service/set/setting_formats/system_settings.cpp +++ b/src/core/hle/service/set/setting_formats/system_settings.cpp @@ -1,6 +1,7 @@ // 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 { @@ -44,7 +45,7 @@ SystemSettings DefaultSystemSettings() { .console_sleep_plan = ConsoleSleepPlan::Sleep1Hour, }; - settings.device_time_zone_location_name = {"UTC"}; + settings.device_time_zone_location_name = Service::PSC::Time::LocationName{"UTC"}; settings.user_system_clock_automatic_correction_enabled = true; settings.primary_album_storage = PrimaryAlbumStorage::SdCard; @@ -52,6 +53,17 @@ SystemSettings DefaultSystemSettings() { settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0; settings.vibration_master_volume = 1.0f; + const auto language_code = + available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())]; + const auto key_code = + std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), + [=](const auto& element) { return element.first == language_code; }); + + settings.keyboard_layout = KeyboardLayout::EnglishUs; + if (key_code != language_to_layout.end()) { + settings.keyboard_layout = key_code->second; + } + return settings; } diff --git a/src/core/hle/service/set/setting_formats/system_settings.h b/src/core/hle/service/set/setting_formats/system_settings.h index af5929fa9..ebc373da5 100644 --- a/src/core/hle/service/set/setting_formats/system_settings.h +++ b/src/core/hle/service/set/setting_formats/system_settings.h @@ -213,10 +213,9 @@ struct SystemSettings { // nn::settings::system::AudioVolume std::array<u8, 0x8> audio_volume_type0; std::array<u8, 0x8> audio_volume_type1; - // nn::settings::system::AudioOutputMode - s32 audio_output_mode_type0; - s32 audio_output_mode_type1; - s32 audio_output_mode_type2; + AudioOutputMode audio_output_mode_hdmi; + AudioOutputMode audio_output_mode_speaker; + AudioOutputMode audio_output_mode_headphone; bool force_mute_on_headphone_removed; INSERT_PADDING_BYTES(0x3); s32 headphone_volume_warning_count; @@ -224,9 +223,8 @@ struct SystemSettings { INSERT_PADDING_BYTES(0x3); // nn::settings::system::AudioVolume std::array<u8, 0x8> audio_volume_type2; - // nn::settings::system::AudioOutputMode - s32 audio_output_mode_type3; - s32 audio_output_mode_type4; + AudioOutputMode audio_output_mode_type3; + AudioOutputMode audio_output_mode_type4; bool hearing_protection_safeguard_flag; INSERT_PADDING_BYTES(0x3); INSERT_PADDING_BYTES(0x4); // Reserved diff --git a/src/core/hle/service/set/settings_types.h b/src/core/hle/service/set/settings_types.h index 968425319..ceb85b82a 100644 --- a/src/core/hle/service/set/settings_types.h +++ b/src/core/hle/service/set/settings_types.h @@ -23,9 +23,12 @@ enum class AudioOutputMode : u32 { /// This is nn::settings::system::AudioOutputModeTarget enum class AudioOutputModeTarget : u32 { + None, Hdmi, Speaker, Headphone, + Type3, + Type4, }; /// This is nn::settings::system::AudioVolumeTarget @@ -367,6 +370,12 @@ struct AccountNotificationSettings { static_assert(sizeof(AccountNotificationSettings) == 0x18, "AccountNotificationSettings is an invalid size"); +/// This is nn::settings::factory::BatteryLot +struct BatteryLot { + std::array<char, 0x18> lot_number; +}; +static_assert(sizeof(BatteryLot) == 0x18, "BatteryLot is an invalid size"); + /// This is nn::settings::system::EulaVersion struct EulaVersion { u32 version; @@ -436,6 +445,12 @@ struct NotificationSettings { }; static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size"); +/// This is nn::settings::factory::SerialNumber +struct SerialNumber { + std::array<char, 0x18> serial_number; +}; +static_assert(sizeof(SerialNumber) == 0x18, "SerialNumber is an invalid size"); + /// This is nn::settings::system::SleepSettings struct SleepSettings { SleepFlag flags; diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index e907b57b6..100cb2db4 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -25,7 +25,7 @@ namespace Service::Set { namespace { -constexpr u32 SETTINGS_VERSION{1u}; +constexpr u32 SETTINGS_VERSION{2u}; constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); struct SettingsHeader { u64 magic; @@ -131,10 +131,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"}, {41, nullptr, "GetEdid"}, {42, nullptr, "SetEdid"}, - {43, nullptr, "GetAudioOutputMode"}, - {44, nullptr, "SetAudioOutputMode"}, - {45, &ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved, "IsForceMuteOnHeadphoneRemoved"}, - {46, &ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved, "SetForceMuteOnHeadphoneRemoved"}, + {43, &ISystemSettingsServer::GetAudioOutputMode, "GetAudioOutputMode"}, + {44, &ISystemSettingsServer::SetAudioOutputMode, "SetAudioOutputMode"}, + {45, &ISystemSettingsServer::GetSpeakerAutoMuteFlag , "GetSpeakerAutoMuteFlag"}, + {46, &ISystemSettingsServer::SetSpeakerAutoMuteFlag , "SetSpeakerAutoMuteFlag"}, {47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"}, {48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"}, {49, nullptr, "GetDataDeletionSettings"}, @@ -155,8 +155,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"}, {65, nullptr, "GetUsb30EnableFlag"}, {66, nullptr, "SetUsb30EnableFlag"}, - {67, nullptr, "GetBatteryLot"}, - {68, nullptr, "GetSerialNumber"}, + {67, &ISystemSettingsServer::GetBatteryLot, "GetBatteryLot"}, + {68, &ISystemSettingsServer::GetSerialNumber, "GetSerialNumber"}, {69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"}, {70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"}, {71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"}, @@ -184,11 +184,11 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {93, nullptr, "AcquireFatalDirtyFlagEventHandle"}, {94, nullptr, "GetFatalDirtyFlags"}, {95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"}, - {96, nullptr, "SetAutoUpdateEnableFlag"}, + {96, &ISystemSettingsServer::SetAutoUpdateEnableFlag, "SetAutoUpdateEnableFlag"}, {97, nullptr, "GetNxControllerSettings"}, {98, nullptr, "SetNxControllerSettings"}, {99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"}, - {100, nullptr, "SetBatteryPercentageFlag"}, + {100, &ISystemSettingsServer::SetBatteryPercentageFlag, "SetBatteryPercentageFlag"}, {101, nullptr, "GetExternalRtcResetFlag"}, {102, nullptr, "SetExternalRtcResetFlag"}, {103, nullptr, "GetUsbFullKeyEnableFlag"}, @@ -208,12 +208,12 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {117, nullptr, "GetHeadphoneVolumeUpdateFlag"}, {118, nullptr, "SetHeadphoneVolumeUpdateFlag"}, {119, nullptr, "NeedsToUpdateHeadphoneVolume"}, - {120, nullptr, "GetPushNotificationActivityModeOnSleep"}, - {121, nullptr, "SetPushNotificationActivityModeOnSleep"}, + {120, &ISystemSettingsServer::GetPushNotificationActivityModeOnSleep, "GetPushNotificationActivityModeOnSleep"}, + {121, &ISystemSettingsServer::SetPushNotificationActivityModeOnSleep, "SetPushNotificationActivityModeOnSleep"}, {122, nullptr, "GetServiceDiscoveryControlSettings"}, {123, nullptr, "SetServiceDiscoveryControlSettings"}, {124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"}, - {125, nullptr, "SetErrorReportSharePermission"}, + {125, &ISystemSettingsServer::SetErrorReportSharePermission, "SetErrorReportSharePermission"}, {126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"}, {127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"}, {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"}, @@ -225,7 +225,7 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"}, {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"}, {136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"}, - {137, nullptr, "SetKeyboardLayout"}, + {137, &ISystemSettingsServer::SetKeyboardLayout, "SetKeyboardLayout"}, {138, nullptr, "GetWebInspectorFlag"}, {139, nullptr, "GetAllowedSslHosts"}, {140, nullptr, "GetHostFsMountPoint"}, @@ -291,8 +291,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {200, nullptr, "SetButtonConfigRegisteredSettings"}, {201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"}, {202, nullptr, "SetFieldTestingFlag"}, - {203, nullptr, "GetPanelCrcMode"}, - {204, nullptr, "SetPanelCrcMode"}, + {203, &ISystemSettingsServer::GetPanelCrcMode, "GetPanelCrcMode"}, + {204, &ISystemSettingsServer::SetPanelCrcMode, "SetPanelCrcMode"}, {205, nullptr, "GetNxControllerSettingsEx"}, {206, nullptr, "SetNxControllerSettingsEx"}, {207, nullptr, "GetHearingProtectionSafeguardFlag"}, @@ -349,7 +349,7 @@ bool ISystemSettingsServer::LoadSettingsFile(std::filesystem::path& path, auto&& } SettingsHeader hdr{}; file.read(reinterpret_cast<char*>(&hdr), sizeof(hdr)); - return hdr.magic == SETTINGS_MAGIC && hdr.version == SETTINGS_VERSION; + return hdr.magic == SETTINGS_MAGIC && hdr.version >= SETTINGS_VERSION; }; if (!exists || !file_size_ok) { @@ -390,7 +390,7 @@ bool ISystemSettingsServer::StoreSettingsFile(std::filesystem::path& path, auto& } auto settings_base = path / "settings"; - auto settings_tmp_file = settings_base; + std::filesystem::path settings_tmp_file = settings_base; settings_tmp_file = settings_tmp_file.replace_extension("tmp"); std::ofstream file(settings_tmp_file, std::ios::binary | std::ios::out); if (!file.is_open()) { @@ -722,6 +722,9 @@ static Settings GetSettings() { ret["hid_debug"]["disabled_features_per_id"] = std::vector<u8>(0xa8); ret["hid_debug"]["touch_firmware_auto_update_disabled"] = ToBytes(bool{false}); + // Mii + ret["mii"]["is_db_test_mode_enabled"] = ToBytes(bool{false}); + // Settings ret["settings_debug"]["is_debug_mode_enabled"] = ToBytes(bool{false}); @@ -814,7 +817,34 @@ void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) { +void ISystemSettingsServer::GetAudioOutputMode(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto target{rp.PopEnum<AudioOutputModeTarget>()}; + + AudioOutputMode output_mode{}; + const auto result = GetAudioOutputMode(output_mode, target); + + LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(result); + rb.PushEnum(output_mode); +} + +void ISystemSettingsServer::SetAudioOutputMode(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto target{rp.PopEnum<AudioOutputModeTarget>()}; + const auto output_mode{rp.PopEnum<AudioOutputMode>()}; + + const auto result = SetAudioOutputMode(target, output_mode); + + LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void ISystemSettingsServer::GetSpeakerAutoMuteFlag(HLERequestContext& ctx) { LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}", m_system_settings.force_mute_on_headphone_removed); @@ -823,7 +853,7 @@ void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx rb.PushRaw(m_system_settings.force_mute_on_headphone_removed); } -void ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) { +void ISystemSettingsServer::SetSpeakerAutoMuteFlag(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>(); SetSaveNeeded(); @@ -966,6 +996,26 @@ void ISystemSettingsServer::SetPrimaryAlbumStorage(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void ISystemSettingsServer::GetBatteryLot(HLERequestContext& ctx) { + BatteryLot battery_lot = {"YUZUEMULATOR123456789"}; + + LOG_INFO(Service_SET, "called"); + + IPC::ResponseBuilder rb{ctx, 8}; + rb.Push(ResultSuccess); + rb.PushRaw(battery_lot); +} + +void ISystemSettingsServer::GetSerialNumber(HLERequestContext& ctx) { + SerialNumber console_serial = {"YUZ10012345678"}; + + LOG_INFO(Service_SET, "called"); + + IPC::ResponseBuilder rb{ctx, 8}; + rb.Push(ResultSuccess); + rb.PushRaw(console_serial); +} + void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) { LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag); @@ -1129,6 +1179,17 @@ void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) { rb.Push(m_system_settings.auto_update_enable_flag); } +void ISystemSettingsServer::SetAutoUpdateEnableFlag(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.auto_update_enable_flag = rp.Pop<bool>(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}", m_system_settings.battery_percentage_flag); @@ -1138,6 +1199,18 @@ void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) { rb.Push(m_system_settings.battery_percentage_flag); } +void ISystemSettingsServer::SetBatteryPercentageFlag(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.battery_percentage_flag = rp.Pop<bool>(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, battery_percentage_flag={}", + m_system_settings.battery_percentage_flag); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called."); @@ -1161,6 +1234,27 @@ void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestConte rb.Push(offset); } +void ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}", + m_system_settings.push_notification_activity_mode_on_sleep); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(m_system_settings.push_notification_activity_mode_on_sleep); +} + +void ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.push_notification_activity_mode_on_sleep = rp.Pop<s32>(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}", + m_system_settings.push_notification_activity_mode_on_sleep); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) { LOG_INFO(Service_SET, "called, error_report_share_permission={}", m_system_settings.error_report_share_permission); @@ -1170,6 +1264,18 @@ void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx rb.PushEnum(m_system_settings.error_report_share_permission); } +void ISystemSettingsServer::SetErrorReportSharePermission(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.error_report_share_permission = rp.PopEnum<ErrorReportSharePermission>(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, error_report_share_permission={}", + m_system_settings.error_report_share_permission); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) { LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag); @@ -1190,22 +1296,22 @@ void ISystemSettingsServer::SetAppletLaunchFlags(HLERequestContext& ctx) { } void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) { - const auto language_code = - available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())]; - const auto key_code = - std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), - [=](const auto& element) { return element.first == language_code; }); - - KeyboardLayout selected_keyboard_layout = KeyboardLayout::EnglishUs; - if (key_code != language_to_layout.end()) { - selected_keyboard_layout = key_code->second; - } - - LOG_INFO(Service_SET, "called, selected_keyboard_layout={}", selected_keyboard_layout); + LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(static_cast<u32>(selected_keyboard_layout)); + rb.Push(static_cast<u32>(m_system_settings.keyboard_layout)); +} + +void ISystemSettingsServer::SetKeyboardLayout(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.keyboard_layout = rp.PopRaw<KeyboardLayout>(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); } void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) { @@ -1297,6 +1403,25 @@ void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) { rb.Push(m_system_settings.field_testing_flag); } +void ISystemSettingsServer::GetPanelCrcMode(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(m_system_settings.panel_crc_mode); +} + +void ISystemSettingsServer::SetPanelCrcMode(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.panel_crc_mode = rp.PopRaw<s32>(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void ISystemSettingsServer::SetupSettings() { auto system_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050"; @@ -1387,6 +1512,66 @@ Result ISystemSettingsServer::SetVibrationMasterVolume(f32 volume) { R_SUCCEED(); } +Result ISystemSettingsServer::GetAudioOutputMode(AudioOutputMode& out_output_mode, + AudioOutputModeTarget target) const { + switch (target) { + case AudioOutputModeTarget::Hdmi: + out_output_mode = m_system_settings.audio_output_mode_hdmi; + break; + case AudioOutputModeTarget::Speaker: + out_output_mode = m_system_settings.audio_output_mode_speaker; + break; + case AudioOutputModeTarget::Headphone: + out_output_mode = m_system_settings.audio_output_mode_headphone; + break; + case AudioOutputModeTarget::Type3: + out_output_mode = m_system_settings.audio_output_mode_type3; + break; + case AudioOutputModeTarget::Type4: + out_output_mode = m_system_settings.audio_output_mode_type4; + break; + default: + LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target); + } + R_SUCCEED(); +} + +Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target, + AudioOutputMode output_mode) { + switch (target) { + case AudioOutputModeTarget::Hdmi: + m_system_settings.audio_output_mode_hdmi = output_mode; + break; + case AudioOutputModeTarget::Speaker: + m_system_settings.audio_output_mode_speaker = output_mode; + break; + case AudioOutputModeTarget::Headphone: + m_system_settings.audio_output_mode_headphone = output_mode; + break; + case AudioOutputModeTarget::Type3: + m_system_settings.audio_output_mode_type3 = output_mode; + break; + case AudioOutputModeTarget::Type4: + m_system_settings.audio_output_mode_type4 = output_mode; + break; + default: + LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target); + } + SetSaveNeeded(); + R_SUCCEED(); +} + +Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(bool& is_auto_mute) const { + is_auto_mute = m_system_settings.force_mute_on_headphone_removed; + R_SUCCEED(); +} + +Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool is_auto_mute) { + m_system_settings.force_mute_on_headphone_removed = is_auto_mute; + SetSaveNeeded(); + R_SUCCEED(); +} + Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const { out_id = m_private_settings.external_clock_source_id; R_SUCCEED(); diff --git a/src/core/hle/service/set/system_settings_server.h b/src/core/hle/service/set/system_settings_server.h index acbda8b8c..1982b9723 100644 --- a/src/core/hle/service/set/system_settings_server.h +++ b/src/core/hle/service/set/system_settings_server.h @@ -50,6 +50,10 @@ public: Result GetVibrationMasterVolume(f32& out_volume) const; Result SetVibrationMasterVolume(f32 volume); + Result GetAudioOutputMode(AudioOutputMode& out_output_mode, AudioOutputModeTarget target) const; + Result SetAudioOutputMode(AudioOutputModeTarget target, AudioOutputMode output_mode); + Result GetSpeakerAutoMuteFlag(bool& is_auto_mute) const; + Result SetSpeakerAutoMuteFlag(bool auto_mute); Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const; Result SetExternalSteadyClockSourceId(const Common::UUID& id); Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const; @@ -97,8 +101,10 @@ private: void GetSettingsItemValue(HLERequestContext& ctx); void GetTvSettings(HLERequestContext& ctx); void SetTvSettings(HLERequestContext& ctx); - void IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx); - void SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx); + void GetAudioOutputMode(HLERequestContext& ctx); + void SetAudioOutputMode(HLERequestContext& ctx); + void GetSpeakerAutoMuteFlag(HLERequestContext& ctx); + void SetSpeakerAutoMuteFlag(HLERequestContext& ctx); void GetDebugModeFlag(HLERequestContext& ctx); void GetQuestFlag(HLERequestContext& ctx); void SetQuestFlag(HLERequestContext& ctx); @@ -111,6 +117,8 @@ private: void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); void GetPrimaryAlbumStorage(HLERequestContext& ctx); void SetPrimaryAlbumStorage(HLERequestContext& ctx); + void GetBatteryLot(HLERequestContext& ctx); + void GetSerialNumber(HLERequestContext& ctx); void GetNfcEnableFlag(HLERequestContext& ctx); void SetNfcEnableFlag(HLERequestContext& ctx); void GetSleepSettings(HLERequestContext& ctx); @@ -126,13 +134,19 @@ private: void SetBluetoothEnableFlag(HLERequestContext& ctx); void GetMiiAuthorId(HLERequestContext& ctx); void GetAutoUpdateEnableFlag(HLERequestContext& ctx); + void SetAutoUpdateEnableFlag(HLERequestContext& ctx); void GetBatteryPercentageFlag(HLERequestContext& ctx); + void SetBatteryPercentageFlag(HLERequestContext& ctx); void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx); void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx); + void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx); + void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx); void GetErrorReportSharePermission(HLERequestContext& ctx); + void SetErrorReportSharePermission(HLERequestContext& ctx); void GetAppletLaunchFlags(HLERequestContext& ctx); void SetAppletLaunchFlags(HLERequestContext& ctx); void GetKeyboardLayout(HLERequestContext& ctx); + void SetKeyboardLayout(HLERequestContext& ctx); void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); @@ -141,6 +155,8 @@ private: void GetHomeMenuScheme(HLERequestContext& ctx); void GetHomeMenuSchemeModel(HLERequestContext& ctx); void GetFieldTestingFlag(HLERequestContext& ctx); + void GetPanelCrcMode(HLERequestContext& ctx); + void SetPanelCrcMode(HLERequestContext& ctx); bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func); bool StoreSettingsFile(std::filesystem::path& path, auto& settings); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 1c218566f..e10a4601e 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -781,8 +781,7 @@ struct Memory::Impl { }, [&]() { 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; } diff --git a/src/dedicated_room/CMakeLists.txt b/src/dedicated_room/CMakeLists.txt index 136109a0c..c0dcc0241 100644 --- a/src/dedicated_room/CMakeLists.txt +++ b/src/dedicated_room/CMakeLists.txt @@ -7,8 +7,6 @@ add_executable(yuzu-room yuzu_room.rc ) -create_target_directory_groups(yuzu-room) - target_link_libraries(yuzu-room PRIVATE common network) if (ENABLE_WEB_SERVICE) target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE) @@ -28,3 +26,5 @@ endif() if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h) endif() + +create_target_directory_groups(yuzu-room) diff --git a/src/frontend_common/config.cpp b/src/frontend_common/config.cpp index 46277e288..905f35118 100644 --- a/src/frontend_common/config.cpp +++ b/src/frontend_common/config.cpp @@ -298,6 +298,16 @@ void Config::ReadDebuggingValues() { 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)); diff --git a/src/frontend_common/config.h b/src/frontend_common/config.h index 4798d6432..4ecb97044 100644 --- a/src/frontend_common/config.h +++ b/src/frontend_common/config.h @@ -76,6 +76,9 @@ protected: 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(); diff --git a/src/hid_core/CMakeLists.txt b/src/hid_core/CMakeLists.txt index aa85502b5..64cd6e726 100644 --- a/src/hid_core/CMakeLists.txt +++ b/src/hid_core/CMakeLists.txt @@ -96,6 +96,7 @@ add_library(hid_core STATIC resources/system_buttons/home_button.h resources/system_buttons/sleep_button.cpp resources/system_buttons/sleep_button.h + resources/system_buttons/system_button_types.h resources/touch_screen/gesture.cpp resources/touch_screen/gesture.h resources/touch_screen/gesture_types.h diff --git a/src/hid_core/hid_types.h b/src/hid_core/hid_types.h index a01292a70..b310ab72d 100644 --- a/src/hid_core/hid_types.h +++ b/src/hid_core/hid_types.h @@ -437,6 +437,16 @@ struct LedPattern { }; }; +struct SleepButtonState { + union { + u64 raw{}; + + // Buttons + BitField<0, 1, u64> sleep; + }; +}; +static_assert(sizeof(SleepButtonState) == 0x8, "SleepButtonState has incorrect size."); + struct HomeButtonState { union { u64 raw{}; diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp index a2295219a..e78665d31 100644 --- a/src/hid_core/resource_manager.cpp +++ b/src/hid_core/resource_manager.cpp @@ -184,7 +184,7 @@ void ResourceManager::InitializeHidCommonSampler() { keyboard->SetAppletResource(applet_resource, &shared_mutex); const auto settings = - system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys"); + system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, settings); six_axis->SetAppletResource(applet_resource, &shared_mutex); diff --git a/src/hid_core/resources/hid_firmware_settings.cpp b/src/hid_core/resources/hid_firmware_settings.cpp index 9c9019e8f..b32c0660a 100644 --- a/src/hid_core/resources/hid_firmware_settings.cpp +++ b/src/hid_core/resources/hid_firmware_settings.cpp @@ -8,7 +8,8 @@ namespace Service::HID { HidFirmwareSettings::HidFirmwareSettings(Core::System& system) { - m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys"); + m_set_sys = + system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); LoadSettings(true); } diff --git a/src/hid_core/resources/shared_memory_format.h b/src/hid_core/resources/shared_memory_format.h index 2ae0004ba..49755c8dc 100644 --- a/src/hid_core/resources/shared_memory_format.h +++ b/src/hid_core/resources/shared_memory_format.h @@ -12,6 +12,7 @@ #include "hid_core/resources/mouse/mouse_types.h" #include "hid_core/resources/npad/npad_types.h" #include "hid_core/resources/ring_lifo.h" +#include "hid_core/resources/system_buttons/system_button_types.h" #include "hid_core/resources/touch_screen/touch_types.h" namespace Service::HID { @@ -75,24 +76,24 @@ static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000, // This is nn::hid::detail::HomeButtonSharedMemoryFormat struct HomeButtonSharedMemoryFormat { - CommonHeader header; - INSERT_PADDING_BYTES(0x1E0); + Lifo<HomeButtonState, HidEntryCount> home_lifo{}; + INSERT_PADDING_BYTES(0x48); }; static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200, "HomeButtonSharedMemoryFormat is an invalid size"); // This is nn::hid::detail::SleepButtonSharedMemoryFormat struct SleepButtonSharedMemoryFormat { - CommonHeader header; - INSERT_PADDING_BYTES(0x1E0); + Lifo<SleepButtonState, HidEntryCount> sleep_lifo{}; + INSERT_PADDING_BYTES(0x48); }; static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200, "SleepButtonSharedMemoryFormat is an invalid size"); // This is nn::hid::detail::CaptureButtonSharedMemoryFormat struct CaptureButtonSharedMemoryFormat { - CommonHeader header; - INSERT_PADDING_BYTES(0x1E0); + Lifo<CaptureButtonState, HidEntryCount> capture_lifo{}; + INSERT_PADDING_BYTES(0x48); }; static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200, "CaptureButtonSharedMemoryFormat is an invalid size"); diff --git a/src/hid_core/resources/system_buttons/capture_button.cpp b/src/hid_core/resources/system_buttons/capture_button.cpp index 70973ae25..95eb60424 100644 --- a/src/hid_core/resources/system_buttons/capture_button.cpp +++ b/src/hid_core/resources/system_buttons/capture_button.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core_timing.h" +#include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" #include "hid_core/resources/applet_resource.h" #include "hid_core/resources/shared_memory_format.h" #include "hid_core/resources/system_buttons/capture_button.h" @@ -17,10 +19,6 @@ void CaptureButton::OnInit() {} void CaptureButton::OnRelease() {} void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!smart_update) { - return; - } - std::scoped_lock shared_lock{*shared_mutex}; const u64 aruid = applet_resource->GetActiveAruid(); auto* data = applet_resource->GetAruidData(aruid); @@ -29,11 +27,21 @@ void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { return; } - auto& header = data->shared_memory_format->capture_button.header; - header.timestamp = core_timing.GetGlobalTimeNs().count(); - header.total_entry_count = 17; - header.entry_count = 0; - header.last_entry_index = 0; + auto& shared_memory = data->shared_memory_format->capture_button; + + if (!IsControllerActivated()) { + shared_memory.capture_lifo.buffer_count = 0; + shared_memory.capture_lifo.buffer_tail = 0; + return; + } + + const auto& last_entry = shared_memory.capture_lifo.ReadCurrentEntry().state; + next_state.sampling_number = last_entry.sampling_number + 1; + + auto* controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); + next_state.buttons.raw = controller->GetHomeButtons().raw; + + shared_memory.capture_lifo.WriteNextEntry(next_state); } } // namespace Service::HID diff --git a/src/hid_core/resources/system_buttons/capture_button.h b/src/hid_core/resources/system_buttons/capture_button.h index ad95d7cad..f362ef90b 100644 --- a/src/hid_core/resources/system_buttons/capture_button.h +++ b/src/hid_core/resources/system_buttons/capture_button.h @@ -4,6 +4,7 @@ #pragma once #include "hid_core/resources/controller_base.h" +#include "hid_core/resources/system_buttons/system_button_types.h" namespace Service::HID { @@ -22,6 +23,6 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; private: - bool smart_update{}; + CaptureButtonState next_state{}; }; } // namespace Service::HID diff --git a/src/hid_core/resources/system_buttons/home_button.cpp b/src/hid_core/resources/system_buttons/home_button.cpp index f9c1f44b5..f665338f3 100644 --- a/src/hid_core/resources/system_buttons/home_button.cpp +++ b/src/hid_core/resources/system_buttons/home_button.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core_timing.h" +#include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" #include "hid_core/resources/applet_resource.h" #include "hid_core/resources/shared_memory_format.h" #include "hid_core/resources/system_buttons/home_button.h" @@ -17,10 +19,6 @@ void HomeButton::OnInit() {} void HomeButton::OnRelease() {} void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!smart_update) { - return; - } - std::scoped_lock shared_lock{*shared_mutex}; const u64 aruid = applet_resource->GetActiveAruid(); auto* data = applet_resource->GetAruidData(aruid); @@ -29,11 +27,21 @@ void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { return; } - auto& header = data->shared_memory_format->home_button.header; - header.timestamp = core_timing.GetGlobalTimeNs().count(); - header.total_entry_count = 17; - header.entry_count = 0; - header.last_entry_index = 0; + auto& shared_memory = data->shared_memory_format->home_button; + + if (!IsControllerActivated()) { + shared_memory.home_lifo.buffer_count = 0; + shared_memory.home_lifo.buffer_tail = 0; + return; + } + + const auto& last_entry = shared_memory.home_lifo.ReadCurrentEntry().state; + next_state.sampling_number = last_entry.sampling_number + 1; + + auto* controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); + next_state.buttons.raw = controller->GetHomeButtons().raw; + + shared_memory.home_lifo.WriteNextEntry(next_state); } } // namespace Service::HID diff --git a/src/hid_core/resources/system_buttons/home_button.h b/src/hid_core/resources/system_buttons/home_button.h index ecf8327f4..a9374828d 100644 --- a/src/hid_core/resources/system_buttons/home_button.h +++ b/src/hid_core/resources/system_buttons/home_button.h @@ -4,6 +4,7 @@ #pragma once #include "hid_core/resources/controller_base.h" +#include "hid_core/resources/system_buttons/system_button_types.h" namespace Service::HID { @@ -22,6 +23,6 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; private: - bool smart_update{}; + HomeButtonState next_state{}; }; } // namespace Service::HID diff --git a/src/hid_core/resources/system_buttons/sleep_button.cpp b/src/hid_core/resources/system_buttons/sleep_button.cpp index 22adf501f..159663246 100644 --- a/src/hid_core/resources/system_buttons/sleep_button.cpp +++ b/src/hid_core/resources/system_buttons/sleep_button.cpp @@ -17,10 +17,6 @@ void SleepButton::OnInit() {} void SleepButton::OnRelease() {} void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!smart_update) { - return; - } - std::scoped_lock shared_lock{*shared_mutex}; const u64 aruid = applet_resource->GetActiveAruid(); auto* data = applet_resource->GetAruidData(aruid); @@ -29,11 +25,20 @@ void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { return; } - auto& header = data->shared_memory_format->capture_button.header; - header.timestamp = core_timing.GetGlobalTimeNs().count(); - header.total_entry_count = 17; - header.entry_count = 0; - header.last_entry_index = 0; + auto& shared_memory = data->shared_memory_format->sleep_button; + + if (!IsControllerActivated()) { + shared_memory.sleep_lifo.buffer_count = 0; + shared_memory.sleep_lifo.buffer_tail = 0; + return; + } + + const auto& last_entry = shared_memory.sleep_lifo.ReadCurrentEntry().state; + next_state.sampling_number = last_entry.sampling_number + 1; + + next_state.buttons.raw = 0; + + shared_memory.sleep_lifo.WriteNextEntry(next_state); } } // namespace Service::HID diff --git a/src/hid_core/resources/system_buttons/sleep_button.h b/src/hid_core/resources/system_buttons/sleep_button.h index f9ed38c33..f8ac5031b 100644 --- a/src/hid_core/resources/system_buttons/sleep_button.h +++ b/src/hid_core/resources/system_buttons/sleep_button.h @@ -4,6 +4,7 @@ #pragma once #include "hid_core/resources/controller_base.h" +#include "hid_core/resources/system_buttons/system_button_types.h" namespace Service::HID { @@ -22,6 +23,6 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; private: - bool smart_update{}; + SleepButtonState next_state{}; }; } // namespace Service::HID diff --git a/src/hid_core/resources/system_buttons/system_button_types.h b/src/hid_core/resources/system_buttons/system_button_types.h new file mode 100644 index 000000000..929e1dc4c --- /dev/null +++ b/src/hid_core/resources/system_buttons/system_button_types.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "hid_core/hid_types.h" + +namespace Service::HID { + +// This is nn::hid::system::SleepButtonState +struct SleepButtonState { + s64 sampling_number{}; + Core::HID::SleepButtonState buttons; +}; +static_assert(sizeof(SleepButtonState) == 0x10, "SleepButtonState is an invalid size"); + +// This is nn::hid::system::HomeButtonState +struct HomeButtonState { + s64 sampling_number{}; + Core::HID::HomeButtonState buttons; +}; +static_assert(sizeof(HomeButtonState) == 0x10, "HomeButtonState is an invalid size"); + +// This is nn::hid::system::SleepButtonState +struct CaptureButtonState { + s64 sampling_number{}; + Core::HID::CaptureButtonState buttons; +}; +static_assert(sizeof(CaptureButtonState) == 0x10, "CaptureButtonState is an invalid size"); + +} // namespace Service::HID diff --git a/src/hid_core/resources/unique_pad/unique_pad.cpp b/src/hid_core/resources/unique_pad/unique_pad.cpp index 892bbe3c9..89fc57269 100644 --- a/src/hid_core/resources/unique_pad/unique_pad.cpp +++ b/src/hid_core/resources/unique_pad/unique_pad.cpp @@ -28,7 +28,7 @@ void UniquePad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { return; } - auto& header = data->shared_memory_format->capture_button.header; + auto& header = data->shared_memory_format->unique_pad.header; header.timestamp = core_timing.GetGlobalTimeNs().count(); header.total_entry_count = 17; header.entry_count = 0; diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 5ed0ad0ed..0755ba772 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -289,8 +289,6 @@ add_library(video_core STATIC vulkan_common/vulkan.h ) -create_target_directory_groups(video_core) - target_link_libraries(video_core PUBLIC common core) target_link_libraries(video_core PUBLIC glad shader_recompiler stb bc_decoder) @@ -304,7 +302,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS}) add_dependencies(video_core host_shaders) target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) -target_link_libraries(video_core PRIVATE sirit Vulkan::Headers GPUOpen::VulkanMemoryAllocator) +target_link_libraries(video_core PRIVATE sirit Vulkan::Headers Vulkan::UtilityHeaders GPUOpen::VulkanMemoryAllocator) if (ENABLE_NSIGHT_AFTERMATH) if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) @@ -365,3 +363,5 @@ endif() if (ANDROID AND ARCHITECTURE_arm64) target_link_libraries(video_core PRIVATE adrenotools) endif() + +create_target_directory_groups(video_core) diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 86a30dcd1..4f1d3b4e3 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -12,6 +12,7 @@ #include "core/core.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_swapchain.h" +#include "video_core/vulkan_common/vk_enum_string_helper.h" #include "video_core/vulkan_common/vulkan_device.h" #include "video_core/vulkan_common/vulkan_wrapper.h" #include "vulkan/vulkan_core.h" @@ -151,7 +152,7 @@ bool Swapchain::AcquireNextImage() { vk::Check(result); break; default: - LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", vk::ToString(result)); + LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", string_VkResult(result)); break; } @@ -187,7 +188,7 @@ void Swapchain::Present(VkSemaphore render_semaphore) { vk::Check(result); break; default: - LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", vk::ToString(result)); + LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", string_VkResult(result)); break; } ++frame_index; diff --git a/src/video_core/vulkan_common/vk_enum_string_helper.h b/src/video_core/vulkan_common/vk_enum_string_helper.h new file mode 100644 index 000000000..a1515814c --- /dev/null +++ b/src/video_core/vulkan_common/vk_enum_string_helper.h @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "video_core/vulkan_common/vulkan.h" + +#include <vulkan/vk_enum_string_helper.h> diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 3966bd61e..f1aa45551 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -9,6 +9,7 @@ #include "common/common_types.h" #include "common/logging/log.h" +#include "video_core/vulkan_common/vk_enum_string_helper.h" #include "video_core/vulkan_common/vma.h" #include "video_core/vulkan_common/vulkan_wrapper.h" @@ -298,109 +299,7 @@ bool Load(VkInstance instance, InstanceDispatch& dld) noexcept { } const char* Exception::what() const noexcept { - return ToString(result); -} - -const char* ToString(VkResult result) noexcept { - switch (result) { - case VkResult::VK_SUCCESS: - return "VK_SUCCESS"; - case VkResult::VK_NOT_READY: - return "VK_NOT_READY"; - case VkResult::VK_TIMEOUT: - return "VK_TIMEOUT"; - case VkResult::VK_EVENT_SET: - return "VK_EVENT_SET"; - case VkResult::VK_EVENT_RESET: - return "VK_EVENT_RESET"; - case VkResult::VK_INCOMPLETE: - return "VK_INCOMPLETE"; - case VkResult::VK_ERROR_OUT_OF_HOST_MEMORY: - return "VK_ERROR_OUT_OF_HOST_MEMORY"; - case VkResult::VK_ERROR_OUT_OF_DEVICE_MEMORY: - return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; - case VkResult::VK_ERROR_INITIALIZATION_FAILED: - return "VK_ERROR_INITIALIZATION_FAILED"; - case VkResult::VK_ERROR_DEVICE_LOST: - return "VK_ERROR_DEVICE_LOST"; - case VkResult::VK_ERROR_MEMORY_MAP_FAILED: - return "VK_ERROR_MEMORY_MAP_FAILED"; - case VkResult::VK_ERROR_LAYER_NOT_PRESENT: - return "VK_ERROR_LAYER_NOT_PRESENT"; - case VkResult::VK_ERROR_EXTENSION_NOT_PRESENT: - return "VK_ERROR_EXTENSION_NOT_PRESENT"; - case VkResult::VK_ERROR_FEATURE_NOT_PRESENT: - return "VK_ERROR_FEATURE_NOT_PRESENT"; - case VkResult::VK_ERROR_INCOMPATIBLE_DRIVER: - return "VK_ERROR_INCOMPATIBLE_DRIVER"; - case VkResult::VK_ERROR_TOO_MANY_OBJECTS: - return "VK_ERROR_TOO_MANY_OBJECTS"; - case VkResult::VK_ERROR_FORMAT_NOT_SUPPORTED: - return "VK_ERROR_FORMAT_NOT_SUPPORTED"; - case VkResult::VK_ERROR_FRAGMENTED_POOL: - return "VK_ERROR_FRAGMENTED_POOL"; - case VkResult::VK_ERROR_OUT_OF_POOL_MEMORY: - return "VK_ERROR_OUT_OF_POOL_MEMORY"; - case VkResult::VK_ERROR_INVALID_EXTERNAL_HANDLE: - return "VK_ERROR_INVALID_EXTERNAL_HANDLE"; - case VkResult::VK_ERROR_SURFACE_LOST_KHR: - return "VK_ERROR_SURFACE_LOST_KHR"; - case VkResult::VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: - return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; - case VkResult::VK_SUBOPTIMAL_KHR: - return "VK_SUBOPTIMAL_KHR"; - case VkResult::VK_ERROR_OUT_OF_DATE_KHR: - return "VK_ERROR_OUT_OF_DATE_KHR"; - case VkResult::VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: - return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; - case VkResult::VK_ERROR_VALIDATION_FAILED_EXT: - return "VK_ERROR_VALIDATION_FAILED_EXT"; - case VkResult::VK_ERROR_INVALID_SHADER_NV: - return "VK_ERROR_INVALID_SHADER_NV"; - case VkResult::VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR: - return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR"; - case VkResult::VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR: - return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR"; - case VkResult::VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR: - return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR"; - case VkResult::VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR: - return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR"; - case VkResult::VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR: - return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR"; - case VkResult::VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR: - return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR"; - case VkResult::VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: - return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"; - case VkResult::VK_ERROR_FRAGMENTATION_EXT: - return "VK_ERROR_FRAGMENTATION_EXT"; - case VkResult::VK_ERROR_NOT_PERMITTED_EXT: - return "VK_ERROR_NOT_PERMITTED_EXT"; - case VkResult::VK_ERROR_INVALID_DEVICE_ADDRESS_EXT: - return "VK_ERROR_INVALID_DEVICE_ADDRESS_EXT"; - case VkResult::VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: - return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"; - case VkResult::VK_ERROR_UNKNOWN: - return "VK_ERROR_UNKNOWN"; - case VkResult::VK_THREAD_IDLE_KHR: - return "VK_THREAD_IDLE_KHR"; - case VkResult::VK_THREAD_DONE_KHR: - return "VK_THREAD_DONE_KHR"; - case VkResult::VK_OPERATION_DEFERRED_KHR: - return "VK_OPERATION_DEFERRED_KHR"; - case VkResult::VK_OPERATION_NOT_DEFERRED_KHR: - return "VK_OPERATION_NOT_DEFERRED_KHR"; - case VkResult::VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR: - return "VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR"; - case VkResult::VK_PIPELINE_COMPILE_REQUIRED_EXT: - return "VK_PIPELINE_COMPILE_REQUIRED_EXT"; - case VkResult::VK_RESULT_MAX_ENUM: - return "VK_RESULT_MAX_ENUM"; - case VkResult::VK_ERROR_COMPRESSION_EXHAUSTED_EXT: - return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT"; - case VkResult::VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT: - return "VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT"; - } - return "Unknown"; + return string_VkResult(result); } void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept { @@ -1067,7 +966,7 @@ u32 AvailableVersion(const InstanceDispatch& dld) noexcept { u32 version; if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) { LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1", - ToString(result)); + string_VkResult(result)); return VK_API_VERSION_1_1; } return version; diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index a0c70797f..757f3c8af 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -125,9 +125,6 @@ private: VkResult result; }; -/// Converts a VkResult enum into a rodata string -const char* ToString(VkResult) noexcept; - /// Throws a Vulkan exception if result is not success. inline void Check(VkResult result) { if (result != VK_SUCCESS) { diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 93b03b917..76f06da12 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -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 @@ -375,8 +378,6 @@ elseif(WIN32) endif() endif() -create_target_directory_groups(yuzu) - target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core) target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets) target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) @@ -472,3 +473,5 @@ endif() if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(yuzu PRIVATE precompiled_headers.h) endif() + +create_target_directory_groups(yuzu) diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index 79538e81c..82d7f6524 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h @@ -24,6 +24,8 @@ class Builder; } class ConfigureAudio : public ConfigurationShared::Tab { + Q_OBJECT + public: explicit ConfigureAudio(const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index a102b4c1f..7bbeac496 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h @@ -24,6 +24,8 @@ class Builder; } class ConfigureCpu : public ConfigurationShared::Tab { + Q_OBJECT + public: explicit ConfigureCpu(const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 2d953f679..ada6526a6 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -25,6 +25,8 @@ class Builder; } class ConfigureGeneral : public ConfigurationShared::Tab { + Q_OBJECT + public: explicit ConfigureGeneral(const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 0836bcb7e..54c931e56 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -224,6 +224,11 @@ void ConfigureGraphics::PopulateVSyncModeSelection(bool use_setting) { } 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); diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index 5c8286836..b92b4496b 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -43,6 +43,8 @@ class Builder; } class ConfigureGraphics : public ConfigurationShared::Tab { + Q_OBJECT + public: explicit ConfigureGraphics( const Core::System& system_, std::vector<VkDeviceInfo::Record>& records, diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index 78b5389c3..82431987e 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h @@ -21,6 +21,8 @@ class Builder; } class ConfigureGraphicsAdvanced : public ConfigurationShared::Tab { + Q_OBJECT + public: explicit ConfigureGraphicsAdvanced( const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, diff --git a/src/yuzu/configuration/configure_linux_tab.cpp b/src/yuzu/configuration/configure_linux_tab.cpp new file mode 100644 index 000000000..ab3d18816 --- /dev/null +++ b/src/yuzu/configuration/configure_linux_tab.cpp @@ -0,0 +1,75 @@ +// 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); +} diff --git a/src/yuzu/configuration/configure_linux_tab.h b/src/yuzu/configuration/configure_linux_tab.h new file mode 100644 index 000000000..2f402079c --- /dev/null +++ b/src/yuzu/configuration/configure_linux_tab.h @@ -0,0 +1,44 @@ +// 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{}; +}; diff --git a/src/yuzu/configuration/configure_linux_tab.ui b/src/yuzu/configuration/configure_linux_tab.ui new file mode 100644 index 000000000..f8e07f581 --- /dev/null +++ b/src/yuzu/configuration/configure_linux_tab.ui @@ -0,0 +1,53 @@ +<?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> diff --git a/src/yuzu/configuration/configure_motion_touch.h b/src/yuzu/configuration/configure_motion_touch.h index 7dcc9318e..a5db0de51 100644 --- a/src/yuzu/configuration/configure_motion_touch.h +++ b/src/yuzu/configuration/configure_motion_touch.h @@ -26,6 +26,7 @@ class ConfigureMotionTouch; /// 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; diff --git a/src/yuzu/configuration/configure_mouse_panning.h b/src/yuzu/configuration/configure_mouse_panning.h index 08c6e1f62..f5e62ee13 100644 --- a/src/yuzu/configuration/configure_mouse_panning.h +++ b/src/yuzu/configuration/configure_mouse_panning.h @@ -16,6 +16,7 @@ class ConfigureMousePanning; class ConfigureMousePanning : public QDialog { Q_OBJECT + public: explicit ConfigureMousePanning(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_, float right_stick_deadzone, float right_stick_range); diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index b274a3321..9d38ab812 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp @@ -33,6 +33,7 @@ #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")); diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index 9daae772c..196cb32e6 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h @@ -32,6 +32,7 @@ class ConfigureCpu; 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; }; diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h index 4334211f9..a01c29dcf 100644 --- a/src/yuzu/configuration/configure_system.h +++ b/src/yuzu/configuration/configure_system.h @@ -27,6 +27,8 @@ class Builder; } class ConfigureSystem : public ConfigurationShared::Tab { + Q_OBJECT + public: explicit ConfigureSystem(Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group, diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index fbeba8813..ebd8fd738 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -28,8 +28,6 @@ add_executable(yuzu-cmd yuzu.rc ) -create_target_directory_groups(yuzu-cmd) - target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common) target_link_libraries(yuzu-cmd PRIVATE glad) if (MSVC) @@ -63,3 +61,5 @@ endif() if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(yuzu-cmd PRIVATE precompiled_headers.h) endif() + +create_target_directory_groups(yuzu-cmd) |