From 182137a9a4b09c8188d2cbffa312550c5dc83641 Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 2 Jan 2024 18:29:03 -0500 Subject: [PATCH] am: migrate global state to per-applet state structure --- src/core/core.cpp | 9 +- src/core/core.h | 3 +- src/core/hle/kernel/kernel.cpp | 30 +- src/core/hle/service/am/am.cpp | 10 +- src/core/hle/service/am/am_results.h | 1 + src/core/hle/service/am/applet_ae.cpp | 72 ++-- src/core/hle/service/am/applet_ae.h | 10 +- .../service/am/applet_common_functions.cpp | 11 +- .../hle/service/am/applet_common_functions.h | 6 +- src/core/hle/service/am/applet_manager.cpp | 2 +- .../hle/service/am/applet_message_queue.cpp | 7 +- .../hle/service/am/applet_message_queue.h | 1 + src/core/hle/service/am/applet_oe.cpp | 35 +- src/core/hle/service/am/applet_oe.h | 10 +- .../hle/service/am/application_functions.cpp | 156 ++++---- .../hle/service/am/application_functions.h | 13 +- src/core/hle/service/am/application_proxy.cpp | 21 +- src/core/hle/service/am/application_proxy.h | 9 +- .../hle/service/am/common_state_getter.cpp | 51 +-- src/core/hle/service/am/common_state_getter.h | 10 +- src/core/hle/service/am/frontend/applets.cpp | 20 +- src/core/hle/service/am/frontend/applets.h | 1 - .../service/am/library_applet_accessor.cpp | 80 ++--- .../hle/service/am/library_applet_accessor.h | 13 +- .../hle/service/am/library_applet_creator.cpp | 115 +++++- .../hle/service/am/library_applet_creator.h | 6 +- .../hle/service/am/library_applet_proxy.cpp | 23 +- .../hle/service/am/library_applet_proxy.h | 9 +- .../am/library_applet_self_accessor.cpp | 336 ++++++------------ .../service/am/library_applet_self_accessor.h | 18 +- .../service/am/process_winding_controller.cpp | 35 +- .../service/am/process_winding_controller.h | 6 +- src/core/hle/service/am/self_controller.cpp | 187 +++++----- src/core/hle/service/am/self_controller.h | 25 +- .../hle/service/am/system_applet_proxy.cpp | 19 +- src/core/hle/service/am/system_applet_proxy.h | 8 +- src/core/hle/service/am/window_controller.cpp | 18 +- src/core/hle/service/am/window_controller.h | 6 +- src/core/hle/service/vi/vi.cpp | 8 + src/yuzu/configuration/configure_input.cpp | 17 +- src/yuzu/main.cpp | 28 +- 41 files changed, 692 insertions(+), 753 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 8c04685a5d..435ef67934 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -392,6 +392,7 @@ struct System::Impl { // All threads are started, begin main process execution, now that we're in the clear. main_process->Run(load_parameters->main_thread_priority, load_parameters->main_thread_stack_size); + main_process->Close(); if (Settings::values.gamecard_inserted) { if (Settings::values.gamecard_current_game) { @@ -886,10 +887,6 @@ void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set impl->frontend_applets.SetFrontendAppletSet(std::move(set)); } -void System::SetDefaultAppletFrontendSet() { - impl->frontend_applets.SetDefaultAppletFrontendSet(); -} - Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() { return impl->frontend_applets; } @@ -898,6 +895,10 @@ const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHold return impl->frontend_applets; } +Service::AM::AppletManager& System::GetAppletManager() { + return impl->applet_manager; +} + void System::SetContentProvider(std::unique_ptr provider) { impl->content_provider = std::move(provider); } diff --git a/src/core/core.h b/src/core/core.h index 97e2d4b50d..90826bd3a1 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -350,12 +350,13 @@ public: u64 main_region_size); void SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set); - void SetDefaultAppletFrontendSet(); [[nodiscard]] Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder(); [[nodiscard]] const Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder() const; + [[nodiscard]] Service::AM::AppletManager& GetAppletManager(); + void SetContentProvider(std::unique_ptr provider); [[nodiscard]] FileSys::ContentProvider& GetContentProvider(); diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f3683cdcc9..34b25be665 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -97,8 +97,14 @@ struct KernelCore::Impl { RegisterHostThread(nullptr); } - void TerminateApplicationProcess() { - application_process.load()->Terminate(); + void TerminateAllProcesses() { + std::scoped_lock lk{process_list_lock}; + for (auto& process : process_list) { + process->Terminate(); + process->Close(); + process = nullptr; + } + process_list.clear(); } void Shutdown() { @@ -107,18 +113,9 @@ struct KernelCore::Impl { CloseServices(); - auto* old_process = application_process.exchange(nullptr); - if (old_process) { - old_process->Close(); - } - - { - std::scoped_lock lk{process_list_lock}; - for (auto* const process : process_list) { - process->Terminate(); - process->Close(); - } - process_list.clear(); + if (application_process) { + application_process->Close(); + application_process = nullptr; } next_object_id = 0; @@ -354,6 +351,7 @@ struct KernelCore::Impl { void MakeApplicationProcess(KProcess* process) { application_process = process; + application_process->Open(); } static inline thread_local u8 host_thread_id = UINT8_MAX; @@ -779,7 +777,7 @@ struct KernelCore::Impl { // Lists all processes that exist in the current session. std::mutex process_list_lock; std::vector process_list; - std::atomic application_process{}; + KProcess* application_process{}; std::unique_ptr global_scheduler_context; std::unique_ptr hardware_timer; @@ -1243,7 +1241,7 @@ void KernelCore::SuspendApplication(bool suspended) { } void KernelCore::ShutdownCores() { - impl->TerminateApplicationProcess(); + impl->TerminateAllProcesses(); KScopedSchedulerLock lk{*this}; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 46bc4f703e..8f90eba34b 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -3,7 +3,6 @@ #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" -#include "core/hle/service/am/applet_message_queue.h" #include "core/hle/service/am/applet_oe.h" #include "core/hle/service/am/idle.h" #include "core/hle/service/am/omm.h" @@ -13,13 +12,12 @@ namespace Service::AM { void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { - auto message_queue = std::make_shared(system); auto server_manager = std::make_unique(system); - server_manager->RegisterNamedService( - "appletAE", std::make_shared(nvnflinger, message_queue, system)); - server_manager->RegisterNamedService( - "appletOE", std::make_shared(nvnflinger, message_queue, system)); + server_manager->RegisterNamedService("appletAE", + std::make_shared(nvnflinger, system)); + server_manager->RegisterNamedService("appletOE", + std::make_shared(nvnflinger, system)); server_manager->RegisterNamedService("idle:sys", std::make_shared(system)); server_manager->RegisterNamedService("omm", std::make_shared(system)); server_manager->RegisterNamedService("spsm", std::make_shared(system)); diff --git a/src/core/hle/service/am/am_results.h b/src/core/hle/service/am/am_results.h index 528b334adb..e82d391adc 100644 --- a/src/core/hle/service/am/am_results.h +++ b/src/core/hle/service/am/am_results.h @@ -10,5 +10,6 @@ namespace Service::AM { constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2}; constexpr Result ResultNoMessages{ErrorModule::AM, 3}; constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; +constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512}; } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index bd9e5f5055..1b715dea6e 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp @@ -2,40 +2,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/am/applet_ae.h" +#include "core/hle/service/am/applet_manager.h" #include "core/hle/service/am/library_applet_proxy.h" #include "core/hle/service/am/system_applet_proxy.h" #include "core/hle/service/ipc_helpers.h" namespace Service::AM { -void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(nvnflinger, msg_queue, system); -} - -void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(nvnflinger, msg_queue, system); -} - -void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(nvnflinger, msg_queue, system); -} - -AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, Core::System& system_) - : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_}, - msg_queue{std::move(msg_queue_)} { +AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_) + : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_} { // clang-format off static const FunctionInfo functions[] = { {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, @@ -54,8 +29,45 @@ AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, AppletAE::~AppletAE() = default; -const std::shared_ptr& AppletAE::GetMessageQueue() const { - return msg_queue; +void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + if (const auto applet = GetAppletFromContext(ctx)) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(nvnflinger, applet, system); + } else { + UNIMPLEMENTED(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + } +} + +void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + if (const auto applet = GetAppletFromContext(ctx)) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(nvnflinger, applet, system); + } else { + UNIMPLEMENTED(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + } +} + +void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + return OpenLibraryAppletProxy(ctx); +} + +std::shared_ptr AppletAE::GetAppletFromContext(HLERequestContext& ctx) { + const auto aruid = ctx.GetPID(); + return system.GetAppletManager().GetByAppletResourceUserId(aruid); } } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h index 538ce2903a..3d7961fa1d 100644 --- a/src/core/hle/service/am/applet_ae.h +++ b/src/core/hle/service/am/applet_ae.h @@ -18,23 +18,21 @@ class Nvnflinger; namespace AM { -class AppletMessageQueue; +struct Applet; class AppletAE final : public ServiceFramework { public: - explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, Core::System& system_); + explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_); ~AppletAE() override; - const std::shared_ptr& GetMessageQueue() const; - private: void OpenSystemAppletProxy(HLERequestContext& ctx); void OpenLibraryAppletProxy(HLERequestContext& ctx); void OpenLibraryAppletProxyOld(HLERequestContext& ctx); + std::shared_ptr GetAppletFromContext(HLERequestContext& ctx); + Nvnflinger::Nvnflinger& nvnflinger; - std::shared_ptr msg_queue; }; } // namespace AM diff --git a/src/core/hle/service/am/applet_common_functions.cpp b/src/core/hle/service/am/applet_common_functions.cpp index 81c01a48ba..a5c54ce878 100644 --- a/src/core/hle/service/am/applet_common_functions.cpp +++ b/src/core/hle/service/am/applet_common_functions.cpp @@ -1,13 +1,15 @@ // 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/applet_common_functions.h" #include "core/hle/service/ipc_helpers.h" namespace Service::AM { -IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_) - : ServiceFramework{system_, "IAppletCommonFunctions"} { +IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_, + std::shared_ptr applet_) + : ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetTerminateResult"}, @@ -40,6 +42,11 @@ IAppletCommonFunctions::~IAppletCommonFunctions() = default; void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + + std::scoped_lock lk{applet->lock}; + applet->cpu_boost_request_priority = rp.Pop(); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } diff --git a/src/core/hle/service/am/applet_common_functions.h b/src/core/hle/service/am/applet_common_functions.h index be87b38206..229555669c 100644 --- a/src/core/hle/service/am/applet_common_functions.h +++ b/src/core/hle/service/am/applet_common_functions.h @@ -7,13 +7,17 @@ namespace Service::AM { +struct Applet; + class IAppletCommonFunctions final : public ServiceFramework { public: - explicit IAppletCommonFunctions(Core::System& system_); + explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr applet_); ~IAppletCommonFunctions() override; private: void SetCpuBoostRequestPriority(HLERequestContext& ctx); + + const std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp index 4aac5dba70..efbd0108c3 100644 --- a/src/core/hle/service/am/applet_manager.cpp +++ b/src/core/hle/service/am/applet_manager.cpp @@ -294,8 +294,8 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters( } // Applet was started by frontend, so it is foreground. - applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); + applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); applet->focus_state = FocusState::InFocus; this->InsertApplet(std::move(applet)); diff --git a/src/core/hle/service/am/applet_message_queue.cpp b/src/core/hle/service/am/applet_message_queue.cpp index e4931031dd..5ed996b70d 100644 --- a/src/core/hle/service/am/applet_message_queue.cpp +++ b/src/core/hle/service/am/applet_message_queue.cpp @@ -26,11 +26,15 @@ Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() { } void AppletMessageQueue::PushMessage(AppletMessage msg) { - messages.push(msg); + { + std::scoped_lock lk{lock}; + messages.push(msg); + } on_new_message->Signal(); } AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { + std::scoped_lock lk{lock}; if (messages.empty()) { on_new_message->Clear(); return AppletMessage::None; @@ -44,6 +48,7 @@ AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { } std::size_t AppletMessageQueue::GetMessageCount() const { + std::scoped_lock lk{lock}; return messages.size(); } diff --git a/src/core/hle/service/am/applet_message_queue.h b/src/core/hle/service/am/applet_message_queue.h index 60145aae9a..5cb236d477 100644 --- a/src/core/hle/service/am/applet_message_queue.h +++ b/src/core/hle/service/am/applet_message_queue.h @@ -69,6 +69,7 @@ private: Kernel::KEvent* on_new_message; Kernel::KEvent* on_operation_mode_changed; + mutable std::mutex lock; std::queue messages; }; diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index f373d11366..56bafd1622 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp @@ -2,24 +2,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/am/am.h" +#include "core/hle/service/am/applet_manager.h" #include "core/hle/service/am/applet_oe.h" #include "core/hle/service/am/application_proxy.h" #include "core/hle/service/ipc_helpers.h" namespace Service::AM { -void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(nvnflinger, msg_queue, system); -} - -AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, Core::System& system_) - : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_}, - msg_queue{std::move(msg_queue_)} { +AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_) + : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_} { static const FunctionInfo functions[] = { {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, }; @@ -28,8 +19,24 @@ AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, AppletOE::~AppletOE() = default; -const std::shared_ptr& AppletOE::GetMessageQueue() const { - return msg_queue; +void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + if (const auto applet = GetAppletFromContext(ctx)) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(nvnflinger, applet, system); + } else { + UNIMPLEMENTED(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + } +} + +std::shared_ptr AppletOE::GetAppletFromContext(HLERequestContext& ctx) { + const auto aruid = ctx.GetPID(); + return system.GetAppletManager().GetByAppletResourceUserId(aruid); } } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index 39eccc4ab5..f2ba1c9242 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h @@ -18,21 +18,19 @@ class Nvnflinger; namespace AM { -class AppletMessageQueue; +struct Applet; class AppletOE final : public ServiceFramework { public: - explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, Core::System& system_); + explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_); ~AppletOE() override; - const std::shared_ptr& GetMessageQueue() const; - private: void OpenApplicationProxy(HLERequestContext& ctx); + std::shared_ptr GetAppletFromContext(HLERequestContext& ctx); + Nvnflinger::Nvnflinger& nvnflinger; - std::shared_ptr msg_queue; }; } // namespace AM diff --git a/src/core/hle/service/am/application_functions.cpp b/src/core/hle/service/am/application_functions.cpp index fef45c7322..51c5be2d1a 100644 --- a/src/core/hle/service/am/application_functions.cpp +++ b/src/core/hle/service/am/application_functions.cpp @@ -9,6 +9,7 @@ #include "core/file_sys/savedata_factory.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/am_results.h" +#include "core/hle/service/am/applet.h" #include "core/hle/service/am/application_functions.h" #include "core/hle/service/am/storage.h" #include "core/hle/service/filesystem/filesystem.h" @@ -24,19 +25,8 @@ enum class LaunchParameterKind : u32 { AccountPreselectedUser = 2, }; -constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA; - -struct LaunchParameterAccountPreselectedUser { - u32_le magic; - u32_le is_account_selected; - Common::UUID current_user; - INSERT_PADDING_BYTES(0x70); -}; -static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); - -IApplicationFunctions::IApplicationFunctions(Core::System& system_) - : ServiceFramework{system_, "IApplicationFunctions"}, - service_context{system, "IApplicationFunctions"} { +IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr applet_) + : ServiceFramework{system_, "IApplicationFunctions"}, applet{std::move(applet_)} { // clang-format off static const FunctionInfo functions[] = { {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, @@ -105,27 +95,16 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) // clang-format on RegisterHandlers(functions); - - gpu_error_detected_event = - service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent"); - friend_invitation_storage_channel_event = - service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent"); - notification_storage_channel_event = - service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent"); - health_warning_disappeared_system_event = - service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent"); } -IApplicationFunctions::~IApplicationFunctions() { - service_context.CloseEvent(gpu_error_detected_event); - service_context.CloseEvent(friend_invitation_storage_channel_event); - service_context.CloseEvent(notification_storage_channel_event); - service_context.CloseEvent(health_warning_disappeared_system_event); -} +IApplicationFunctions::~IApplicationFunctions() = default; void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->application_crash_report_enabled = true; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -157,6 +136,10 @@ void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->home_button_long_pressed_blocked = true; + applet->home_button_short_pressed_blocked = true; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -164,6 +147,10 @@ void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLEReques void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->home_button_long_pressed_blocked = false; + applet->home_button_short_pressed_blocked = false; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -171,6 +158,11 @@ void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestC void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->home_button_long_pressed_blocked = true; + applet->home_button_short_pressed_blocked = true; + applet->home_button_double_click_enabled = true; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -178,6 +170,11 @@ void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) { void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->home_button_long_pressed_blocked = false; + applet->home_button_short_pressed_blocked = false; + applet->home_button_double_click_enabled = false; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -188,47 +185,25 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) { LOG_INFO(Service_AM, "called, kind={:08X}", kind); - if (kind == LaunchParameterKind::UserChannel) { - auto channel = system.GetUserChannel(); - if (channel.empty()) { - LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(AM::ResultNoDataInChannel); - return; - } + std::scoped_lock lk{applet->lock}; - auto data = channel.back(); - channel.pop_back(); + auto& channel = kind == LaunchParameterKind::UserChannel + ? applet->user_channel_launch_parameter + : applet->preselected_user_launch_parameter; - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, std::move(data)); - } else if (kind == LaunchParameterKind::AccountPreselectedUser && - !launch_popped_account_preselect) { - // TODO: Verify this is hw-accurate - LaunchParameterAccountPreselectedUser params{}; - - params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC; - params.is_account_selected = 1; - - Account::ProfileManager profile_manager{}; - const auto uuid = profile_manager.GetUser(static_cast(Settings::values.current_user)); - ASSERT(uuid.has_value() && uuid->IsValid()); - params.current_user = *uuid; - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - - std::vector buffer(sizeof(LaunchParameterAccountPreselectedUser)); - std::memcpy(buffer.data(), ¶ms, buffer.size()); - - rb.PushIpcInterface(system, std::move(buffer)); - launch_popped_account_preselect = true; - } else { - LOG_ERROR(Service_AM, "Unknown launch parameter kind."); + if (channel.empty()) { + LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", kind); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(AM::ResultNoDataInChannel); + return; } + + auto data = channel.back(); + channel.pop_back(); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(system, std::move(data)); } void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { @@ -245,7 +220,7 @@ void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); FileSys::SaveDataAttribute attribute{}; - attribute.title_id = system.GetApplicationProcessProgramID(); + attribute.title_id = applet->program_id; attribute.user_id = user_id; attribute.type = FileSys::SaveDataType::SaveData; @@ -267,6 +242,9 @@ void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) { u32 result = rp.Pop(); LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result); + std::scoped_lock lk{applet->lock}; + applet->terminate_result = Result(result); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -277,16 +255,14 @@ void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) { std::array version_string{}; const auto res = [this] { - const auto title_id = system.GetApplicationProcessProgramID(); - - const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(), system.GetContentProvider()}; auto metadata = pm.GetControlMetadata(); if (metadata.first != nullptr) { return metadata; } - const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), + const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id), system.GetFileSystemController(), system.GetContentProvider()}; return pm_update.GetControlMetadata(); @@ -314,16 +290,14 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { u32 supported_languages = 0; const auto res = [this] { - const auto title_id = system.GetApplicationProcessProgramID(); - - const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(), system.GetContentProvider()}; auto metadata = pm.GetControlMetadata(); if (metadata.first != nullptr) { return metadata; } - const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), + const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id), system.GetFileSystemController(), system.GetContentProvider()}; return pm_update.GetControlMetadata(); @@ -368,11 +342,9 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); - constexpr bool gameplay_recording_supported = false; - IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(gameplay_recording_supported); + rb.Push(applet->gameplay_recording_supported); } void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) { @@ -385,6 +357,11 @@ void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + + std::scoped_lock lk{applet->lock}; + applet->gameplay_recording_state = rp.PopRaw(); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -392,6 +369,9 @@ void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) { void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->is_running = true; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(0); // Unknown, seems to be ignored by official processes @@ -426,8 +406,7 @@ void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) { static_cast(type), user_id[1], user_id[0], new_normal_size, new_journal_size); system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize( - type, system.GetApplicationProcessProgramID(), user_id, - {new_normal_size, new_journal_size}); + type, applet->program_id, user_id, {new_normal_size, new_journal_size}); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); @@ -451,7 +430,7 @@ void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) { user_id[0]); const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize( - type, system.GetApplicationProcessProgramID(), user_id); + type, applet->program_id, user_id); IPC::ResponseBuilder rb{ctx, 6}; rb.Push(ResultSuccess); @@ -528,13 +507,15 @@ void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); + // Swap user channel ownership into the system so that it will be preserved + system.GetUserChannel().swap(applet->user_channel_launch_parameter); system.ExecuteProgram(program_index); } void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); - system.GetUserChannel().clear(); + applet->user_channel_launch_parameter.clear(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -546,7 +527,7 @@ void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto storage = rp.PopIpcInterface().lock(); if (storage) { - system.GetUserChannel().push_back(storage->GetData()); + applet->user_channel_launch_parameter.push_back(storage->GetData()); } IPC::ResponseBuilder rb{ctx, 2}; @@ -558,7 +539,7 @@ void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(previous_program_index); + rb.Push(applet->previous_program_index); } void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) { @@ -566,7 +547,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ct IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent()); + rb.PushCopyObjects(applet->gpu_error_detected_event.GetHandle()); } void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) { @@ -574,7 +555,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestCon IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent()); + rb.PushCopyObjects(applet->friend_invitation_storage_channel_event.GetHandle()); } void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) { @@ -589,7 +570,7 @@ void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent()); + rb.PushCopyObjects(applet->notification_storage_channel_event.GetHandle()); } void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) { @@ -597,12 +578,15 @@ void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestCon IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent()); + rb.PushCopyObjects(applet->health_warning_disappeared_system_event.GetHandle()); } void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->jit_service_launched = true; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } diff --git a/src/core/hle/service/am/application_functions.h b/src/core/hle/service/am/application_functions.h index 22aab1c8f9..55eb21d391 100644 --- a/src/core/hle/service/am/application_functions.h +++ b/src/core/hle/service/am/application_functions.h @@ -8,9 +8,11 @@ namespace Service::AM { +struct Applet; + class IApplicationFunctions final : public ServiceFramework { public: - explicit IApplicationFunctions(Core::System& system_); + explicit IApplicationFunctions(Core::System& system_, std::shared_ptr applet_); ~IApplicationFunctions() override; private: @@ -50,14 +52,7 @@ private: void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx); void PrepareForJit(HLERequestContext& ctx); - KernelHelpers::ServiceContext service_context; - - bool launch_popped_account_preselect = false; - s32 previous_program_index{-1}; - Kernel::KEvent* gpu_error_detected_event; - Kernel::KEvent* friend_invitation_storage_channel_event; - Kernel::KEvent* notification_storage_channel_event; - Kernel::KEvent* health_warning_disappeared_system_event; + const std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/application_proxy.cpp b/src/core/hle/service/am/application_proxy.cpp index e9cd0aa718..99e97f4bc4 100644 --- a/src/core/hle/service/am/application_proxy.cpp +++ b/src/core/hle/service/am/application_proxy.cpp @@ -18,10 +18,9 @@ namespace Service::AM { IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, - Core::System& system_) - : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, - msg_queue{std::move(msg_queue_)} { + std::shared_ptr applet_, Core::System& system_) + : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, applet{std::move( + applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -39,6 +38,8 @@ IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, RegisterHandlers(functions); } +IApplicationProxy::~IApplicationProxy() = default; + void IApplicationProxy::GetAudioController(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); @@ -60,7 +61,7 @@ void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) { @@ -76,7 +77,7 @@ void IApplicationProxy::GetWindowController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void IApplicationProxy::GetSelfController(HLERequestContext& ctx) { @@ -84,7 +85,7 @@ void IApplicationProxy::GetSelfController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system, nvnflinger); + rb.PushIpcInterface(system, applet, nvnflinger); } void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) { @@ -92,7 +93,7 @@ void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system, msg_queue); + rb.PushIpcInterface(system, applet); } void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { @@ -100,7 +101,7 @@ void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) { @@ -108,7 +109,7 @@ void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } } // namespace Service::AM diff --git a/src/core/hle/service/am/application_proxy.h b/src/core/hle/service/am/application_proxy.h index 4f620242ba..eb98b095cb 100644 --- a/src/core/hle/service/am/application_proxy.h +++ b/src/core/hle/service/am/application_proxy.h @@ -3,16 +3,17 @@ #pragma once -#include "core/hle/service/am/applet_message_queue.h" #include "core/hle/service/service.h" namespace Service::AM { +struct Applet; + class IApplicationProxy final : public ServiceFramework { public: explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, - Core::System& system_); + std::shared_ptr msg_queue_, Core::System& system_); + ~IApplicationProxy(); private: void GetAudioController(HLERequestContext& ctx); @@ -26,7 +27,7 @@ private: void GetApplicationFunctions(HLERequestContext& ctx); Nvnflinger::Nvnflinger& nvnflinger; - std::shared_ptr msg_queue; + std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/common_state_getter.cpp b/src/core/hle/service/am/common_state_getter.cpp index 0b54b769db..77f3fd8684 100644 --- a/src/core/hle/service/am/common_state_getter.cpp +++ b/src/core/hle/service/am/common_state_getter.cpp @@ -3,6 +3,7 @@ #include "common/settings.h" #include "core/hle/service/am/am_results.h" +#include "core/hle/service/am/applet.h" #include "core/hle/service/am/common_state_getter.h" #include "core/hle/service/am/lock_accessor.h" #include "core/hle/service/apm/apm_controller.h" @@ -14,10 +15,8 @@ namespace Service::AM { -ICommonStateGetter::ICommonStateGetter(Core::System& system_, - std::shared_ptr msg_queue_) - : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)}, - service_context{system_, "ICommonStateGetter"} { +ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr applet_) + : ServiceFramework{system_, "ICommonStateGetter"}, applet{std::move(applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, @@ -75,17 +74,9 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, // clang-format on RegisterHandlers(functions); - - sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent"); - - // Configure applets to be in foreground state - msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); - msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); } -ICommonStateGetter::~ICommonStateGetter() { - service_context.CloseEvent(sleep_lock_event); -}; +ICommonStateGetter::~ICommonStateGetter() = default; void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); @@ -96,17 +87,17 @@ void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { } void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); + LOG_DEBUG(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent()); + rb.PushCopyObjects(applet->message_queue.GetMessageReceiveEvent()); } void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); - const auto message = msg_queue->PopMessage(); + const auto message = applet->message_queue.PopMessage(); IPC::ResponseBuilder rb{ctx, 3}; if (message == AppletMessageQueue::AppletMessage::None) { @@ -123,9 +114,11 @@ void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) { void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(static_cast(FocusState::InFocus)); + rb.Push(static_cast(applet->focus_state)); } void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) { @@ -149,7 +142,7 @@ void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); // Sleep lock is acquired immediately. - sleep_lock_event->Signal(); + applet->sleep_lock_event.Signal(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -172,22 +165,25 @@ void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(sleep_lock_event->GetReadableEvent()); + rb.PushCopyObjects(applet->sleep_lock_event.GetHandle()); } void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); + std::scoped_lock lk{applet->lock}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(vr_mode_state); + rb.Push(applet->vr_mode_enabled); } void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - vr_mode_state = rp.Pop(); - LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off"); + std::scoped_lock lk{applet->lock}; + applet->vr_mode_enabled = rp.Pop(); + LOG_WARNING(Service_AM, "VR Mode is {}", applet->vr_mode_enabled ? "on" : "off"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -207,6 +203,9 @@ void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) { void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->vr_mode_enabled = true; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -214,6 +213,9 @@ void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) { void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->vr_mode_enabled = false; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -223,7 +225,7 @@ void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContex IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent()); + rb.PushCopyObjects(applet->message_queue.GetOperationModeChangedEvent()); } void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) { @@ -281,6 +283,9 @@ void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnable HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->request_exit_to_library_applet_at_execute_next_program_enabled = true; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } diff --git a/src/core/hle/service/am/common_state_getter.h b/src/core/hle/service/am/common_state_getter.h index 11d66f10af..643ca4dc54 100644 --- a/src/core/hle/service/am/common_state_getter.h +++ b/src/core/hle/service/am/common_state_getter.h @@ -10,10 +10,11 @@ namespace Service::AM { +struct Applet; + class ICommonStateGetter final : public ServiceFramework { public: - explicit ICommonStateGetter(Core::System& system_, - std::shared_ptr msg_queue_); + explicit ICommonStateGetter(Core::System& system_, std::shared_ptr applet_); ~ICommonStateGetter() override; private: @@ -69,10 +70,7 @@ private: void GetSettingsPlatformRegion(HLERequestContext& ctx); void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx); - std::shared_ptr msg_queue; - bool vr_mode_state{}; - Kernel::KEvent* sleep_lock_event; - KernelHelpers::ServiceContext service_context; + const std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp index 4e8f806d7c..38495ee19e 100644 --- a/src/core/hle/service/am/frontend/applets.cpp +++ b/src/core/hle/service/am/frontend/applets.cpp @@ -16,6 +16,7 @@ #include "core/hle/kernel/k_event.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" +#include "core/hle/service/am/applet_manager.h" #include "core/hle/service/am/applet_message_queue.h" #include "core/hle/service/am/applet_oe.h" #include "core/hle/service/am/frontend/applet_cabinet.h" @@ -122,21 +123,11 @@ void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr&& void AppletDataBroker::SignalStateChanged() { state_changed_event->Signal(); + // TODO proper window management switch (applet_mode) { case LibraryAppletMode::AllForeground: case LibraryAppletMode::AllForegroundInitiallyHidden: { - auto applet_oe = system.ServiceManager().GetService("appletOE"); - auto applet_ae = system.ServiceManager().GetService("appletAE"); - - if (applet_oe) { - applet_oe->GetMessageQueue()->FocusStateChanged(); - break; - } - - if (applet_ae) { - applet_ae->GetMessageQueue()->FocusStateChanged(); - break; - } + system.GetAppletManager().FocusStateChanged(); break; } default: @@ -255,11 +246,6 @@ void FrontendAppletHolder::SetCurrentAppletId(AppletId applet_id) { current_applet_id = applet_id; } -void FrontendAppletHolder::SetDefaultAppletFrontendSet() { - ClearAll(); - SetDefaultAppletsIfMissing(); -} - void FrontendAppletHolder::SetDefaultAppletsIfMissing() { if (frontend.cabinet == nullptr) { frontend.cabinet = std::make_unique(); diff --git a/src/core/hle/service/am/frontend/applets.h b/src/core/hle/service/am/frontend/applets.h index f581479551..dec1d63b2a 100644 --- a/src/core/hle/service/am/frontend/applets.h +++ b/src/core/hle/service/am/frontend/applets.h @@ -188,7 +188,6 @@ public: void SetFrontendAppletSet(FrontendAppletSet set); void SetCabinetMode(NFP::CabinetMode mode); void SetCurrentAppletId(AppletId applet_id); - void SetDefaultAppletFrontendSet(); void SetDefaultAppletsIfMissing(); void ClearAll(); diff --git a/src/core/hle/service/am/library_applet_accessor.cpp b/src/core/hle/service/am/library_applet_accessor.cpp index dabbd6dbe7..d3be493e6a 100644 --- a/src/core/hle/service/am/library_applet_accessor.cpp +++ b/src/core/hle/service/am/library_applet_accessor.cpp @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/scope_exit.h" #include "core/hle/service/am/am_results.h" +#include "core/hle/service/am/frontend/applets.h" #include "core/hle/service/am/library_applet_accessor.h" #include "core/hle/service/am/storage.h" #include "core/hle/service/ipc_helpers.h" @@ -9,8 +11,10 @@ namespace Service::AM { ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_, - std::shared_ptr applet_) - : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} { + std::shared_ptr storage_, + std::shared_ptr applet_) + : ServiceFramework{system_, "ILibraryAppletAccessor"}, storage{std::move(storage_)}, + applet{std::move(applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, @@ -38,27 +42,31 @@ ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_, RegisterHandlers(functions); } +ILibraryAppletAccessor::~ILibraryAppletAccessor() = default; + void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent()); + rb.PushCopyObjects(storage->state_changed_event.GetHandle()); } void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); + std::scoped_lock lk{applet->lock}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(applet->TransactionComplete()); + rb.Push(applet->is_completed); } void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(applet->GetStatus()); + rb.Push(applet->terminate_result); } void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) { @@ -71,10 +79,7 @@ void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestConte void ILibraryAppletAccessor::Start(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); - ASSERT(applet != nullptr); - - applet->Initialize(); - applet->Execute(); + applet->process->Run(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -84,16 +89,17 @@ void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); ASSERT(applet != nullptr); + applet->message_queue.RequestExit(); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(applet->RequestExit()); + rb.Push(ResultSuccess); } void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::RequestParser rp{ctx}; - applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface().lock()); + storage->in_data.PushData(rp.PopIpcInterface().lock()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -102,29 +108,24 @@ void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) { void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); - auto storage = applet->GetBroker().PopNormalDataToGame(); - if (storage == nullptr) { - LOG_DEBUG(Service_AM, - "storage is a nullptr. There is no data in the current normal channel"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(AM::ResultNoDataInChannel); - return; - } + std::shared_ptr data; + const auto res = storage->out_data.PopData(&data); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(std::move(storage)); + if (res.IsSuccess()) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(res); + rb.PushIpcInterface(std::move(data)); + } else { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res); + } } void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::RequestParser rp{ctx}; - applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface().lock()); - - ASSERT(applet->IsInitialized()); - applet->ExecuteInteractive(); - applet->Execute(); + storage->interactive_in_data.PushData(rp.PopIpcInterface().lock()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -133,18 +134,17 @@ void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) { void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); - auto storage = applet->GetBroker().PopInteractiveDataToGame(); - if (storage == nullptr) { - LOG_DEBUG(Service_AM, - "storage is a nullptr. There is no data in the current interactive channel"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(AM::ResultNoDataInChannel); - return; - } + std::shared_ptr data; + const auto res = storage->interactive_out_data.PopData(&data); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(std::move(storage)); + if (res.IsSuccess()) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(res); + rb.PushIpcInterface(std::move(data)); + } else { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res); + } } void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) { @@ -152,7 +152,7 @@ void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent()); + rb.PushCopyObjects(storage->out_data.GetEvent()); } void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) { @@ -160,7 +160,7 @@ void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ct IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent()); + rb.PushCopyObjects(storage->interactive_out_data.GetEvent()); } void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/library_applet_accessor.h b/src/core/hle/service/am/library_applet_accessor.h index 77f62906c7..c34a1cbca8 100644 --- a/src/core/hle/service/am/library_applet_accessor.h +++ b/src/core/hle/service/am/library_applet_accessor.h @@ -3,17 +3,21 @@ #pragma once -#include "core/hle/service/am/frontend/applets.h" #include "core/hle/service/service.h" namespace Service::AM { +struct AppletStorageHolder; +struct Applet; + class ILibraryAppletAccessor final : public ServiceFramework { public: explicit ILibraryAppletAccessor(Core::System& system_, - std::shared_ptr applet_); + std::shared_ptr storage_, + std::shared_ptr applet_); + ~ILibraryAppletAccessor(); -private: +protected: void GetAppletStateChangedEvent(HLERequestContext& ctx); void IsCompleted(HLERequestContext& ctx); void GetResult(HLERequestContext& ctx); @@ -28,7 +32,8 @@ private: void GetPopInteractiveOutDataEvent(HLERequestContext& ctx); void GetIndirectLayerConsumerHandle(HLERequestContext& ctx); - std::shared_ptr applet; + const std::shared_ptr storage; + const std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp index f808875175..e4332e244d 100644 --- a/src/core/hle/service/am/library_applet_creator.cpp +++ b/src/core/hle/service/am/library_applet_creator.cpp @@ -2,16 +2,112 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/service/am/applet_manager.h" #include "core/hle/service/am/frontend/applets.h" #include "core/hle/service/am/library_applet_accessor.h" #include "core/hle/service/am/library_applet_creator.h" #include "core/hle/service/am/storage.h" #include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/sm/sm.h" namespace Service::AM { -ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) - : ServiceFramework{system_, "ILibraryAppletCreator"} { +namespace { + +AppletProgramId AppletIdToProgramId(AppletId applet_id) { + switch (applet_id) { + case AppletId::OverlayDisplay: + return AppletProgramId::OverlayDisplay; + case AppletId::QLaunch: + return AppletProgramId::QLaunch; + case AppletId::Starter: + return AppletProgramId::Starter; + case AppletId::Auth: + return AppletProgramId::Auth; + case AppletId::Cabinet: + return AppletProgramId::Cabinet; + case AppletId::Controller: + return AppletProgramId::Controller; + case AppletId::DataErase: + return AppletProgramId::DataErase; + case AppletId::Error: + return AppletProgramId::Error; + case AppletId::NetConnect: + return AppletProgramId::NetConnect; + case AppletId::ProfileSelect: + return AppletProgramId::ProfileSelect; + case AppletId::SoftwareKeyboard: + return AppletProgramId::SoftwareKeyboard; + case AppletId::MiiEdit: + return AppletProgramId::MiiEdit; + case AppletId::Web: + return AppletProgramId::Web; + case AppletId::Shop: + return AppletProgramId::Shop; + case AppletId::PhotoViewer: + return AppletProgramId::PhotoViewer; + case AppletId::Settings: + return AppletProgramId::Settings; + case AppletId::OfflineWeb: + return AppletProgramId::OfflineWeb; + case AppletId::LoginShare: + return AppletProgramId::LoginShare; + case AppletId::WebAuth: + return AppletProgramId::WebAuth; + case AppletId::MyPage: + return AppletProgramId::MyPage; + default: + return static_cast(0); + } +} + +std::shared_ptr CreateGuestApplet(Core::System& system, + std::shared_ptr caller_applet, + AppletId applet_id, + LibraryAppletMode mode) { + const auto program_id = static_cast(AppletIdToProgramId(applet_id)); + if (program_id == 0) { + // Unknown applet + return {}; + } + + auto process = std::make_unique(system); + if (!process->Initialize(program_id)) { + // Couldn't initialize the guest process + return {}; + } + + const auto applet = std::make_shared(system, std::move(process)); + applet->program_id = program_id; + applet->applet_id = 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; + + auto storage = std::make_shared(system); + applet->caller_applet = caller_applet; + applet->caller_applet_storage = storage; + + system.GetAppletManager().InsertApplet(applet); + + return std::make_shared(system, storage, applet); +} + +std::shared_ptr CreateFrontendApplet(Core::System& system, + AppletId applet_id, + LibraryAppletMode mode) { + UNREACHABLE(); + return {}; +} + +} // namespace + +ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr applet_) + : ServiceFramework{system_, "ILibraryAppletCreator"}, applet{std::move(applet_)} { static const FunctionInfo functions[] = { {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, {1, nullptr, "TerminateAllLibraryApplets"}, @@ -34,10 +130,11 @@ void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, applet_mode); - const auto& holder{system.GetFrontendAppletHolder()}; - const auto applet = holder.GetApplet(applet_id, applet_mode); - - if (applet == nullptr) { + auto library_applet = CreateGuestApplet(system, applet, applet_id, applet_mode); + if (!library_applet) { + library_applet = CreateFrontendApplet(system, applet_id, applet_mode); + } + if (!library_applet) { LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -45,10 +142,12 @@ void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) { return; } - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + // Applet is created, can now be launched. + applet->library_applet_launchable_event.Signal(); + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system, applet); + rb.PushIpcInterface(library_applet); } void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/library_applet_creator.h b/src/core/hle/service/am/library_applet_creator.h index 97f236fbcb..551f287bd6 100644 --- a/src/core/hle/service/am/library_applet_creator.h +++ b/src/core/hle/service/am/library_applet_creator.h @@ -7,9 +7,11 @@ namespace Service::AM { +struct Applet; + class ILibraryAppletCreator final : public ServiceFramework { public: - explicit ILibraryAppletCreator(Core::System& system_); + explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr applet_); ~ILibraryAppletCreator() override; private: @@ -17,6 +19,8 @@ private: void CreateStorage(HLERequestContext& ctx); void CreateTransferMemoryStorage(HLERequestContext& ctx); void CreateHandleStorage(HLERequestContext& ctx); + + const std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_proxy.cpp b/src/core/hle/service/am/library_applet_proxy.cpp index 047fc40f48..1d88dd78cb 100644 --- a/src/core/hle/service/am/library_applet_proxy.cpp +++ b/src/core/hle/service/am/library_applet_proxy.cpp @@ -19,10 +19,9 @@ namespace Service::AM { ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, - Core::System& system_) - : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, - msg_queue{std::move(msg_queue_)} { + std::shared_ptr applet_, Core::System& system_) + : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move( + applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -43,12 +42,14 @@ ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, RegisterHandlers(functions); } +ILibraryAppletProxy::~ILibraryAppletProxy() = default; + void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system, msg_queue); + rb.PushIpcInterface(system, applet); } void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) { @@ -56,7 +57,7 @@ void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system, nvnflinger); + rb.PushIpcInterface(system, applet, nvnflinger); } void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) { @@ -64,7 +65,7 @@ void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) { @@ -88,7 +89,7 @@ void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { @@ -96,7 +97,7 @@ void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { @@ -104,7 +105,7 @@ void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { @@ -112,7 +113,7 @@ void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/library_applet_proxy.h b/src/core/hle/service/am/library_applet_proxy.h index cd9e6d02b0..8f7a258975 100644 --- a/src/core/hle/service/am/library_applet_proxy.h +++ b/src/core/hle/service/am/library_applet_proxy.h @@ -3,16 +3,17 @@ #pragma once -#include "core/hle/service/am/applet_message_queue.h" #include "core/hle/service/service.h" namespace Service::AM { +struct Applet; + class ILibraryAppletProxy final : public ServiceFramework { public: explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, - Core::System& system_); + std::shared_ptr applet_, Core::System& system_); + ~ILibraryAppletProxy(); private: void GetCommonStateGetter(HLERequestContext& ctx); @@ -29,7 +30,7 @@ private: void GetDebugFunctions(HLERequestContext& ctx); Nvnflinger::Nvnflinger& nvnflinger; - std::shared_ptr msg_queue; + std::shared_ptr applet; }; } // namespace Service::AM 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 c36f141f49..74ee332133 100644 --- a/src/core/hle/service/am/library_applet_self_accessor.cpp +++ b/src/core/hle/service/am/library_applet_self_accessor.cpp @@ -1,9 +1,11 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/scope_exit.h" #include "core/core_timing.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/am_results.h" +#include "core/hle/service/am/applet_manager.h" #include "core/hle/service/am/frontend/applet_cabinet.h" #include "core/hle/service/am/frontend/applet_controller.h" #include "core/hle/service/am/frontend/applet_mii_edit_types.h" @@ -16,16 +18,44 @@ namespace Service::AM { -ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) - : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} { +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, + }; + } else { + return { + .applet_id = AppletId::QLaunch, + .application_id = 0x0100000000001000ull, + }; + } +} + +} // namespace + +ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_, + std::shared_ptr applet_) + : ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, applet{std::move(applet_)}, + storage{applet->caller_applet_storage} { // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"}, {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"}, - {2, nullptr, "PopInteractiveInData"}, - {3, nullptr, "PushInteractiveOutData"}, - {5, nullptr, "GetPopInDataEvent"}, - {6, nullptr, "GetPopInteractiveInDataEvent"}, + {2, &ILibraryAppletSelfAccessor::PopInteractiveInData, "PopInteractiveInData"}, + {3, &ILibraryAppletSelfAccessor::PushInteractiveOutData, "PushInteractiveOutData"}, + {5, &ILibraryAppletSelfAccessor::GetPopInDataEvent, "GetPopInDataEvent"}, + {6, &ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent, "GetPopInteractiveInDataEvent"}, {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"}, @@ -58,26 +88,6 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) }; // clang-format on RegisterHandlers(functions); - - switch (system.GetFrontendAppletHolder().GetCurrentAppletId()) { - case AppletId::Cabinet: - PushInShowCabinetData(); - break; - case AppletId::MiiEdit: - PushInShowMiiEditData(); - break; - case AppletId::PhotoViewer: - PushInShowAlbum(); - break; - case AppletId::SoftwareKeyboard: - PushInShowSoftwareKeyboard(); - break; - case AppletId::Controller: - PushInShowController(); - break; - default: - break; - } } ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; @@ -85,31 +95,81 @@ ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) { LOG_INFO(Service_AM, "called"); - if (queue_data.empty()) { + std::shared_ptr data; + const auto res = storage->in_data.PopData(&data); + + if (res.IsSuccess()) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(res); + rb.PushIpcInterface(std::move(data)); + } else { IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(AM::ResultNoDataInChannel); - return; + rb.Push(res); } - - auto data = queue_data.front(); - queue_data.pop_front(); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, std::move(data)); } void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_INFO(Service_AM, "called"); + + IPC::RequestParser rp{ctx}; + storage->out_data.PushData(rp.PopIpcInterface().lock()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } -void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); +void ILibraryAppletSelfAccessor::PopInteractiveInData(HLERequestContext& ctx) { + LOG_INFO(Service_AM, "called"); - system.Exit(); + std::shared_ptr data; + const auto res = storage->interactive_in_data.PopData(&data); + + if (res.IsSuccess()) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(res); + rb.PushIpcInterface(std::move(data)); + } else { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res); + } +} + +void ILibraryAppletSelfAccessor::PushInteractiveOutData(HLERequestContext& ctx) { + LOG_INFO(Service_AM, "called"); + + IPC::RequestParser rp{ctx}; + storage->interactive_out_data.PushData(rp.PopIpcInterface().lock()); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ILibraryAppletSelfAccessor::GetPopInDataEvent(HLERequestContext& ctx) { + LOG_INFO(Service_AM, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(storage->in_data.GetEvent()); +} + +void ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(HLERequestContext& ctx) { + LOG_INFO(Service_AM, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(storage->interactive_in_data.GetEvent()); +} + +void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) { + LOG_INFO(Service_AM, "called"); + + system.GetAppletManager().TerminateAndRemoveApplet(applet->aruid); + + { + std::scoped_lock lk{applet->lock}; + applet->is_completed = true; + storage->state_changed_event.Signal(); + } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -124,8 +184,8 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); const LibraryAppletInfo applet_info{ - .applet_id = system.GetFrontendAppletHolder().GetCurrentAppletId(), - .library_applet_mode = LibraryAppletMode::AllForeground, + .applet_id = applet->applet_id, + .library_applet_mode = applet->library_applet_mode, }; IPC::ResponseBuilder rb{ctx, 4}; @@ -134,13 +194,6 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) { } void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) { - struct AppletIdentityInfo { - AppletId applet_id; - INSERT_PADDING_BYTES(0x4); - u64 application_id; - }; - static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); - LOG_WARNING(Service_AM, "(STUBBED) called"); const AppletIdentityInfo applet_info{ @@ -154,22 +207,11 @@ void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ct } void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { - struct AppletIdentityInfo { - AppletId applet_id; - INSERT_PADDING_BYTES(0x4); - u64 application_id; - }; - static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); LOG_WARNING(Service_AM, "(STUBBED) called"); - const AppletIdentityInfo applet_info{ - .applet_id = AppletId::QLaunch, - .application_id = 0x0100000000001000ull, - }; - IPC::ResponseBuilder rb{ctx, 6}; rb.Push(ResultSuccess); - rb.PushRaw(applet_info); + rb.PushRaw(GetCallerIdentity(applet)); } void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) { @@ -207,176 +249,4 @@ void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext rb.Push(0); } -void ILibraryAppletSelfAccessor::PushInShowAlbum() { - const CommonArguments arguments{ - .arguments_version = CommonArgumentVersion::Version3, - .size = CommonArgumentSize::Version3, - .library_version = 1, - .theme_color = ThemeColor::BasicBlack, - .play_startup_sound = true, - .system_tick = system.CoreTiming().GetClockTicks(), - }; - - std::vector argument_data(sizeof(arguments)); - std::vector settings_data{2}; - std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); - queue_data.emplace_back(std::move(argument_data)); - queue_data.emplace_back(std::move(settings_data)); -} - -void ILibraryAppletSelfAccessor::PushInShowController() { - const CommonArguments common_args = { - .arguments_version = CommonArgumentVersion::Version3, - .size = CommonArgumentSize::Version3, - .library_version = static_cast(Frontend::ControllerAppletVersion::Version8), - .theme_color = ThemeColor::BasicBlack, - .play_startup_sound = true, - .system_tick = system.CoreTiming().GetClockTicks(), - }; - - Frontend::ControllerSupportArgNew user_args = { - .header = {.player_count_min = 1, - .player_count_max = 4, - .enable_take_over_connection = true, - .enable_left_justify = false, - .enable_permit_joy_dual = true, - .enable_single_mode = false, - .enable_identification_color = false}, - .identification_colors = {}, - .enable_explain_text = false, - .explain_text = {}, - }; - - Frontend::ControllerSupportArgPrivate private_args = { - .arg_private_size = sizeof(Frontend::ControllerSupportArgPrivate), - .arg_size = sizeof(Frontend::ControllerSupportArgNew), - .is_home_menu = true, - .flag_1 = true, - .mode = Frontend::ControllerSupportMode::ShowControllerSupport, - .caller = Frontend::ControllerSupportCaller:: - Application, // switchbrew: Always zero except with - // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem, - // which sets this to the input param - .style_set = Core::HID::NpadStyleSet::None, - .joy_hold_type = 0, - }; - std::vector common_args_data(sizeof(common_args)); - std::vector private_args_data(sizeof(private_args)); - std::vector user_args_data(sizeof(user_args)); - - std::memcpy(common_args_data.data(), &common_args, sizeof(common_args)); - std::memcpy(private_args_data.data(), &private_args, sizeof(private_args)); - std::memcpy(user_args_data.data(), &user_args, sizeof(user_args)); - - queue_data.emplace_back(std::move(common_args_data)); - queue_data.emplace_back(std::move(private_args_data)); - queue_data.emplace_back(std::move(user_args_data)); -} - -void ILibraryAppletSelfAccessor::PushInShowCabinetData() { - const CommonArguments arguments{ - .arguments_version = CommonArgumentVersion::Version3, - .size = CommonArgumentSize::Version3, - .library_version = static_cast(Frontend::CabinetAppletVersion::Version1), - .theme_color = ThemeColor::BasicBlack, - .play_startup_sound = true, - .system_tick = system.CoreTiming().GetClockTicks(), - }; - - const Frontend::StartParamForAmiiboSettings amiibo_settings{ - .param_1 = 0, - .applet_mode = system.GetFrontendAppletHolder().GetCabinetMode(), - .flags = Frontend::CabinetFlags::None, - .amiibo_settings_1 = 0, - .device_handle = 0, - .tag_info{}, - .register_info{}, - .amiibo_settings_3{}, - }; - - std::vector argument_data(sizeof(arguments)); - std::vector settings_data(sizeof(amiibo_settings)); - std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); - std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings)); - queue_data.emplace_back(std::move(argument_data)); - queue_data.emplace_back(std::move(settings_data)); -} - -void ILibraryAppletSelfAccessor::PushInShowMiiEditData() { - struct MiiEditV3 { - Frontend::MiiEditAppletInputCommon common; - Frontend::MiiEditAppletInputV3 input; - }; - static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size."); - - MiiEditV3 mii_arguments{ - .common = - { - .version = Frontend::MiiEditAppletVersion::Version3, - .applet_mode = Frontend::MiiEditAppletMode::ShowMiiEdit, - }, - .input{}, - }; - - std::vector argument_data(sizeof(mii_arguments)); - std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments)); - - queue_data.emplace_back(std::move(argument_data)); -} - -void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() { - const CommonArguments arguments{ - .arguments_version = CommonArgumentVersion::Version3, - .size = CommonArgumentSize::Version3, - .library_version = static_cast(Frontend::SwkbdAppletVersion::Version524301), - .theme_color = ThemeColor::BasicBlack, - .play_startup_sound = true, - .system_tick = system.CoreTiming().GetClockTicks(), - }; - - std::vector initial_string(0); - - const Frontend::SwkbdConfigCommon swkbd_config{ - .type = Frontend::SwkbdType::Qwerty, - .ok_text{}, - .left_optional_symbol_key{}, - .right_optional_symbol_key{}, - .use_prediction = false, - .key_disable_flags{}, - .initial_cursor_position = Frontend::SwkbdInitialCursorPosition::Start, - .header_text{}, - .sub_text{}, - .guide_text{}, - .max_text_length = 500, - .min_text_length = 0, - .password_mode = Frontend::SwkbdPasswordMode::Disabled, - .text_draw_type = Frontend::SwkbdTextDrawType::Box, - .enable_return_button = true, - .use_utf8 = false, - .use_blur_background = true, - .initial_string_offset{}, - .initial_string_length = static_cast(initial_string.size()), - .user_dictionary_offset{}, - .user_dictionary_entries{}, - .use_text_check = false, - }; - - Frontend::SwkbdConfigNew swkbd_config_new{}; - - std::vector argument_data(sizeof(arguments)); - std::vector swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new)); - std::vector work_buffer(swkbd_config.initial_string_length * sizeof(char16_t)); - - std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); - std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config)); - std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new, - sizeof(Frontend::SwkbdConfigNew)); - std::memcpy(work_buffer.data(), initial_string.data(), - swkbd_config.initial_string_length * sizeof(char16_t)); - - queue_data.emplace_back(std::move(argument_data)); - queue_data.emplace_back(std::move(swkbd_data)); - queue_data.emplace_back(std::move(work_buffer)); -} - } // 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 45b325b77c..b150405394 100644 --- a/src/core/hle/service/am/library_applet_self_accessor.h +++ b/src/core/hle/service/am/library_applet_self_accessor.h @@ -10,14 +10,21 @@ namespace Service::AM { +struct AppletStorageHolder; +struct Applet; + class ILibraryAppletSelfAccessor final : public ServiceFramework { public: - explicit ILibraryAppletSelfAccessor(Core::System& system_); + explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr applet_); ~ILibraryAppletSelfAccessor() override; private: void PopInData(HLERequestContext& ctx); void PushOutData(HLERequestContext& ctx); + void PopInteractiveInData(HLERequestContext& ctx); + void PushInteractiveOutData(HLERequestContext& ctx); + void GetPopInDataEvent(HLERequestContext& ctx); + void GetPopInteractiveInDataEvent(HLERequestContext& ctx); void GetLibraryAppletInfo(HLERequestContext& ctx); void GetMainAppletIdentityInfo(HLERequestContext& ctx); void ExitProcessAndReturn(HLERequestContext& ctx); @@ -26,13 +33,8 @@ private: void GetMainAppletAvailableUsers(HLERequestContext& ctx); void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx); - void PushInShowAlbum(); - void PushInShowCabinetData(); - void PushInShowMiiEditData(); - void PushInShowSoftwareKeyboard(); - void PushInShowController(); - - std::deque> queue_data; + const std::shared_ptr applet; + const std::shared_ptr storage; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/process_winding_controller.cpp b/src/core/hle/service/am/process_winding_controller.cpp index 7954abd7ae..f5ccc4643e 100644 --- a/src/core/hle/service/am/process_winding_controller.cpp +++ b/src/core/hle/service/am/process_winding_controller.cpp @@ -8,8 +8,9 @@ namespace Service::AM { -IProcessWindingController::IProcessWindingController(Core::System& system_) - : ServiceFramework{system_, "IProcessWindingController"} { +IProcessWindingController::IProcessWindingController(Core::System& system_, + std::shared_ptr applet_) + : ServiceFramework{system_, "IProcessWindingController"}, applet{std::move(applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"}, @@ -31,34 +32,15 @@ IProcessWindingController::~IProcessWindingController() = default; void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); - struct AppletProcessLaunchReason { - u8 flag; - INSERT_PADDING_BYTES(3); - }; - static_assert(sizeof(AppletProcessLaunchReason) == 0x4, - "AppletProcessLaunchReason is an invalid size"); - - AppletProcessLaunchReason reason{ - .flag = 0, - }; - IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.PushRaw(reason); + rb.PushRaw(applet->launch_reason); } void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { - const auto applet_id = system.GetFrontendAppletHolder().GetCurrentAppletId(); - const auto applet_mode = LibraryAppletMode::AllForeground; - - LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id, - applet_mode); - - const auto& holder{system.GetFrontendAppletHolder()}; - const auto applet = holder.GetApplet(applet_id, applet_mode); - - if (applet == nullptr) { - LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); + const auto caller_applet = applet->caller_applet.lock(); + if (caller_applet == nullptr) { + LOG_ERROR(Service_AM, "No calling applet available"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultUnknown); @@ -67,7 +49,8 @@ void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system, applet); + rb.PushIpcInterface(system, applet->caller_applet_storage, + caller_applet); } } // namespace Service::AM diff --git a/src/core/hle/service/am/process_winding_controller.h b/src/core/hle/service/am/process_winding_controller.h index 9b9704201c..71ae4c4f53 100644 --- a/src/core/hle/service/am/process_winding_controller.h +++ b/src/core/hle/service/am/process_winding_controller.h @@ -7,14 +7,18 @@ namespace Service::AM { +struct Applet; + class IProcessWindingController final : public ServiceFramework { public: - explicit IProcessWindingController(Core::System& system_); + explicit IProcessWindingController(Core::System& system_, std::shared_ptr applet_); ~IProcessWindingController() override; private: void GetLaunchReason(HLERequestContext& ctx); void OpenCallingLibraryApplet(HLERequestContext& ctx); + + const std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp index d5de1bb2fb..3ac967b4de 100644 --- a/src/core/hle/service/am/self_controller.cpp +++ b/src/core/hle/service/am/self_controller.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/am/am_results.h" #include "core/hle/service/am/frontend/applets.h" #include "core/hle/service/am/self_controller.h" #include "core/hle/service/caps/caps_su.h" @@ -12,9 +13,10 @@ namespace Service::AM { -ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) - : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, - service_context{system, "ISelfController"} { +ISelfController::ISelfController(Core::System& system_, std::shared_ptr applet_, + Nvnflinger::Nvnflinger& nvnflinger_) + : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, applet{std::move( + applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ISelfController::Exit, "Exit"}, @@ -69,24 +71,9 @@ ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& // clang-format on RegisterHandlers(functions); - - launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent"); - - // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is - // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple - // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not - // suspended if the event has previously been created by a call to - // GetAccumulatedSuspendedTickChangedEvent. - - accumulated_suspended_tick_changed_event = - service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent"); - accumulated_suspended_tick_changed_event->Signal(); } -ISelfController::~ISelfController() { - service_context.CloseEvent(launchable_event); - service_context.CloseEvent(accumulated_suspended_tick_changed_event); -} +ISelfController::~ISelfController() = default; void ISelfController::Exit(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); @@ -94,6 +81,7 @@ void ISelfController::Exit(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); + // TODO system.Exit(); } @@ -120,8 +108,10 @@ void ISelfController::UnlockExit(HLERequestContext& ctx) { } void ISelfController::EnterFatalSection(HLERequestContext& ctx) { - ++num_fatal_sections_entered; - LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); + + std::scoped_lock lk{applet->lock}; + applet->fatal_section_count++; + LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", applet->fatal_section_count); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -131,13 +121,14 @@ void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); // Entry and exit of fatal sections must be balanced. - if (num_fatal_sections_entered == 0) { + std::scoped_lock lk{applet->lock}; + if (applet->fatal_section_count == 0) { IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(Result{ErrorModule::AM, 512}); + rb.Push(AM::ResultFatalSectionCountImbalance); return; } - --num_fatal_sections_entered; + applet->fatal_section_count--; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -146,11 +137,11 @@ void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); - launchable_event->Signal(); + applet->library_applet_launchable_event.Signal(); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(launchable_event->GetReadableEvent()); + rb.PushCopyObjects(applet->library_applet_launchable_event.GetHandle()); } void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { @@ -158,7 +149,8 @@ void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { const auto permission = rp.PopEnum(); LOG_DEBUG(Service_AM, "called, permission={}", permission); - screenshot_permission = permission; + std::scoped_lock lk{applet->lock}; + applet->screenshot_permission = permission; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -167,8 +159,11 @@ void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - bool flag = rp.Pop(); - LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); + const bool notification_enabled = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled); + + std::scoped_lock lk{applet->lock}; + applet->operation_mode_changed_notification_enabled = notification_enabled; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -177,28 +172,27 @@ void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - bool flag = rp.Pop(); - LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); + const bool notification_enabled = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled); + + std::scoped_lock lk{applet->lock}; + applet->performance_mode_changed_notification_enabled = notification_enabled; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { - // Takes 3 input u8s with each field located immediately after the previous - // u8, these are bool flags. No output. IPC::RequestParser rp{ctx}; - struct FocusHandlingModeParams { - u8 unknown0; - u8 unknown1; - u8 unknown2; - }; - const auto flags = rp.PopRaw(); + const auto flags = rp.PopRaw(); LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}", flags.unknown0, flags.unknown1, flags.unknown2); + std::scoped_lock lk{applet->lock}; + applet->focus_handling_mode = flags; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -206,24 +200,35 @@ void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->restart_message_enabled = true; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { - // Takes 3 input u8s with each field located immediately after the previous - // u8, these are bool flags. No output. IPC::RequestParser rp{ctx}; - bool enabled = rp.Pop(); + const bool enabled = rp.Pop(); LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); + std::scoped_lock lk{applet->lock}; + ASSERT(applet->type == AppletType::Application); + applet->out_of_focus_suspension_enabled = enabled; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + + const auto orientation = rp.PopRaw(); + LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", static_cast(orientation)); + + std::scoped_lock lk{applet->lock}; + applet->album_image_orientation = orientation; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -232,14 +237,13 @@ void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); - // TODO(Subv): Find out how AM determines the display to use, for now just - // create the layer in the Default display. - const auto display_id = nvnflinger.OpenDisplay("Default"); - const auto layer_id = nvnflinger.CreateLayer(*display_id); + u64 layer_id{}; + applet->managed_layer_holder.Initialize(&nvnflinger); + applet->managed_layer_holder.CreateManagedDisplayLayer(&layer_id); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(*layer_id); + rb.Push(layer_id); } void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { @@ -252,56 +256,46 @@ void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + u64 buffer_id, layer_id; + applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id); + IPC::ResponseBuilder rb{ctx, 6}; rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); - rb.Push(system_shared_buffer_id); - rb.Push(system_shared_layer_id); + rb.Push(buffer_id); + rb.Push(layer_id); } void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + u64 buffer_id, layer_id; + applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); - rb.Push(system_shared_buffer_id); + rb.Push(buffer_id); } Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { - if (buffer_sharing_enabled) { + if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id)) { return ResultSuccess; } - if (system.GetFrontendAppletHolder().GetCurrentAppletId() <= AppletId::Application) { - return VI::ResultOperationFailed; - } - - const auto display_id = nvnflinger.OpenDisplay("Default"); - const auto result = nvnflinger.GetSystemBufferManager().Initialize( - &system_shared_buffer_id, &system_shared_layer_id, *display_id); - - if (result.IsSuccess()) { - buffer_sharing_enabled = true; - } - - return result; + return VI::ResultOperationFailed; } void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); - // TODO(Subv): Find out how AM determines the display to use, for now just - // create the layer in the Default display. - // This calls nn::vi::CreateRecordingLayer() which creates another layer. - // Currently we do not support more than 1 layer per display, output 1 layer id for now. - // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse - // side effects. - // TODO: Support multiple layers - const auto display_id = nvnflinger.OpenDisplay("Default"); - const auto layer_id = nvnflinger.CreateLayer(*display_id); + u64 layer_id{}; + u64 recording_layer_id{}; + applet->managed_layer_holder.Initialize(&nvnflinger); + applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(&layer_id, &recording_layer_id); - IPC::ResponseBuilder rb{ctx, 4}; + IPC::ResponseBuilder rb{ctx, 6}; rb.Push(ResultSuccess); - rb.Push(*layer_id); + rb.Push(layer_id); + rb.Push(recording_layer_id); } void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { @@ -320,9 +314,12 @@ void ISelfController::ApproveToDisplay(HLERequestContext& ctx) { void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - idle_time_detection_extension = rp.Pop(); - LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}", - idle_time_detection_extension); + + const auto extension = rp.PopRaw(); + LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", extension); + + std::scoped_lock lk{applet->lock}; + applet->idle_time_detection_extension = extension; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -331,9 +328,11 @@ void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(idle_time_detection_extension); + rb.PushRaw(applet->idle_time_detection_extension); } void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { @@ -345,7 +344,9 @@ void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - is_auto_sleep_disabled = rp.Pop(); + + std::scoped_lock lk{applet->lock}; + applet->auto_sleep_disabled = rp.Pop(); // On the system itself, if the previous state of is_auto_sleep_disabled // differed from the current value passed in, it'd signify the internal @@ -357,7 +358,7 @@ void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { // and it's sufficient to simply set the member variable for querying via // IsAutoSleepDisabled(). - LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled); + LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", applet->auto_sleep_disabled); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -366,20 +367,23 @@ void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); + std::scoped_lock lk{applet->lock}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(is_auto_sleep_disabled); + rb.Push(applet->auto_sleep_disabled); } void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); + std::scoped_lock lk{applet->lock}; // This command returns the total number of system ticks since ISelfController creation // where the game was suspended. Since Yuzu doesn't implement game suspension, this command // can just always return 0 ticks. IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(0); + rb.Push(applet->suspended_ticks); } void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { @@ -387,7 +391,7 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); + rb.PushCopyObjects(applet->accumulated_suspended_tick_changed_event.GetHandle()); } void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { @@ -396,10 +400,11 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& c // This service call sets an internal flag whether a notification is shown when an image is // captured. Currently we do not support capturing images via the capture button, so this can be // stubbed for now. - const bool album_image_taken_notification_enabled = rp.Pop(); + const bool enabled = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled); - LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}", - album_image_taken_notification_enabled); + std::scoped_lock lk{applet->lock}; + applet->album_image_taken_notification_enabled = enabled; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -427,9 +432,11 @@ void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto is_record_volume_muted = rp.Pop(); + const auto enabled = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled); - LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted); + std::scoped_lock lk{applet->lock}; + applet->record_volume_muted = enabled; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h index f157bb8263..6e69752648 100644 --- a/src/core/hle/service/am/self_controller.h +++ b/src/core/hle/service/am/self_controller.h @@ -8,9 +8,12 @@ namespace Service::AM { +struct Applet; + class ISelfController final : public ServiceFramework { public: - explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); + explicit ISelfController(Core::System& system_, std::shared_ptr applet_, + Nvnflinger::Nvnflinger& nvnflinger_); ~ISelfController() override; private: @@ -47,26 +50,8 @@ private: Result EnsureBufferSharingEnabled(Kernel::KProcess* process); - enum class ScreenshotPermission : u32 { - Inherit = 0, - Enable = 1, - Disable = 2, - }; - Nvnflinger::Nvnflinger& nvnflinger; - - KernelHelpers::ServiceContext service_context; - - Kernel::KEvent* launchable_event; - Kernel::KEvent* accumulated_suspended_tick_changed_event; - - u32 idle_time_detection_extension = 0; - u64 num_fatal_sections_entered = 0; - u64 system_shared_buffer_id = 0; - u64 system_shared_layer_id = 0; - bool is_auto_sleep_disabled = false; - bool buffer_sharing_enabled = false; - ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit; + const std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/system_applet_proxy.cpp b/src/core/hle/service/am/system_applet_proxy.cpp index d51a2c8dba..e3013271bc 100644 --- a/src/core/hle/service/am/system_applet_proxy.cpp +++ b/src/core/hle/service/am/system_applet_proxy.cpp @@ -20,10 +20,9 @@ namespace Service::AM { ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, - Core::System& system_) - : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_}, - msg_queue{std::move(msg_queue_)} { + std::shared_ptr applet_, Core::System& system_) + : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move( + applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -44,12 +43,14 @@ ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, RegisterHandlers(functions); } +ISystemAppletProxy::~ISystemAppletProxy() = default; + void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system, msg_queue); + rb.PushIpcInterface(system, applet); } void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) { @@ -57,7 +58,7 @@ void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system, nvnflinger); + rb.PushIpcInterface(system, applet, nvnflinger); } void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) { @@ -65,7 +66,7 @@ void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) { @@ -89,7 +90,7 @@ void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { @@ -121,7 +122,7 @@ void ISystemAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system, applet); } void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/system_applet_proxy.h b/src/core/hle/service/am/system_applet_proxy.h index b8855b1d62..0390cd1e5f 100644 --- a/src/core/hle/service/am/system_applet_proxy.h +++ b/src/core/hle/service/am/system_applet_proxy.h @@ -8,11 +8,13 @@ namespace Service::AM { +struct Applet; + class ISystemAppletProxy final : public ServiceFramework { public: explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr msg_queue_, - Core::System& system_); + std::shared_ptr applet_, Core::System& system_); + ~ISystemAppletProxy(); private: void GetCommonStateGetter(HLERequestContext& ctx); @@ -28,7 +30,7 @@ private: void GetDebugFunctions(HLERequestContext& ctx); Nvnflinger::Nvnflinger& nvnflinger; - std::shared_ptr msg_queue; + std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp index f2ba3c134e..430ca180bd 100644 --- a/src/core/hle/service/am/window_controller.cpp +++ b/src/core/hle/service/am/window_controller.cpp @@ -1,13 +1,14 @@ // 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/window_controller.h" #include "core/hle/service/ipc_helpers.h" namespace Service::AM { -IWindowController::IWindowController(Core::System& system_) - : ServiceFramework{system_, "IWindowController"} { +IWindowController::IWindowController(Core::System& system_, std::shared_ptr applet_) + : ServiceFramework{system_, "IWindowController"}, applet{std::move(applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CreateWindow"}, @@ -27,23 +28,22 @@ IWindowController::IWindowController(Core::System& system_) IWindowController::~IWindowController() = default; void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) { - const u64 process_id = system.ApplicationProcess()->GetProcessId(); - - LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id); - IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(process_id); + rb.Push(applet->aruid); } void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) { - const u64 process_id = 0; + u64 aruid = 0; + if (auto caller = applet->caller_applet.lock(); caller) { + aruid = caller->aruid; + } LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(process_id); + rb.Push(aruid); } void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/window_controller.h b/src/core/hle/service/am/window_controller.h index 07b0e0e179..d97f937379 100644 --- a/src/core/hle/service/am/window_controller.h +++ b/src/core/hle/service/am/window_controller.h @@ -7,15 +7,19 @@ namespace Service::AM { +struct Applet; + class IWindowController final : public ServiceFramework { public: - explicit IWindowController(Core::System& system_); + explicit IWindowController(Core::System& system_, std::shared_ptr applet_); ~IWindowController() override; private: void GetAppletResourceUserId(HLERequestContext& ctx); void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx); void AcquireForegroundRights(HLERequestContext& ctx); + + const std::shared_ptr applet; }; } // namespace Service::AM diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 1f3d82c570..73058db9a5 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -535,6 +535,12 @@ public: RegisterHandlers(functions); } + ~IApplicationDisplayService() { + for (const auto layer_id : stray_layer_ids) { + nvnflinger.DestroyLayer(layer_id); + } + } + private: enum class ConvertedScaleMode : u64 { Freeze = 0, @@ -770,6 +776,7 @@ private: return; } + stray_layer_ids.push_back(*layer_id); const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); if (!buffer_queue_id) { LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); @@ -916,6 +923,7 @@ private: Nvnflinger::Nvnflinger& nvnflinger; Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; + std::vector stray_layer_ids; bool vsync_event_fetched{false}; }; diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 718534ba1b..e28df10bdb 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -9,6 +9,7 @@ #include "core/core.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" +#include "core/hle/service/am/applet_manager.h" #include "core/hle/service/am/applet_message_queue.h" #include "core/hle/service/am/applet_oe.h" #include "core/hle/service/sm/sm.h" @@ -48,22 +49,8 @@ void OnDockedModeChanged(bool last_state, bool new_state, Core::System& system) if (!system.IsPoweredOn()) { return; } - Service::SM::ServiceManager& sm = system.ServiceManager(); - // Message queue is shared between these services, we just need to signal an operation - // change to one and it will handle both automatically - auto applet_oe = sm.GetService("appletOE"); - auto applet_ae = sm.GetService("appletAE"); - bool has_signalled = false; - - if (applet_oe != nullptr) { - applet_oe->GetMessageQueue()->OperationModeChanged(); - has_signalled = true; - } - - if (applet_ae != nullptr && !has_signalled) { - applet_ae->GetMessageQueue()->OperationModeChanged(); - } + system.GetAppletManager().OperationModeChanged(); } ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent) diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 02508b20d9..4e5c4da53c 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -4783,36 +4783,12 @@ void GMainWindow::RequestGameExit() { return; } - auto& sm{system->ServiceManager()}; - auto applet_oe = sm.GetService("appletOE"); - auto applet_ae = sm.GetService("appletAE"); - bool has_signalled = false; - system->SetExitRequested(true); - - if (applet_oe != nullptr) { - applet_oe->GetMessageQueue()->RequestExit(); - has_signalled = true; - } - - if (applet_ae != nullptr && !has_signalled) { - applet_ae->GetMessageQueue()->RequestExit(); - } + system->GetAppletManager().RequestExit(); } void GMainWindow::RequestGameResume() { - auto& sm{system->ServiceManager()}; - auto applet_oe = sm.GetService("appletOE"); - auto applet_ae = sm.GetService("appletAE"); - - if (applet_oe != nullptr) { - applet_oe->GetMessageQueue()->RequestResume(); - return; - } - - if (applet_ae != nullptr) { - applet_ae->GetMessageQueue()->RequestResume(); - } + system->GetAppletManager().RequestResume(); } void GMainWindow::filterBarSetChecked(bool state) {