From 68303ed6016da0926df8b62e5a0c55c9b914f927 Mon Sep 17 00:00:00 2001 From: Liam Date: Sat, 6 Jan 2024 21:21:01 -0500 Subject: core: support offline web applet --- src/core/hle/service/am/am_types.h | 7 ++ src/core/hle/service/am/applet.h | 3 + .../hle/service/am/applet_common_functions.cpp | 9 ++ src/core/hle/service/am/applet_common_functions.h | 1 + src/core/hle/service/am/application_proxy.cpp | 2 +- src/core/hle/service/am/common_state_getter.cpp | 23 ++++- src/core/hle/service/am/common_state_getter.h | 1 + src/core/hle/service/am/display_controller.cpp | 64 +++++++++--- src/core/hle/service/am/display_controller.h | 8 +- src/core/hle/service/am/hid_registration.cpp | 6 ++ src/core/hle/service/am/hid_registration.h | 2 + src/core/hle/service/am/library_applet_creator.cpp | 27 ++++- src/core/hle/service/am/library_applet_proxy.cpp | 2 +- .../service/am/library_applet_self_accessor.cpp | 114 ++++++++++++++++++--- .../hle/service/am/library_applet_self_accessor.h | 4 + src/core/hle/service/am/self_controller.cpp | 13 ++- src/core/hle/service/am/self_controller.h | 1 + src/core/hle/service/am/system_applet_proxy.cpp | 2 +- src/core/hle/service/am/system_buffer_manager.cpp | 20 ++++ src/core/hle/service/am/system_buffer_manager.h | 7 ++ src/core/hle/service/am/window_controller.cpp | 35 ++++++- src/core/hle/service/am/window_controller.h | 2 + src/core/hle/service/filesystem/fsp/fsp_srv.cpp | 48 ++++++--- src/core/hle/service/nifm/nifm.cpp | 12 ++- src/core/hle/service/ns/ns.cpp | 67 +++++++++++- src/core/hle/service/ns/ns.h | 15 +++ src/core/hle/service/nvnflinger/nvnflinger.cpp | 10 ++ src/core/hle/service/nvnflinger/nvnflinger.h | 3 + src/core/hle/service/vi/display/vi_display.cpp | 4 +- src/core/hle/service/vi/layer/vi_layer.cpp | 2 +- src/core/hle/service/vi/layer/vi_layer.h | 9 ++ src/yuzu/main.cpp | 5 +- 32 files changed, 470 insertions(+), 58 deletions(-) diff --git a/src/core/hle/service/am/am_types.h b/src/core/hle/service/am/am_types.h index d47028b80..a2b852b12 100644 --- a/src/core/hle/service/am/am_types.h +++ b/src/core/hle/service/am/am_types.h @@ -162,6 +162,13 @@ struct CommonArguments { }; static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size."); +struct AppletIdentityInfo { + AppletId applet_id; + INSERT_PADDING_BYTES(0x4); + u64 application_id; +}; +static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); + using AppletResourceUserId = u64; using ProgramId = u64; diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h index 65bfbc250..bce6f9050 100644 --- a/src/core/hle/service/am/applet.h +++ b/src/core/hle/service/am/applet.h @@ -49,6 +49,9 @@ struct Applet { s32 previous_program_index{-1}; ScreenshotPermission previous_screenshot_permission{ScreenshotPermission::Enable}; + // TODO: some fields above can be AppletIdentityInfo + AppletIdentityInfo screen_shot_identity; + // hid state HidRegistration hid_registration; diff --git a/src/core/hle/service/am/applet_common_functions.cpp b/src/core/hle/service/am/applet_common_functions.cpp index a5c54ce87..130614ae5 100644 --- a/src/core/hle/service/am/applet_common_functions.cpp +++ b/src/core/hle/service/am/applet_common_functions.cpp @@ -31,6 +31,7 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_, {90, nullptr, "OpenNamedChannelAsParent"}, {91, nullptr, "OpenNamedChannelAsChild"}, {100, nullptr, "SetApplicationCoreUsageMode"}, + {300, &IAppletCommonFunctions::GetCurrentApplicationId, "GetCurrentApplicationId"}, }; // clang-format on @@ -51,4 +52,12 @@ void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) rb.Push(ResultSuccess); } +void IAppletCommonFunctions::GetCurrentApplicationId(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(system.GetApplicationProcessProgramID() & ~0xFFFULL); +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_common_functions.h b/src/core/hle/service/am/applet_common_functions.h index 229555669..b86adf5cb 100644 --- a/src/core/hle/service/am/applet_common_functions.h +++ b/src/core/hle/service/am/applet_common_functions.h @@ -16,6 +16,7 @@ public: private: void SetCpuBoostRequestPriority(HLERequestContext& ctx); + void GetCurrentApplicationId(HLERequestContext& ctx); const std::shared_ptr applet; }; diff --git a/src/core/hle/service/am/application_proxy.cpp b/src/core/hle/service/am/application_proxy.cpp index 99e97f4bc..a6fd6d37f 100644 --- a/src/core/hle/service/am/application_proxy.cpp +++ b/src/core/hle/service/am/application_proxy.cpp @@ -53,7 +53,7 @@ void IApplicationProxy::GetDisplayController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/common_state_getter.cpp b/src/core/hle/service/am/common_state_getter.cpp index 77f3fd868..937ac0beb 100644 --- a/src/core/hle/service/am/common_state_getter.cpp +++ b/src/core/hle/service/am/common_state_getter.cpp @@ -60,7 +60,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr current_applet = applet; + std::vector result; + + const size_t count = ctx.GetWriteBufferNumElements(); + size_t i; + + for (i = 0; i < count && current_applet != nullptr; i++) { + result.push_back(current_applet->applet_id); + current_applet = current_applet->caller_applet.lock(); + } + + ctx.WriteBuffer(result); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast(i)); +} + void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); diff --git a/src/core/hle/service/am/common_state_getter.h b/src/core/hle/service/am/common_state_getter.h index 643ca4dc5..bf652790c 100644 --- a/src/core/hle/service/am/common_state_getter.h +++ b/src/core/hle/service/am/common_state_getter.h @@ -67,6 +67,7 @@ private: void SetCpuBoostMode(HLERequestContext& ctx); void GetBuiltInDisplayType(HLERequestContext& ctx); void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx); + void GetAppletLaunchedHistory(HLERequestContext& ctx); void GetSettingsPlatformRegion(HLERequestContext& ctx); void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx); diff --git a/src/core/hle/service/am/display_controller.cpp b/src/core/hle/service/am/display_controller.cpp index d4d3d60e7..4d6858348 100644 --- a/src/core/hle/service/am/display_controller.cpp +++ b/src/core/hle/service/am/display_controller.cpp @@ -1,13 +1,23 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/am/applet.h" #include "core/hle/service/am/display_controller.h" #include "core/hle/service/ipc_helpers.h" namespace Service::AM { -IDisplayController::IDisplayController(Core::System& system_) - : ServiceFramework{system_, "IDisplayController"} { +namespace { +struct OutputParameters { + bool was_written; + s32 fbshare_layer_index; +}; + +static_assert(sizeof(OutputParameters) == 8, "OutputParameters has wrong size"); +} // namespace + +IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr applet_) + : ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetLastForegroundCaptureImage"}, @@ -31,8 +41,8 @@ IDisplayController::IDisplayController(Core::System& system_) {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, {20, nullptr, "ClearCaptureBuffer"}, {21, nullptr, "ClearAppletTransitionBuffer"}, - {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"}, - {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, + {22, &IDisplayController::AcquireLastApplicationCaptureSharedBuffer, "AcquireLastApplicationCaptureSharedBuffer"}, + {23, &IDisplayController::ReleaseLastApplicationCaptureSharedBuffer, "ReleaseLastApplicationCaptureSharedBuffer"}, {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"}, {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"}, {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"}, @@ -49,10 +59,13 @@ IDisplayController::~IDisplayController() = default; void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + OutputParameters params{}; + const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( + ¶ms.was_written, ¶ms.fbshare_layer_index); + IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(1u); - rb.Push(1); + rb.Push(res); + rb.PushRaw(params); } void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { @@ -62,13 +75,35 @@ void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { rb.Push(ResultSuccess); } -void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { +void IDisplayController::AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + OutputParameters params{}; + const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( + ¶ms.was_written, ¶ms.fbshare_layer_index); + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(res); + rb.PushRaw(params); +} + +void IDisplayController::ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); - rb.Push(1U); - rb.Push(1); +} + +void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + OutputParameters params{}; + const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( + ¶ms.was_written, ¶ms.fbshare_layer_index); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(res); + rb.PushRaw(params); } void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { @@ -81,10 +116,13 @@ void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestCont void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + OutputParameters params{}; + const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( + ¶ms.was_written, ¶ms.fbshare_layer_index); + IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(1U); - rb.Push(1); + rb.Push(res); + rb.PushRaw(params); } void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/display_controller.h b/src/core/hle/service/am/display_controller.h index 32f819294..75172580c 100644 --- a/src/core/hle/service/am/display_controller.h +++ b/src/core/hle/service/am/display_controller.h @@ -7,9 +7,11 @@ namespace Service::AM { +struct Applet; + class IDisplayController final : public ServiceFramework { public: - explicit IDisplayController(Core::System& system_); + explicit IDisplayController(Core::System& system_, std::shared_ptr applet_); ~IDisplayController() override; private: @@ -19,6 +21,10 @@ private: void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); + void AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx); + void ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx); + + const std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/hid_registration.cpp b/src/core/hle/service/am/hid_registration.cpp index b9426f7b6..8ed49bac1 100644 --- a/src/core/hle/service/am/hid_registration.cpp +++ b/src/core/hle/service/am/hid_registration.cpp @@ -26,4 +26,10 @@ HidRegistration::~HidRegistration() { } } +void HidRegistration::EnableAppletToGetInput(bool enable) { + if (m_process.IsInitialized()) { + m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable); + } +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/hid_registration.h b/src/core/hle/service/am/hid_registration.h index 8a732349c..67cd84961 100644 --- a/src/core/hle/service/am/hid_registration.h +++ b/src/core/hle/service/am/hid_registration.h @@ -22,6 +22,8 @@ public: explicit HidRegistration(Core::System& system, Process& process); ~HidRegistration(); + void EnableAppletToGetInput(bool enable); + private: Process& m_process; std::shared_ptr m_hid_server; diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp index e69764670..47bab7528 100644 --- a/src/core/hle/service/am/library_applet_creator.cpp +++ b/src/core/hle/service/am/library_applet_creator.cpp @@ -84,10 +84,29 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) { applet->type = AppletType::LibraryApplet; applet->library_applet_mode = mode; - // Library applet should be foreground - applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); - applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); - applet->focus_state = FocusState::InFocus; + // Set focus state + switch (mode) { + case LibraryAppletMode::AllForeground: + case LibraryAppletMode::NoUI: + applet->focus_state = FocusState::InFocus; + applet->hid_registration.EnableAppletToGetInput(true); + applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); + applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); + break; + case LibraryAppletMode::AllForegroundInitiallyHidden: + applet->system_buffer_manager.SetWindowVisibility(false); + applet->focus_state = FocusState::NotInFocus; + applet->hid_registration.EnableAppletToGetInput(false); + applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); + break; + case LibraryAppletMode::Background: + case LibraryAppletMode::BackgroundIndirectDisplay: + default: + applet->focus_state = FocusState::Background; + applet->hid_registration.EnableAppletToGetInput(true); + applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); + break; + } auto broker = std::make_shared(system); applet->caller_applet = caller_applet; diff --git a/src/core/hle/service/am/library_applet_proxy.cpp b/src/core/hle/service/am/library_applet_proxy.cpp index 1d88dd78c..d6108fba3 100644 --- a/src/core/hle/service/am/library_applet_proxy.cpp +++ b/src/core/hle/service/am/library_applet_proxy.cpp @@ -81,7 +81,7 @@ void ILibraryAppletProxy::GetDisplayController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/library_applet_self_accessor.cpp b/src/core/hle/service/am/library_applet_self_accessor.cpp index bc66bcb6b..b560f580b 100644 --- a/src/core/hle/service/am/library_applet_self_accessor.cpp +++ b/src/core/hle/service/am/library_applet_self_accessor.cpp @@ -3,6 +3,9 @@ #include "common/scope_exit.h" #include "core/core_timing.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/registered_cache.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/am_results.h" #include "core/hle/service/am/applet_data_broker.h" @@ -15,25 +18,20 @@ #include "core/hle/service/am/library_applet_self_accessor.h" #include "core/hle/service/am/storage.h" #include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/ns/ns.h" +#include "core/hle/service/sm/sm.h" #include "hid_core/hid_types.h" namespace Service::AM { namespace { -struct AppletIdentityInfo { - AppletId applet_id; - INSERT_PADDING_BYTES(0x4); - u64 application_id; -}; -static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); - AppletIdentityInfo GetCallerIdentity(std::shared_ptr applet) { if (const auto caller_applet = applet->caller_applet.lock(); caller_applet) { // TODO: is this actually the application ID? return { - .applet_id = applet->applet_id, - .application_id = applet->program_id, + .applet_id = caller_applet->applet_id, + .application_id = caller_applet->program_id, }; } else { return { @@ -60,7 +58,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_, {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"}, - {13, nullptr, "CanUseApplicationCore"}, + {13, &ILibraryAppletSelfAccessor::CanUseApplicationCore, "CanUseApplicationCore"}, {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"}, {15, nullptr, "GetMainAppletApplicationControlProperty"}, {16, nullptr, "GetMainAppletStorageId"}, @@ -74,8 +72,8 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_, {40, nullptr, "GetIndirectLayerProducerHandle"}, {50, nullptr, "ReportVisibleError"}, {51, nullptr, "ReportVisibleErrorWithErrorContext"}, - {60, nullptr, "GetMainAppletApplicationDesiredLanguage"}, - {70, nullptr, "GetCurrentApplicationId"}, + {60, &ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage, "GetMainAppletApplicationDesiredLanguage"}, + {70, &ILibraryAppletSelfAccessor::GetCurrentApplicationId, "GetCurrentApplicationId"}, {80, nullptr, "RequestExitToSelf"}, {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, {100, nullptr, "CreateGameMovieTrimmer"}, @@ -86,6 +84,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_, {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, {140, nullptr, "SetApplicationMemoryReservation"}, {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"}, + {160, &ILibraryAppletSelfAccessor::Cmd160, "Cmd160"}, }; // clang-format on RegisterHandlers(functions); @@ -202,6 +201,15 @@ void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ct rb.PushRaw(applet_info); } +void ILibraryAppletSelfAccessor::CanUseApplicationCore(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // TODO: This appears to read the NPDM from state and check the core mask of the applet. + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); +} + void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); @@ -218,6 +226,80 @@ void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& c rb.Push(0); } +void ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx) { + // FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage + auto identity = GetCallerIdentity(applet); + + // TODO(bunnei): This should be configurable + LOG_DEBUG(Service_AM, "called"); + + // Get supported languages from NACP, if possible + // Default to 0 (all languages supported) + u32 supported_languages = 0; + + const auto res = [this, identity] { + const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(), + system.GetContentProvider()}; + auto metadata = pm.GetControlMetadata(); + if (metadata.first != nullptr) { + return metadata; + } + + const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id), + system.GetFileSystemController(), + system.GetContentProvider()}; + return pm_update.GetControlMetadata(); + }(); + + if (res.first != nullptr) { + supported_languages = res.first->GetSupportedLanguages(); + } + + // Call IApplicationManagerInterface implementation. + auto& service_manager = system.ServiceManager(); + auto ns_am2 = service_manager.GetService("ns:am2"); + auto app_man = ns_am2->GetApplicationManagerInterface(); + + // Get desired application language + u8 desired_language{}; + const auto res_lang = + app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); + if (res_lang != ResultSuccess) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res_lang); + return; + } + + // Convert to settings language code. + u64 language_code{}; + const auto res_code = + app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); + if (res_code != ResultSuccess) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res_code); + return; + } + + LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(language_code); +} + +void ILibraryAppletSelfAccessor::GetCurrentApplicationId(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + u64 application_id = 0; + if (auto caller_applet = applet->caller_applet.lock(); caller_applet) { + application_id = caller_applet->program_id; + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(application_id); +} + void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) { const Service::Account::ProfileManager manager{}; bool is_empty{true}; @@ -245,4 +327,12 @@ void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext rb.Push(0); } +void ILibraryAppletSelfAccessor::Cmd160(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(0); +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_self_accessor.h b/src/core/hle/service/am/library_applet_self_accessor.h index 596cea0df..8717a989a 100644 --- a/src/core/hle/service/am/library_applet_self_accessor.h +++ b/src/core/hle/service/am/library_applet_self_accessor.h @@ -27,11 +27,15 @@ private: void GetPopInteractiveInDataEvent(HLERequestContext& ctx); void GetLibraryAppletInfo(HLERequestContext& ctx); void GetMainAppletIdentityInfo(HLERequestContext& ctx); + void CanUseApplicationCore(HLERequestContext& ctx); void ExitProcessAndReturn(HLERequestContext& ctx); void GetCallerAppletIdentityInfo(HLERequestContext& ctx); void GetDesirableKeyboardLayout(HLERequestContext& ctx); + void GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx); + void GetCurrentApplicationId(HLERequestContext& ctx); void GetMainAppletAvailableUsers(HLERequestContext& ctx); void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx); + void Cmd160(HLERequestContext& ctx); const std::shared_ptr applet; const std::shared_ptr broker; diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp index 3ac967b4d..0289f5cf1 100644 --- a/src/core/hle/service/am/self_controller.cpp +++ b/src/core/hle/service/am/self_controller.cpp @@ -30,7 +30,7 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"}, {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, - {15, nullptr, "SetScreenShotAppletIdentityInfo"}, + {15, &ISelfController::SetScreenShotAppletIdentityInfo, "SetScreenShotAppletIdentityInfo"}, {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, {17, nullptr, "SetControllerFirmwareUpdateSection"}, {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, @@ -207,6 +207,17 @@ void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void ISelfController::SetScreenShotAppletIdentityInfo(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::RequestParser rp{ctx}; + std::scoped_lock lk{applet->lock}; + applet->screen_shot_identity = rp.PopRaw(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h index 6e6975264..a63bc2e74 100644 --- a/src/core/hle/service/am/self_controller.h +++ b/src/core/hle/service/am/self_controller.h @@ -28,6 +28,7 @@ private: void SetPerformanceModeChangedNotification(HLERequestContext& ctx); void SetFocusHandlingMode(HLERequestContext& ctx); void SetRestartMessageEnabled(HLERequestContext& ctx); + void SetScreenShotAppletIdentityInfo(HLERequestContext& ctx); void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); void SetAlbumImageOrientation(HLERequestContext& ctx); void IsSystemBufferSharingEnabled(HLERequestContext& ctx); diff --git a/src/core/hle/service/am/system_applet_proxy.cpp b/src/core/hle/service/am/system_applet_proxy.cpp index e3013271b..38643408e 100644 --- a/src/core/hle/service/am/system_applet_proxy.cpp +++ b/src/core/hle/service/am/system_applet_proxy.cpp @@ -82,7 +82,7 @@ void ISystemAppletProxy::GetDisplayController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp index 7211ef488..60a9afc9d 100644 --- a/src/core/hle/service/am/system_buffer_manager.cpp +++ b/src/core/hle/service/am/system_buffer_manager.cpp @@ -4,6 +4,7 @@ #include "core/hle/service/am/system_buffer_manager.h" #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" #include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/vi/vi_results.h" namespace Service::AM { @@ -41,9 +42,28 @@ bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel: if (res.IsSuccess()) { m_buffer_sharing_enabled = true; + m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); } return m_buffer_sharing_enabled; } +void SystemBufferManager::SetWindowVisibility(bool visible) { + if (m_visible == visible) { + return; + } + + m_visible = visible; + + if (m_nvnflinger) { + m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); + } +} + +Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, + s32* out_fbshare_layer_index) { + // TODO + R_SUCCEED(); +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/system_buffer_manager.h b/src/core/hle/service/am/system_buffer_manager.h index c60d73416..98c3cf055 100644 --- a/src/core/hle/service/am/system_buffer_manager.h +++ b/src/core/hle/service/am/system_buffer_manager.h @@ -18,6 +18,8 @@ namespace Service::Nvnflinger { class Nvnflinger; } +union Result; + namespace Service::AM { class SystemBufferManager { @@ -33,10 +35,15 @@ public: *out_system_shared_layer_id = m_system_shared_layer_id; } + void SetWindowVisibility(bool visible); + + Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index); + private: Kernel::KProcess* m_process{}; Nvnflinger::Nvnflinger* m_nvnflinger{}; bool m_buffer_sharing_enabled{}; + bool m_visible{true}; u64 m_system_shared_buffer_id{}; u64 m_system_shared_layer_id{}; }; diff --git a/src/core/hle/service/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp index 430ca180b..f00957f83 100644 --- a/src/core/hle/service/am/window_controller.cpp +++ b/src/core/hle/service/am/window_controller.cpp @@ -17,8 +17,8 @@ IWindowController::IWindowController(Core::System& system_, std::shared_ptr(); + + applet->system_buffer_manager.SetWindowVisibility(visible); + applet->hid_registration.EnableAppletToGetInput(visible); + + if (visible) { + applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); + applet->focus_state = FocusState::InFocus; + } else { + applet->focus_state = FocusState::NotInFocus; + } + applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IWindowController::SetAppletGpuTimeSlice(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto time_slice = rp.Pop(); + + LOG_WARNING(Service_AM, "(STUBBED) called, time_slice={}", time_slice); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/window_controller.h b/src/core/hle/service/am/window_controller.h index d97f93737..a28219abe 100644 --- a/src/core/hle/service/am/window_controller.h +++ b/src/core/hle/service/am/window_controller.h @@ -18,6 +18,8 @@ private: void GetAppletResourceUserId(HLERequestContext& ctx); void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx); void AcquireForegroundRights(HLERequestContext& ctx); + void SetAppletWindowVisibility(HLERequestContext& ctx); + void SetAppletGpuTimeSlice(HLERequestContext& ctx); const std::shared_ptr applet; }; diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp index 2be72b021..5fe534c73 100644 --- a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp @@ -15,11 +15,13 @@ #include "common/settings.h" #include "common/string_util.h" #include "core/core.h" +#include "core/file_sys/content_archive.h" #include "core/file_sys/errors.h" #include "core/file_sys/fs_directory.h" #include "core/file_sys/fs_filesystem.h" #include "core/file_sys/nca_metadata.h" #include "core/file_sys/patch_manager.h" +#include "core/file_sys/romfs.h" #include "core/file_sys/romfs_factory.h" #include "core/file_sys/savedata_factory.h" #include "core/file_sys/system_archive/system_archive.h" @@ -33,18 +35,20 @@ #include "core/hle/service/filesystem/save_data_controller.h" #include "core/hle/service/hle_ipc.h" #include "core/hle/service/ipc_helpers.h" +#include "core/loader/loader.h" #include "core/reporter.h" namespace Service::FileSystem { -enum class FileSystemType : u8 { - Invalid0 = 0, - Invalid1 = 1, +enum class FileSystemProxyType : u8 { + Code = 0, + Rom = 1, Logo = 2, - ContentControl = 3, - ContentManual = 4, - ContentMeta = 5, - ContentData = 6, - ApplicationPackage = 7, + Control = 3, + Manual = 4, + Meta = 5, + Data = 6, + Package = 7, + RegisteredUpdate = 8, }; class ISaveDataInfoReader final : public ServiceFramework { @@ -357,12 +361,30 @@ void FSP_SRV::SetCurrentProcess(HLERequestContext& ctx) { void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto type = rp.PopRaw(); - const auto title_id = rp.PopRaw(); - LOG_WARNING(Service_FS, "(STUBBED) called with type={}, title_id={:016X}", type, title_id); + struct InputParameters { + FileSystemProxyType type; + u64 program_id; + }; + static_assert(sizeof(InputParameters) == 0x10, "InputParameters has wrong size"); + + const auto params = rp.PopRaw(); + LOG_ERROR(Service_FS, "(STUBBED) called with type={}, program_id={:016X}", params.type, + params.program_id); + + // FIXME: many issues with this + ASSERT(params.type == FileSystemProxyType::Manual); + const auto manual_romfs = romfs_controller->OpenPatchedRomFS( + params.program_id, FileSys::ContentRecordType::HtmlDocument); - IPC::ResponseBuilder rb{ctx, 2, 0, 0}; - rb.Push(ResultUnknown); + ASSERT(manual_romfs != nullptr); + + const auto extracted_romfs = FileSys::ExtractRomFS(manual_romfs); + ASSERT(extracted_romfs != nullptr); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(system, extracted_romfs, + SizeGetter::FromStorageId(fsc, FileSys::StorageId::NandUser)); } void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 22dc55a6d..8e3224f73 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -185,7 +185,7 @@ public: {3, &IRequest::Cancel, "Cancel"}, {4, &IRequest::Submit, "Submit"}, {5, nullptr, "SetRequirement"}, - {6, nullptr, "SetRequirementPreset"}, + {6, &IRequest::SetRequirementPreset, "SetRequirementPreset"}, {8, nullptr, "SetPriority"}, {9, nullptr, "SetNetworkProfileId"}, {10, nullptr, "SetRejectable"}, @@ -237,6 +237,16 @@ private: rb.PushEnum(state); } + void SetRequirementPreset(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto param_1 = rp.Pop(); + + LOG_WARNING(Service_NIFM, "(STUBBED) called, param_1={}", param_1); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + void GetResult(HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "(STUBBED) called"); diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 2258ee609..19c3ff01b 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -3,6 +3,7 @@ #include "common/logging/log.h" #include "common/settings.h" +#include "core/arm/debug.h" #include "core/core.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" @@ -544,8 +545,8 @@ IDocumentInterface::IDocumentInterface(Core::System& system_) // clang-format off static const FunctionInfo functions[] = { {21, nullptr, "GetApplicationContentPath"}, - {23, nullptr, "ResolveApplicationContentPath"}, - {93, nullptr, "GetRunningApplicationProgramId"}, + {23, &IDocumentInterface::ResolveApplicationContentPath, "ResolveApplicationContentPath"}, + {92, &IDocumentInterface::GetRunningApplicationProgramId, "GetRunningApplicationProgramId"}, }; // clang-format on @@ -554,6 +555,32 @@ IDocumentInterface::IDocumentInterface(Core::System& system_) IDocumentInterface::~IDocumentInterface() = default; +void IDocumentInterface::ResolveApplicationContentPath(HLERequestContext& ctx) { + struct ContentPath { + u8 file_system_proxy_type; + u64 program_id; + }; + static_assert(sizeof(ContentPath) == 0x10, "ContentPath has wrong size"); + + IPC::RequestParser rp{ctx}; + auto content_path = rp.PopRaw(); + LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}", + content_path.file_system_proxy_type, content_path.program_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IDocumentInterface::GetRunningApplicationProgramId(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto caller_program_id = rp.PopRaw(); + LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(system.GetApplicationProcessProgramID()); +} + IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_) : ServiceFramework{system_, "IDownloadTaskInterface"} { // clang-format off @@ -613,6 +640,40 @@ IFactoryResetInterface::IFactoryResetInterface(Core::System& system_) IFactoryResetInterface::~IFactoryResetInterface() = default; +IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_) + : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} { + static const FunctionInfo functions[] = { + {0, &IReadOnlyApplicationRecordInterface::HasApplicationRecord, "HasApplicationRecord"}, + {1, nullptr, "NotifyApplicationFailure"}, + {2, &IReadOnlyApplicationRecordInterface::IsDataCorruptedResult, "IsDataCorruptedResult"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default; + +void IReadOnlyApplicationRecordInterface::HasApplicationRecord(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 program_id = rp.PopRaw(); + LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:X}", program_id); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(1); +} + +void IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto result = rp.PopRaw(); + LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue()); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); +} + IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface( Core::System& system_) : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} { @@ -663,7 +724,7 @@ NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name static const FunctionInfo functions[] = { {7988, nullptr, "GetDynamicRightsInterface"}, {7989, &NS::PushInterface, "GetReadOnlyApplicationControlDataInterface"}, - {7991, nullptr, "GetReadOnlyApplicationRecordInterface"}, + {7991, &NS::PushInterface, "GetReadOnlyApplicationRecordInterface"}, {7992, &NS::PushInterface, "GetECommerceInterface"}, {7993, &NS::PushInterface, "GetApplicationVersionInterface"}, {7994, &NS::PushInterface, "GetFactoryResetInterface"}, diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 34d2a45dc..9ee306ef9 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -58,6 +58,10 @@ class IDocumentInterface final : public ServiceFramework { public: explicit IDocumentInterface(Core::System& system_); ~IDocumentInterface() override; + +private: + void ResolveApplicationContentPath(HLERequestContext& ctx); + void GetRunningApplicationProgramId(HLERequestContext& ctx); }; class IDownloadTaskInterface final : public ServiceFramework { @@ -78,6 +82,17 @@ public: ~IFactoryResetInterface() override; }; +class IReadOnlyApplicationRecordInterface final + : public ServiceFramework { +public: + explicit IReadOnlyApplicationRecordInterface(Core::System& system_); + ~IReadOnlyApplicationRecordInterface() override; + +private: + void HasApplicationRecord(HLERequestContext& ctx); + void IsDataCorruptedResult(HLERequestContext& ctx); +}; + class IReadOnlyApplicationControlDataInterface final : public ServiceFramework { public: diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 71d6fdb0c..51133853c 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp @@ -198,6 +198,16 @@ bool Nvnflinger::CloseLayer(u64 layer_id) { return false; } +void Nvnflinger::SetLayerVisibility(u64 layer_id, bool visible) { + const auto lock_guard = Lock(); + + for (auto& display : displays) { + if (auto* layer = display.FindLayer(layer_id); layer) { + layer->SetVisibility(visible); + } + } +} + void Nvnflinger::DestroyLayer(u64 layer_id) { const auto lock_guard = Lock(); diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index a60e0ae6b..369439142 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -79,6 +79,9 @@ public: /// Closes a layer on all displays for the given layer ID. bool CloseLayer(u64 layer_id); + /// Makes a layer visible on all displays for the given layer ID. + void SetLayerVisibility(u64 layer_id, bool visible); + /// Destroys the given layer ID. void DestroyLayer(u64 layer_id); diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 725311c53..dab1905cc 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -53,7 +53,7 @@ Display::~Display() { Layer& Display::GetLayer(std::size_t index) { size_t i = 0; for (auto& layer : layers) { - if (!layer->IsOpen()) { + if (!layer->IsOpen() || !layer->IsVisible()) { continue; } @@ -68,7 +68,7 @@ Layer& Display::GetLayer(std::size_t index) { } size_t Display::GetNumLayers() const { - return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); }); + return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen() && l->IsVisible(); }); } Kernel::KReadableEvent* Display::GetVSyncEvent() { diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp index 04e52a23b..493bd6e9e 100644 --- a/src/core/hle/service/vi/layer/vi_layer.cpp +++ b/src/core/hle/service/vi/layer/vi_layer.cpp @@ -9,7 +9,7 @@ Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, android::BufferQueueProducer& binder_, std::shared_ptr&& consumer_) : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, - consumer{std::move(consumer_)}, open{false} {} + consumer{std::move(consumer_)}, open{false}, visible{true} {} Layer::~Layer() = default; diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h index f95e2dc71..b4b031ee7 100644 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ b/src/core/hle/service/vi/layer/vi_layer.h @@ -72,6 +72,14 @@ public: return core; } + bool IsVisible() const { + return visible; + } + + void SetVisibility(bool v) { + visible = v; + } + bool IsOpen() const { return open; } @@ -91,6 +99,7 @@ private: android::BufferQueueProducer& binder; std::shared_ptr consumer; bool open; + bool visible; }; } // namespace Service::VI diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 4e5c4da53..303d84a1f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -4931,7 +4931,10 @@ void GMainWindow::changeEvent(QEvent* event) { } Service::AM::FrontendAppletParameters GMainWindow::ApplicationAppletParameters() { - return Service::AM::FrontendAppletParameters{}; + return Service::AM::FrontendAppletParameters{ + .applet_id = Service::AM::AppletId::Application, + .applet_type = Service::AM::AppletType::Application, + }; } Service::AM::FrontendAppletParameters GMainWindow::LibraryAppletParameters( -- cgit v1.2.3