summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Liam2024-01-02 18:29:03 -0500
committerGravatar Liam2024-01-29 20:17:33 -0500
commit182137a9a4b09c8188d2cbffa312550c5dc83641 (patch)
treeaf62d2ecf774e7790c227cb0984e5392deca5afe
parentam: retrieve main applet creation info from frontend (diff)
downloadyuzu-182137a9a4b09c8188d2cbffa312550c5dc83641.tar.gz
yuzu-182137a9a4b09c8188d2cbffa312550c5dc83641.tar.xz
yuzu-182137a9a4b09c8188d2cbffa312550c5dc83641.zip
am: migrate global state to per-applet state structure
-rw-r--r--src/core/core.cpp9
-rw-r--r--src/core/core.h3
-rw-r--r--src/core/hle/kernel/kernel.cpp30
-rw-r--r--src/core/hle/service/am/am.cpp10
-rw-r--r--src/core/hle/service/am/am_results.h1
-rw-r--r--src/core/hle/service/am/applet_ae.cpp72
-rw-r--r--src/core/hle/service/am/applet_ae.h10
-rw-r--r--src/core/hle/service/am/applet_common_functions.cpp11
-rw-r--r--src/core/hle/service/am/applet_common_functions.h6
-rw-r--r--src/core/hle/service/am/applet_manager.cpp2
-rw-r--r--src/core/hle/service/am/applet_message_queue.cpp7
-rw-r--r--src/core/hle/service/am/applet_message_queue.h1
-rw-r--r--src/core/hle/service/am/applet_oe.cpp35
-rw-r--r--src/core/hle/service/am/applet_oe.h10
-rw-r--r--src/core/hle/service/am/application_functions.cpp156
-rw-r--r--src/core/hle/service/am/application_functions.h13
-rw-r--r--src/core/hle/service/am/application_proxy.cpp21
-rw-r--r--src/core/hle/service/am/application_proxy.h9
-rw-r--r--src/core/hle/service/am/common_state_getter.cpp51
-rw-r--r--src/core/hle/service/am/common_state_getter.h10
-rw-r--r--src/core/hle/service/am/frontend/applets.cpp20
-rw-r--r--src/core/hle/service/am/frontend/applets.h1
-rw-r--r--src/core/hle/service/am/library_applet_accessor.cpp76
-rw-r--r--src/core/hle/service/am/library_applet_accessor.h13
-rw-r--r--src/core/hle/service/am/library_applet_creator.cpp115
-rw-r--r--src/core/hle/service/am/library_applet_creator.h6
-rw-r--r--src/core/hle/service/am/library_applet_proxy.cpp23
-rw-r--r--src/core/hle/service/am/library_applet_proxy.h9
-rw-r--r--src/core/hle/service/am/library_applet_self_accessor.cpp330
-rw-r--r--src/core/hle/service/am/library_applet_self_accessor.h18
-rw-r--r--src/core/hle/service/am/process_winding_controller.cpp35
-rw-r--r--src/core/hle/service/am/process_winding_controller.h6
-rw-r--r--src/core/hle/service/am/self_controller.cpp187
-rw-r--r--src/core/hle/service/am/self_controller.h25
-rw-r--r--src/core/hle/service/am/system_applet_proxy.cpp19
-rw-r--r--src/core/hle/service/am/system_applet_proxy.h8
-rw-r--r--src/core/hle/service/am/window_controller.cpp18
-rw-r--r--src/core/hle/service/am/window_controller.h6
-rw-r--r--src/core/hle/service/vi/vi.cpp8
-rw-r--r--src/yuzu/configuration/configure_input.cpp17
-rw-r--r--src/yuzu/main.cpp28
41 files changed, 687 insertions, 748 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 8c04685a5..435ef6793 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -392,6 +392,7 @@ struct System::Impl {
392 // All threads are started, begin main process execution, now that we're in the clear. 392 // All threads are started, begin main process execution, now that we're in the clear.
393 main_process->Run(load_parameters->main_thread_priority, 393 main_process->Run(load_parameters->main_thread_priority,
394 load_parameters->main_thread_stack_size); 394 load_parameters->main_thread_stack_size);
395 main_process->Close();
395 396
396 if (Settings::values.gamecard_inserted) { 397 if (Settings::values.gamecard_inserted) {
397 if (Settings::values.gamecard_current_game) { 398 if (Settings::values.gamecard_current_game) {
@@ -886,10 +887,6 @@ void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set
886 impl->frontend_applets.SetFrontendAppletSet(std::move(set)); 887 impl->frontend_applets.SetFrontendAppletSet(std::move(set));
887} 888}
888 889
889void System::SetDefaultAppletFrontendSet() {
890 impl->frontend_applets.SetDefaultAppletFrontendSet();
891}
892
893Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() { 890Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
894 return impl->frontend_applets; 891 return impl->frontend_applets;
895} 892}
@@ -898,6 +895,10 @@ const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHold
898 return impl->frontend_applets; 895 return impl->frontend_applets;
899} 896}
900 897
898Service::AM::AppletManager& System::GetAppletManager() {
899 return impl->applet_manager;
900}
901
901void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) { 902void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
902 impl->content_provider = std::move(provider); 903 impl->content_provider = std::move(provider);
903} 904}
diff --git a/src/core/core.h b/src/core/core.h
index 97e2d4b50..90826bd3a 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -350,12 +350,13 @@ public:
350 u64 main_region_size); 350 u64 main_region_size);
351 351
352 void SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set); 352 void SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set);
353 void SetDefaultAppletFrontendSet();
354 353
355 [[nodiscard]] Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder(); 354 [[nodiscard]] Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder();
356 [[nodiscard]] const Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder() 355 [[nodiscard]] const Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder()
357 const; 356 const;
358 357
358 [[nodiscard]] Service::AM::AppletManager& GetAppletManager();
359
359 void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider); 360 void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
360 361
361 [[nodiscard]] FileSys::ContentProvider& GetContentProvider(); 362 [[nodiscard]] FileSys::ContentProvider& GetContentProvider();
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index f3683cdcc..34b25be66 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -97,8 +97,14 @@ struct KernelCore::Impl {
97 RegisterHostThread(nullptr); 97 RegisterHostThread(nullptr);
98 } 98 }
99 99
100 void TerminateApplicationProcess() { 100 void TerminateAllProcesses() {
101 application_process.load()->Terminate(); 101 std::scoped_lock lk{process_list_lock};
102 for (auto& process : process_list) {
103 process->Terminate();
104 process->Close();
105 process = nullptr;
106 }
107 process_list.clear();
102 } 108 }
103 109
104 void Shutdown() { 110 void Shutdown() {
@@ -107,18 +113,9 @@ struct KernelCore::Impl {
107 113
108 CloseServices(); 114 CloseServices();
109 115
110 auto* old_process = application_process.exchange(nullptr); 116 if (application_process) {
111 if (old_process) { 117 application_process->Close();
112 old_process->Close(); 118 application_process = nullptr;
113 }
114
115 {
116 std::scoped_lock lk{process_list_lock};
117 for (auto* const process : process_list) {
118 process->Terminate();
119 process->Close();
120 }
121 process_list.clear();
122 } 119 }
123 120
124 next_object_id = 0; 121 next_object_id = 0;
@@ -354,6 +351,7 @@ struct KernelCore::Impl {
354 351
355 void MakeApplicationProcess(KProcess* process) { 352 void MakeApplicationProcess(KProcess* process) {
356 application_process = process; 353 application_process = process;
354 application_process->Open();
357 } 355 }
358 356
359 static inline thread_local u8 host_thread_id = UINT8_MAX; 357 static inline thread_local u8 host_thread_id = UINT8_MAX;
@@ -779,7 +777,7 @@ struct KernelCore::Impl {
779 // Lists all processes that exist in the current session. 777 // Lists all processes that exist in the current session.
780 std::mutex process_list_lock; 778 std::mutex process_list_lock;
781 std::vector<KProcess*> process_list; 779 std::vector<KProcess*> process_list;
782 std::atomic<KProcess*> application_process{}; 780 KProcess* application_process{};
783 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; 781 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
784 std::unique_ptr<Kernel::KHardwareTimer> hardware_timer; 782 std::unique_ptr<Kernel::KHardwareTimer> hardware_timer;
785 783
@@ -1243,7 +1241,7 @@ void KernelCore::SuspendApplication(bool suspended) {
1243} 1241}
1244 1242
1245void KernelCore::ShutdownCores() { 1243void KernelCore::ShutdownCores() {
1246 impl->TerminateApplicationProcess(); 1244 impl->TerminateAllProcesses();
1247 1245
1248 KScopedSchedulerLock lk{*this}; 1246 KScopedSchedulerLock lk{*this};
1249 1247
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 46bc4f703..8f90eba34 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -3,7 +3,6 @@
3 3
4#include "core/hle/service/am/am.h" 4#include "core/hle/service/am/am.h"
5#include "core/hle/service/am/applet_ae.h" 5#include "core/hle/service/am/applet_ae.h"
6#include "core/hle/service/am/applet_message_queue.h"
7#include "core/hle/service/am/applet_oe.h" 6#include "core/hle/service/am/applet_oe.h"
8#include "core/hle/service/am/idle.h" 7#include "core/hle/service/am/idle.h"
9#include "core/hle/service/am/omm.h" 8#include "core/hle/service/am/omm.h"
@@ -13,13 +12,12 @@
13namespace Service::AM { 12namespace Service::AM {
14 13
15void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { 14void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
16 auto message_queue = std::make_shared<AppletMessageQueue>(system);
17 auto server_manager = std::make_unique<ServerManager>(system); 15 auto server_manager = std::make_unique<ServerManager>(system);
18 16
19 server_manager->RegisterNamedService( 17 server_manager->RegisterNamedService("appletAE",
20 "appletAE", std::make_shared<AppletAE>(nvnflinger, message_queue, system)); 18 std::make_shared<AppletAE>(nvnflinger, system));
21 server_manager->RegisterNamedService( 19 server_manager->RegisterNamedService("appletOE",
22 "appletOE", std::make_shared<AppletOE>(nvnflinger, message_queue, system)); 20 std::make_shared<AppletOE>(nvnflinger, system));
23 server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system)); 21 server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system));
24 server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system)); 22 server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system));
25 server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system)); 23 server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system));
diff --git a/src/core/hle/service/am/am_results.h b/src/core/hle/service/am/am_results.h
index 528b334ad..e82d391ad 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 {
10constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2}; 10constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
11constexpr Result ResultNoMessages{ErrorModule::AM, 3}; 11constexpr Result ResultNoMessages{ErrorModule::AM, 3};
12constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; 12constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
13constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512};
13 14
14} // namespace Service::AM 15} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index bd9e5f505..1b715dea6 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -2,40 +2,15 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/am/applet_ae.h" 4#include "core/hle/service/am/applet_ae.h"
5#include "core/hle/service/am/applet_manager.h"
5#include "core/hle/service/am/library_applet_proxy.h" 6#include "core/hle/service/am/library_applet_proxy.h"
6#include "core/hle/service/am/system_applet_proxy.h" 7#include "core/hle/service/am/system_applet_proxy.h"
7#include "core/hle/service/ipc_helpers.h" 8#include "core/hle/service/ipc_helpers.h"
8 9
9namespace Service::AM { 10namespace Service::AM {
10 11
11void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { 12AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
12 LOG_DEBUG(Service_AM, "called"); 13 : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_} {
13
14 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
15 rb.Push(ResultSuccess);
16 rb.PushIpcInterface<ISystemAppletProxy>(nvnflinger, msg_queue, system);
17}
18
19void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) {
20 LOG_DEBUG(Service_AM, "called");
21
22 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
23 rb.Push(ResultSuccess);
24 rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, msg_queue, system);
25}
26
27void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) {
28 LOG_DEBUG(Service_AM, "called");
29
30 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
31 rb.Push(ResultSuccess);
32 rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, msg_queue, system);
33}
34
35AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_,
36 std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_)
37 : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_},
38 msg_queue{std::move(msg_queue_)} {
39 // clang-format off 14 // clang-format off
40 static const FunctionInfo functions[] = { 15 static const FunctionInfo functions[] = {
41 {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, 16 {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
@@ -54,8 +29,45 @@ AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_,
54 29
55AppletAE::~AppletAE() = default; 30AppletAE::~AppletAE() = default;
56 31
57const std::shared_ptr<AppletMessageQueue>& AppletAE::GetMessageQueue() const { 32void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) {
58 return msg_queue; 33 LOG_DEBUG(Service_AM, "called");
34
35 if (const auto applet = GetAppletFromContext(ctx)) {
36 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
37 rb.Push(ResultSuccess);
38 rb.PushIpcInterface<ISystemAppletProxy>(nvnflinger, applet, system);
39 } else {
40 UNIMPLEMENTED();
41
42 IPC::ResponseBuilder rb{ctx, 2};
43 rb.Push(ResultUnknown);
44 }
45}
46
47void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) {
48 LOG_DEBUG(Service_AM, "called");
49
50 if (const auto applet = GetAppletFromContext(ctx)) {
51 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
52 rb.Push(ResultSuccess);
53 rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, applet, system);
54 } else {
55 UNIMPLEMENTED();
56
57 IPC::ResponseBuilder rb{ctx, 2};
58 rb.Push(ResultUnknown);
59 }
60}
61
62void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) {
63 LOG_DEBUG(Service_AM, "called");
64
65 return OpenLibraryAppletProxy(ctx);
66}
67
68std::shared_ptr<Applet> AppletAE::GetAppletFromContext(HLERequestContext& ctx) {
69 const auto aruid = ctx.GetPID();
70 return system.GetAppletManager().GetByAppletResourceUserId(aruid);
59} 71}
60 72
61} // namespace Service::AM 73} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h
index 538ce2903..3d7961fa1 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;
18 18
19namespace AM { 19namespace AM {
20 20
21class AppletMessageQueue; 21struct Applet;
22 22
23class AppletAE final : public ServiceFramework<AppletAE> { 23class AppletAE final : public ServiceFramework<AppletAE> {
24public: 24public:
25 explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, 25 explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_);
26 std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_);
27 ~AppletAE() override; 26 ~AppletAE() override;
28 27
29 const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const;
30
31private: 28private:
32 void OpenSystemAppletProxy(HLERequestContext& ctx); 29 void OpenSystemAppletProxy(HLERequestContext& ctx);
33 void OpenLibraryAppletProxy(HLERequestContext& ctx); 30 void OpenLibraryAppletProxy(HLERequestContext& ctx);
34 void OpenLibraryAppletProxyOld(HLERequestContext& ctx); 31 void OpenLibraryAppletProxyOld(HLERequestContext& ctx);
35 32
33 std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx);
34
36 Nvnflinger::Nvnflinger& nvnflinger; 35 Nvnflinger::Nvnflinger& nvnflinger;
37 std::shared_ptr<AppletMessageQueue> msg_queue;
38}; 36};
39 37
40} // namespace AM 38} // 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 81c01a48b..a5c54ce87 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 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/am/applet.h"
4#include "core/hle/service/am/applet_common_functions.h" 5#include "core/hle/service/am/applet_common_functions.h"
5#include "core/hle/service/ipc_helpers.h" 6#include "core/hle/service/ipc_helpers.h"
6 7
7namespace Service::AM { 8namespace Service::AM {
8 9
9IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_) 10IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
10 : ServiceFramework{system_, "IAppletCommonFunctions"} { 11 std::shared_ptr<Applet> applet_)
12 : ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} {
11 // clang-format off 13 // clang-format off
12 static const FunctionInfo functions[] = { 14 static const FunctionInfo functions[] = {
13 {0, nullptr, "SetTerminateResult"}, 15 {0, nullptr, "SetTerminateResult"},
@@ -40,6 +42,11 @@ IAppletCommonFunctions::~IAppletCommonFunctions() = default;
40void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) { 42void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
41 LOG_WARNING(Service_AM, "(STUBBED) called"); 43 LOG_WARNING(Service_AM, "(STUBBED) called");
42 44
45 IPC::RequestParser rp{ctx};
46
47 std::scoped_lock lk{applet->lock};
48 applet->cpu_boost_request_priority = rp.Pop<s32>();
49
43 IPC::ResponseBuilder rb{ctx, 2}; 50 IPC::ResponseBuilder rb{ctx, 2};
44 rb.Push(ResultSuccess); 51 rb.Push(ResultSuccess);
45} 52}
diff --git a/src/core/hle/service/am/applet_common_functions.h b/src/core/hle/service/am/applet_common_functions.h
index be87b3820..229555669 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 @@
7 7
8namespace Service::AM { 8namespace Service::AM {
9 9
10struct Applet;
11
10class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> { 12class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
11public: 13public:
12 explicit IAppletCommonFunctions(Core::System& system_); 14 explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
13 ~IAppletCommonFunctions() override; 15 ~IAppletCommonFunctions() override;
14 16
15private: 17private:
16 void SetCpuBoostRequestPriority(HLERequestContext& ctx); 18 void SetCpuBoostRequestPriority(HLERequestContext& ctx);
19
20 const std::shared_ptr<Applet> applet;
17}; 21};
18 22
19} // namespace Service::AM 23} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp
index 4aac5dba7..efbd0108c 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(
294 } 294 }
295 295
296 // Applet was started by frontend, so it is foreground. 296 // Applet was started by frontend, so it is foreground.
297 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
298 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); 297 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
298 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
299 applet->focus_state = FocusState::InFocus; 299 applet->focus_state = FocusState::InFocus;
300 300
301 this->InsertApplet(std::move(applet)); 301 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 e4931031d..5ed996b70 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() {
26} 26}
27 27
28void AppletMessageQueue::PushMessage(AppletMessage msg) { 28void AppletMessageQueue::PushMessage(AppletMessage msg) {
29 messages.push(msg); 29 {
30 std::scoped_lock lk{lock};
31 messages.push(msg);
32 }
30 on_new_message->Signal(); 33 on_new_message->Signal();
31} 34}
32 35
33AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { 36AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
37 std::scoped_lock lk{lock};
34 if (messages.empty()) { 38 if (messages.empty()) {
35 on_new_message->Clear(); 39 on_new_message->Clear();
36 return AppletMessage::None; 40 return AppletMessage::None;
@@ -44,6 +48,7 @@ AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
44} 48}
45 49
46std::size_t AppletMessageQueue::GetMessageCount() const { 50std::size_t AppletMessageQueue::GetMessageCount() const {
51 std::scoped_lock lk{lock};
47 return messages.size(); 52 return messages.size();
48} 53}
49 54
diff --git a/src/core/hle/service/am/applet_message_queue.h b/src/core/hle/service/am/applet_message_queue.h
index 60145aae9..5cb236d47 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:
69 Kernel::KEvent* on_new_message; 69 Kernel::KEvent* on_new_message;
70 Kernel::KEvent* on_operation_mode_changed; 70 Kernel::KEvent* on_operation_mode_changed;
71 71
72 mutable std::mutex lock;
72 std::queue<AppletMessage> messages; 73 std::queue<AppletMessage> messages;
73}; 74};
74 75
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index f373d1136..56bafd162 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -2,24 +2,15 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/am/am.h" 4#include "core/hle/service/am/am.h"
5#include "core/hle/service/am/applet_manager.h"
5#include "core/hle/service/am/applet_oe.h" 6#include "core/hle/service/am/applet_oe.h"
6#include "core/hle/service/am/application_proxy.h" 7#include "core/hle/service/am/application_proxy.h"
7#include "core/hle/service/ipc_helpers.h" 8#include "core/hle/service/ipc_helpers.h"
8 9
9namespace Service::AM { 10namespace Service::AM {
10 11
11void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { 12AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
12 LOG_DEBUG(Service_AM, "called"); 13 : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_} {
13
14 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
15 rb.Push(ResultSuccess);
16 rb.PushIpcInterface<IApplicationProxy>(nvnflinger, msg_queue, system);
17}
18
19AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_,
20 std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_)
21 : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_},
22 msg_queue{std::move(msg_queue_)} {
23 static const FunctionInfo functions[] = { 14 static const FunctionInfo functions[] = {
24 {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, 15 {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
25 }; 16 };
@@ -28,8 +19,24 @@ AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_,
28 19
29AppletOE::~AppletOE() = default; 20AppletOE::~AppletOE() = default;
30 21
31const std::shared_ptr<AppletMessageQueue>& AppletOE::GetMessageQueue() const { 22void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
32 return msg_queue; 23 LOG_DEBUG(Service_AM, "called");
24
25 if (const auto applet = GetAppletFromContext(ctx)) {
26 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
27 rb.Push(ResultSuccess);
28 rb.PushIpcInterface<IApplicationProxy>(nvnflinger, applet, system);
29 } else {
30 UNIMPLEMENTED();
31
32 IPC::ResponseBuilder rb{ctx, 2};
33 rb.Push(ResultUnknown);
34 }
35}
36
37std::shared_ptr<Applet> AppletOE::GetAppletFromContext(HLERequestContext& ctx) {
38 const auto aruid = ctx.GetPID();
39 return system.GetAppletManager().GetByAppletResourceUserId(aruid);
33} 40}
34 41
35} // namespace Service::AM 42} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h
index 39eccc4ab..f2ba1c924 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;
18 18
19namespace AM { 19namespace AM {
20 20
21class AppletMessageQueue; 21struct Applet;
22 22
23class AppletOE final : public ServiceFramework<AppletOE> { 23class AppletOE final : public ServiceFramework<AppletOE> {
24public: 24public:
25 explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, 25 explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_);
26 std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_);
27 ~AppletOE() override; 26 ~AppletOE() override;
28 27
29 const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const;
30
31private: 28private:
32 void OpenApplicationProxy(HLERequestContext& ctx); 29 void OpenApplicationProxy(HLERequestContext& ctx);
33 30
31 std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx);
32
34 Nvnflinger::Nvnflinger& nvnflinger; 33 Nvnflinger::Nvnflinger& nvnflinger;
35 std::shared_ptr<AppletMessageQueue> msg_queue;
36}; 34};
37 35
38} // namespace AM 36} // namespace AM
diff --git a/src/core/hle/service/am/application_functions.cpp b/src/core/hle/service/am/application_functions.cpp
index fef45c732..51c5be2d1 100644
--- a/src/core/hle/service/am/application_functions.cpp
+++ b/src/core/hle/service/am/application_functions.cpp
@@ -9,6 +9,7 @@
9#include "core/file_sys/savedata_factory.h" 9#include "core/file_sys/savedata_factory.h"
10#include "core/hle/service/acc/profile_manager.h" 10#include "core/hle/service/acc/profile_manager.h"
11#include "core/hle/service/am/am_results.h" 11#include "core/hle/service/am/am_results.h"
12#include "core/hle/service/am/applet.h"
12#include "core/hle/service/am/application_functions.h" 13#include "core/hle/service/am/application_functions.h"
13#include "core/hle/service/am/storage.h" 14#include "core/hle/service/am/storage.h"
14#include "core/hle/service/filesystem/filesystem.h" 15#include "core/hle/service/filesystem/filesystem.h"
@@ -24,19 +25,8 @@ enum class LaunchParameterKind : u32 {
24 AccountPreselectedUser = 2, 25 AccountPreselectedUser = 2,
25}; 26};
26 27
27constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA; 28IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_)
28 29 : ServiceFramework{system_, "IApplicationFunctions"}, applet{std::move(applet_)} {
29struct LaunchParameterAccountPreselectedUser {
30 u32_le magic;
31 u32_le is_account_selected;
32 Common::UUID current_user;
33 INSERT_PADDING_BYTES(0x70);
34};
35static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
36
37IApplicationFunctions::IApplicationFunctions(Core::System& system_)
38 : ServiceFramework{system_, "IApplicationFunctions"},
39 service_context{system, "IApplicationFunctions"} {
40 // clang-format off 30 // clang-format off
41 static const FunctionInfo functions[] = { 31 static const FunctionInfo functions[] = {
42 {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, 32 {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
@@ -105,27 +95,16 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
105 // clang-format on 95 // clang-format on
106 96
107 RegisterHandlers(functions); 97 RegisterHandlers(functions);
108
109 gpu_error_detected_event =
110 service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent");
111 friend_invitation_storage_channel_event =
112 service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent");
113 notification_storage_channel_event =
114 service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent");
115 health_warning_disappeared_system_event =
116 service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent");
117} 98}
118 99
119IApplicationFunctions::~IApplicationFunctions() { 100IApplicationFunctions::~IApplicationFunctions() = default;
120 service_context.CloseEvent(gpu_error_detected_event);
121 service_context.CloseEvent(friend_invitation_storage_channel_event);
122 service_context.CloseEvent(notification_storage_channel_event);
123 service_context.CloseEvent(health_warning_disappeared_system_event);
124}
125 101
126void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) { 102void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
127 LOG_WARNING(Service_AM, "(STUBBED) called"); 103 LOG_WARNING(Service_AM, "(STUBBED) called");
128 104
105 std::scoped_lock lk{applet->lock};
106 applet->application_crash_report_enabled = true;
107
129 IPC::ResponseBuilder rb{ctx, 2}; 108 IPC::ResponseBuilder rb{ctx, 2};
130 rb.Push(ResultSuccess); 109 rb.Push(ResultSuccess);
131} 110}
@@ -157,6 +136,10 @@ void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext&
157void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { 136void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
158 LOG_WARNING(Service_AM, "(STUBBED) called"); 137 LOG_WARNING(Service_AM, "(STUBBED) called");
159 138
139 std::scoped_lock lk{applet->lock};
140 applet->home_button_long_pressed_blocked = true;
141 applet->home_button_short_pressed_blocked = true;
142
160 IPC::ResponseBuilder rb{ctx, 2}; 143 IPC::ResponseBuilder rb{ctx, 2};
161 rb.Push(ResultSuccess); 144 rb.Push(ResultSuccess);
162} 145}
@@ -164,6 +147,10 @@ void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLEReques
164void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { 147void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
165 LOG_WARNING(Service_AM, "(STUBBED) called"); 148 LOG_WARNING(Service_AM, "(STUBBED) called");
166 149
150 std::scoped_lock lk{applet->lock};
151 applet->home_button_long_pressed_blocked = false;
152 applet->home_button_short_pressed_blocked = false;
153
167 IPC::ResponseBuilder rb{ctx, 2}; 154 IPC::ResponseBuilder rb{ctx, 2};
168 rb.Push(ResultSuccess); 155 rb.Push(ResultSuccess);
169} 156}
@@ -171,6 +158,11 @@ void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestC
171void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) { 158void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
172 LOG_WARNING(Service_AM, "(STUBBED) called"); 159 LOG_WARNING(Service_AM, "(STUBBED) called");
173 160
161 std::scoped_lock lk{applet->lock};
162 applet->home_button_long_pressed_blocked = true;
163 applet->home_button_short_pressed_blocked = true;
164 applet->home_button_double_click_enabled = true;
165
174 IPC::ResponseBuilder rb{ctx, 2}; 166 IPC::ResponseBuilder rb{ctx, 2};
175 rb.Push(ResultSuccess); 167 rb.Push(ResultSuccess);
176} 168}
@@ -178,6 +170,11 @@ void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
178void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) { 170void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
179 LOG_WARNING(Service_AM, "(STUBBED) called"); 171 LOG_WARNING(Service_AM, "(STUBBED) called");
180 172
173 std::scoped_lock lk{applet->lock};
174 applet->home_button_long_pressed_blocked = false;
175 applet->home_button_short_pressed_blocked = false;
176 applet->home_button_double_click_enabled = false;
177
181 IPC::ResponseBuilder rb{ctx, 2}; 178 IPC::ResponseBuilder rb{ctx, 2};
182 rb.Push(ResultSuccess); 179 rb.Push(ResultSuccess);
183} 180}
@@ -188,47 +185,25 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
188 185
189 LOG_INFO(Service_AM, "called, kind={:08X}", kind); 186 LOG_INFO(Service_AM, "called, kind={:08X}", kind);
190 187
191 if (kind == LaunchParameterKind::UserChannel) { 188 std::scoped_lock lk{applet->lock};
192 auto channel = system.GetUserChannel();
193 if (channel.empty()) {
194 LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
195 IPC::ResponseBuilder rb{ctx, 2};
196 rb.Push(AM::ResultNoDataInChannel);
197 return;
198 }
199
200 auto data = channel.back();
201 channel.pop_back();
202
203 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
204 rb.Push(ResultSuccess);
205 rb.PushIpcInterface<IStorage>(system, std::move(data));
206 } else if (kind == LaunchParameterKind::AccountPreselectedUser &&
207 !launch_popped_account_preselect) {
208 // TODO: Verify this is hw-accurate
209 LaunchParameterAccountPreselectedUser params{};
210
211 params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
212 params.is_account_selected = 1;
213
214 Account::ProfileManager profile_manager{};
215 const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user));
216 ASSERT(uuid.has_value() && uuid->IsValid());
217 params.current_user = *uuid;
218 189
219 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 190 auto& channel = kind == LaunchParameterKind::UserChannel
220 rb.Push(ResultSuccess); 191 ? applet->user_channel_launch_parameter
192 : applet->preselected_user_launch_parameter;
221 193
222 std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); 194 if (channel.empty()) {
223 std::memcpy(buffer.data(), &params, buffer.size()); 195 LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", kind);
224
225 rb.PushIpcInterface<IStorage>(system, std::move(buffer));
226 launch_popped_account_preselect = true;
227 } else {
228 LOG_ERROR(Service_AM, "Unknown launch parameter kind.");
229 IPC::ResponseBuilder rb{ctx, 2}; 196 IPC::ResponseBuilder rb{ctx, 2};
230 rb.Push(AM::ResultNoDataInChannel); 197 rb.Push(AM::ResultNoDataInChannel);
198 return;
231 } 199 }
200
201 auto data = channel.back();
202 channel.pop_back();
203
204 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
205 rb.Push(ResultSuccess);
206 rb.PushIpcInterface<IStorage>(system, std::move(data));
232} 207}
233 208
234void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { 209void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
@@ -245,7 +220,7 @@ void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
245 LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); 220 LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
246 221
247 FileSys::SaveDataAttribute attribute{}; 222 FileSys::SaveDataAttribute attribute{};
248 attribute.title_id = system.GetApplicationProcessProgramID(); 223 attribute.title_id = applet->program_id;
249 attribute.user_id = user_id; 224 attribute.user_id = user_id;
250 attribute.type = FileSys::SaveDataType::SaveData; 225 attribute.type = FileSys::SaveDataType::SaveData;
251 226
@@ -267,6 +242,9 @@ void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) {
267 u32 result = rp.Pop<u32>(); 242 u32 result = rp.Pop<u32>();
268 LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result); 243 LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
269 244
245 std::scoped_lock lk{applet->lock};
246 applet->terminate_result = Result(result);
247
270 IPC::ResponseBuilder rb{ctx, 2}; 248 IPC::ResponseBuilder rb{ctx, 2};
271 rb.Push(ResultSuccess); 249 rb.Push(ResultSuccess);
272} 250}
@@ -277,16 +255,14 @@ void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) {
277 std::array<u8, 0x10> version_string{}; 255 std::array<u8, 0x10> version_string{};
278 256
279 const auto res = [this] { 257 const auto res = [this] {
280 const auto title_id = system.GetApplicationProcessProgramID(); 258 const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
281
282 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
283 system.GetContentProvider()}; 259 system.GetContentProvider()};
284 auto metadata = pm.GetControlMetadata(); 260 auto metadata = pm.GetControlMetadata();
285 if (metadata.first != nullptr) { 261 if (metadata.first != nullptr) {
286 return metadata; 262 return metadata;
287 } 263 }
288 264
289 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), 265 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
290 system.GetFileSystemController(), 266 system.GetFileSystemController(),
291 system.GetContentProvider()}; 267 system.GetContentProvider()};
292 return pm_update.GetControlMetadata(); 268 return pm_update.GetControlMetadata();
@@ -314,16 +290,14 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
314 u32 supported_languages = 0; 290 u32 supported_languages = 0;
315 291
316 const auto res = [this] { 292 const auto res = [this] {
317 const auto title_id = system.GetApplicationProcessProgramID(); 293 const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
318
319 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
320 system.GetContentProvider()}; 294 system.GetContentProvider()};
321 auto metadata = pm.GetControlMetadata(); 295 auto metadata = pm.GetControlMetadata();
322 if (metadata.first != nullptr) { 296 if (metadata.first != nullptr) {
323 return metadata; 297 return metadata;
324 } 298 }
325 299
326 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), 300 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
327 system.GetFileSystemController(), 301 system.GetFileSystemController(),
328 system.GetContentProvider()}; 302 system.GetContentProvider()};
329 return pm_update.GetControlMetadata(); 303 return pm_update.GetControlMetadata();
@@ -368,11 +342,9 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
368void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { 342void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
369 LOG_WARNING(Service_AM, "(STUBBED) called"); 343 LOG_WARNING(Service_AM, "(STUBBED) called");
370 344
371 constexpr bool gameplay_recording_supported = false;
372
373 IPC::ResponseBuilder rb{ctx, 3}; 345 IPC::ResponseBuilder rb{ctx, 3};
374 rb.Push(ResultSuccess); 346 rb.Push(ResultSuccess);
375 rb.Push(gameplay_recording_supported); 347 rb.Push(applet->gameplay_recording_supported);
376} 348}
377 349
378void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) { 350void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
@@ -385,6 +357,11 @@ void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx)
385void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) { 357void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
386 LOG_WARNING(Service_AM, "(STUBBED) called"); 358 LOG_WARNING(Service_AM, "(STUBBED) called");
387 359
360 IPC::RequestParser rp{ctx};
361
362 std::scoped_lock lk{applet->lock};
363 applet->gameplay_recording_state = rp.PopRaw<GameplayRecordingState>();
364
388 IPC::ResponseBuilder rb{ctx, 2}; 365 IPC::ResponseBuilder rb{ctx, 2};
389 rb.Push(ResultSuccess); 366 rb.Push(ResultSuccess);
390} 367}
@@ -392,6 +369,9 @@ void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
392void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) { 369void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
393 LOG_WARNING(Service_AM, "(STUBBED) called"); 370 LOG_WARNING(Service_AM, "(STUBBED) called");
394 371
372 std::scoped_lock lk{applet->lock};
373 applet->is_running = true;
374
395 IPC::ResponseBuilder rb{ctx, 3}; 375 IPC::ResponseBuilder rb{ctx, 3};
396 rb.Push(ResultSuccess); 376 rb.Push(ResultSuccess);
397 rb.Push<u8>(0); // Unknown, seems to be ignored by official processes 377 rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
@@ -426,8 +406,7 @@ void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
426 static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size); 406 static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
427 407
428 system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize( 408 system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
429 type, system.GetApplicationProcessProgramID(), user_id, 409 type, applet->program_id, user_id, {new_normal_size, new_journal_size});
430 {new_normal_size, new_journal_size});
431 410
432 IPC::ResponseBuilder rb{ctx, 4}; 411 IPC::ResponseBuilder rb{ctx, 4};
433 rb.Push(ResultSuccess); 412 rb.Push(ResultSuccess);
@@ -451,7 +430,7 @@ void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
451 user_id[0]); 430 user_id[0]);
452 431
453 const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize( 432 const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
454 type, system.GetApplicationProcessProgramID(), user_id); 433 type, applet->program_id, user_id);
455 434
456 IPC::ResponseBuilder rb{ctx, 6}; 435 IPC::ResponseBuilder rb{ctx, 6};
457 rb.Push(ResultSuccess); 436 rb.Push(ResultSuccess);
@@ -528,13 +507,15 @@ void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
528 IPC::ResponseBuilder rb{ctx, 2}; 507 IPC::ResponseBuilder rb{ctx, 2};
529 rb.Push(ResultSuccess); 508 rb.Push(ResultSuccess);
530 509
510 // Swap user channel ownership into the system so that it will be preserved
511 system.GetUserChannel().swap(applet->user_channel_launch_parameter);
531 system.ExecuteProgram(program_index); 512 system.ExecuteProgram(program_index);
532} 513}
533 514
534void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) { 515void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
535 LOG_DEBUG(Service_AM, "called"); 516 LOG_DEBUG(Service_AM, "called");
536 517
537 system.GetUserChannel().clear(); 518 applet->user_channel_launch_parameter.clear();
538 519
539 IPC::ResponseBuilder rb{ctx, 2}; 520 IPC::ResponseBuilder rb{ctx, 2};
540 rb.Push(ResultSuccess); 521 rb.Push(ResultSuccess);
@@ -546,7 +527,7 @@ void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
546 IPC::RequestParser rp{ctx}; 527 IPC::RequestParser rp{ctx};
547 const auto storage = rp.PopIpcInterface<IStorage>().lock(); 528 const auto storage = rp.PopIpcInterface<IStorage>().lock();
548 if (storage) { 529 if (storage) {
549 system.GetUserChannel().push_back(storage->GetData()); 530 applet->user_channel_launch_parameter.push_back(storage->GetData());
550 } 531 }
551 532
552 IPC::ResponseBuilder rb{ctx, 2}; 533 IPC::ResponseBuilder rb{ctx, 2};
@@ -558,7 +539,7 @@ void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) {
558 539
559 IPC::ResponseBuilder rb{ctx, 3}; 540 IPC::ResponseBuilder rb{ctx, 3};
560 rb.Push(ResultSuccess); 541 rb.Push(ResultSuccess);
561 rb.Push<s32>(previous_program_index); 542 rb.Push<s32>(applet->previous_program_index);
562} 543}
563 544
564void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) { 545void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
@@ -566,7 +547,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ct
566 547
567 IPC::ResponseBuilder rb{ctx, 2, 1}; 548 IPC::ResponseBuilder rb{ctx, 2, 1};
568 rb.Push(ResultSuccess); 549 rb.Push(ResultSuccess);
569 rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent()); 550 rb.PushCopyObjects(applet->gpu_error_detected_event.GetHandle());
570} 551}
571 552
572void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) { 553void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
@@ -574,7 +555,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestCon
574 555
575 IPC::ResponseBuilder rb{ctx, 2, 1}; 556 IPC::ResponseBuilder rb{ctx, 2, 1};
576 rb.Push(ResultSuccess); 557 rb.Push(ResultSuccess);
577 rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent()); 558 rb.PushCopyObjects(applet->friend_invitation_storage_channel_event.GetHandle());
578} 559}
579 560
580void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) { 561void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
@@ -589,7 +570,7 @@ void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext
589 570
590 IPC::ResponseBuilder rb{ctx, 2, 1}; 571 IPC::ResponseBuilder rb{ctx, 2, 1};
591 rb.Push(ResultSuccess); 572 rb.Push(ResultSuccess);
592 rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent()); 573 rb.PushCopyObjects(applet->notification_storage_channel_event.GetHandle());
593} 574}
594 575
595void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) { 576void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
@@ -597,12 +578,15 @@ void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestCon
597 578
598 IPC::ResponseBuilder rb{ctx, 2, 1}; 579 IPC::ResponseBuilder rb{ctx, 2, 1};
599 rb.Push(ResultSuccess); 580 rb.Push(ResultSuccess);
600 rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent()); 581 rb.PushCopyObjects(applet->health_warning_disappeared_system_event.GetHandle());
601} 582}
602 583
603void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) { 584void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
604 LOG_WARNING(Service_AM, "(STUBBED) called"); 585 LOG_WARNING(Service_AM, "(STUBBED) called");
605 586
587 std::scoped_lock lk{applet->lock};
588 applet->jit_service_launched = true;
589
606 IPC::ResponseBuilder rb{ctx, 2}; 590 IPC::ResponseBuilder rb{ctx, 2};
607 rb.Push(ResultSuccess); 591 rb.Push(ResultSuccess);
608} 592}
diff --git a/src/core/hle/service/am/application_functions.h b/src/core/hle/service/am/application_functions.h
index 22aab1c8f..55eb21d39 100644
--- a/src/core/hle/service/am/application_functions.h
+++ b/src/core/hle/service/am/application_functions.h
@@ -8,9 +8,11 @@
8 8
9namespace Service::AM { 9namespace Service::AM {
10 10
11struct Applet;
12
11class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { 13class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
12public: 14public:
13 explicit IApplicationFunctions(Core::System& system_); 15 explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
14 ~IApplicationFunctions() override; 16 ~IApplicationFunctions() override;
15 17
16private: 18private:
@@ -50,14 +52,7 @@ private:
50 void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx); 52 void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
51 void PrepareForJit(HLERequestContext& ctx); 53 void PrepareForJit(HLERequestContext& ctx);
52 54
53 KernelHelpers::ServiceContext service_context; 55 const std::shared_ptr<Applet> applet;
54
55 bool launch_popped_account_preselect = false;
56 s32 previous_program_index{-1};
57 Kernel::KEvent* gpu_error_detected_event;
58 Kernel::KEvent* friend_invitation_storage_channel_event;
59 Kernel::KEvent* notification_storage_channel_event;
60 Kernel::KEvent* health_warning_disappeared_system_event;
61}; 56};
62 57
63} // namespace Service::AM 58} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_proxy.cpp b/src/core/hle/service/am/application_proxy.cpp
index e9cd0aa71..99e97f4bc 100644
--- a/src/core/hle/service/am/application_proxy.cpp
+++ b/src/core/hle/service/am/application_proxy.cpp
@@ -18,10 +18,9 @@
18namespace Service::AM { 18namespace Service::AM {
19 19
20IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, 20IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
21 std::shared_ptr<AppletMessageQueue> msg_queue_, 21 std::shared_ptr<Applet> applet_, Core::System& system_)
22 Core::System& system_) 22 : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
23 : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, 23 applet_)} {
24 msg_queue{std::move(msg_queue_)} {
25 // clang-format off 24 // clang-format off
26 static const FunctionInfo functions[] = { 25 static const FunctionInfo functions[] = {
27 {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, 26 {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
@@ -39,6 +38,8 @@ IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
39 RegisterHandlers(functions); 38 RegisterHandlers(functions);
40} 39}
41 40
41IApplicationProxy::~IApplicationProxy() = default;
42
42void IApplicationProxy::GetAudioController(HLERequestContext& ctx) { 43void IApplicationProxy::GetAudioController(HLERequestContext& ctx) {
43 LOG_DEBUG(Service_AM, "called"); 44 LOG_DEBUG(Service_AM, "called");
44 45
@@ -60,7 +61,7 @@ void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) {
60 61
61 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 62 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
62 rb.Push(ResultSuccess); 63 rb.Push(ResultSuccess);
63 rb.PushIpcInterface<IProcessWindingController>(system); 64 rb.PushIpcInterface<IProcessWindingController>(system, applet);
64} 65}
65 66
66void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) { 67void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) {
@@ -76,7 +77,7 @@ void IApplicationProxy::GetWindowController(HLERequestContext& ctx) {
76 77
77 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 78 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
78 rb.Push(ResultSuccess); 79 rb.Push(ResultSuccess);
79 rb.PushIpcInterface<IWindowController>(system); 80 rb.PushIpcInterface<IWindowController>(system, applet);
80} 81}
81 82
82void IApplicationProxy::GetSelfController(HLERequestContext& ctx) { 83void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
@@ -84,7 +85,7 @@ void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
84 85
85 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 86 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
86 rb.Push(ResultSuccess); 87 rb.Push(ResultSuccess);
87 rb.PushIpcInterface<ISelfController>(system, nvnflinger); 88 rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
88} 89}
89 90
90void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) { 91void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) {
@@ -92,7 +93,7 @@ void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) {
92 93
93 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 94 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
94 rb.Push(ResultSuccess); 95 rb.Push(ResultSuccess);
95 rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); 96 rb.PushIpcInterface<ICommonStateGetter>(system, applet);
96} 97}
97 98
98void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { 99void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
@@ -100,7 +101,7 @@ void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
100 101
101 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 102 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
102 rb.Push(ResultSuccess); 103 rb.Push(ResultSuccess);
103 rb.PushIpcInterface<ILibraryAppletCreator>(system); 104 rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
104} 105}
105 106
106void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) { 107void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
@@ -108,7 +109,7 @@ void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
108 109
109 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 110 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
110 rb.Push(ResultSuccess); 111 rb.Push(ResultSuccess);
111 rb.PushIpcInterface<IApplicationFunctions>(system); 112 rb.PushIpcInterface<IApplicationFunctions>(system, applet);
112} 113}
113 114
114} // namespace Service::AM 115} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_proxy.h b/src/core/hle/service/am/application_proxy.h
index 4f620242b..eb98b095c 100644
--- a/src/core/hle/service/am/application_proxy.h
+++ b/src/core/hle/service/am/application_proxy.h
@@ -3,16 +3,17 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/am/applet_message_queue.h"
7#include "core/hle/service/service.h" 6#include "core/hle/service/service.h"
8 7
9namespace Service::AM { 8namespace Service::AM {
10 9
10struct Applet;
11
11class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { 12class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
12public: 13public:
13 explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, 14 explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
14 std::shared_ptr<AppletMessageQueue> msg_queue_, 15 std::shared_ptr<Applet> msg_queue_, Core::System& system_);
15 Core::System& system_); 16 ~IApplicationProxy();
16 17
17private: 18private:
18 void GetAudioController(HLERequestContext& ctx); 19 void GetAudioController(HLERequestContext& ctx);
@@ -26,7 +27,7 @@ private:
26 void GetApplicationFunctions(HLERequestContext& ctx); 27 void GetApplicationFunctions(HLERequestContext& ctx);
27 28
28 Nvnflinger::Nvnflinger& nvnflinger; 29 Nvnflinger::Nvnflinger& nvnflinger;
29 std::shared_ptr<AppletMessageQueue> msg_queue; 30 std::shared_ptr<Applet> applet;
30}; 31};
31 32
32} // namespace Service::AM 33} // 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 0b54b769d..77f3fd868 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 @@
3 3
4#include "common/settings.h" 4#include "common/settings.h"
5#include "core/hle/service/am/am_results.h" 5#include "core/hle/service/am/am_results.h"
6#include "core/hle/service/am/applet.h"
6#include "core/hle/service/am/common_state_getter.h" 7#include "core/hle/service/am/common_state_getter.h"
7#include "core/hle/service/am/lock_accessor.h" 8#include "core/hle/service/am/lock_accessor.h"
8#include "core/hle/service/apm/apm_controller.h" 9#include "core/hle/service/apm/apm_controller.h"
@@ -14,10 +15,8 @@
14 15
15namespace Service::AM { 16namespace Service::AM {
16 17
17ICommonStateGetter::ICommonStateGetter(Core::System& system_, 18ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_)
18 std::shared_ptr<AppletMessageQueue> msg_queue_) 19 : ServiceFramework{system_, "ICommonStateGetter"}, applet{std::move(applet_)} {
19 : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)},
20 service_context{system_, "ICommonStateGetter"} {
21 // clang-format off 20 // clang-format off
22 static const FunctionInfo functions[] = { 21 static const FunctionInfo functions[] = {
23 {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, 22 {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
@@ -75,17 +74,9 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
75 // clang-format on 74 // clang-format on
76 75
77 RegisterHandlers(functions); 76 RegisterHandlers(functions);
78
79 sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent");
80
81 // Configure applets to be in foreground state
82 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
83 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
84} 77}
85 78
86ICommonStateGetter::~ICommonStateGetter() { 79ICommonStateGetter::~ICommonStateGetter() = default;
87 service_context.CloseEvent(sleep_lock_event);
88};
89 80
90void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { 81void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
91 LOG_DEBUG(Service_AM, "called"); 82 LOG_DEBUG(Service_AM, "called");
@@ -96,17 +87,17 @@ void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
96} 87}
97 88
98void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) { 89void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) {
99 LOG_DEBUG(Service_AM, "called"); 90 LOG_DEBUG(Service_AM, "(STUBBED) called");
100 91
101 IPC::ResponseBuilder rb{ctx, 2, 1}; 92 IPC::ResponseBuilder rb{ctx, 2, 1};
102 rb.Push(ResultSuccess); 93 rb.Push(ResultSuccess);
103 rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent()); 94 rb.PushCopyObjects(applet->message_queue.GetMessageReceiveEvent());
104} 95}
105 96
106void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) { 97void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
107 LOG_DEBUG(Service_AM, "called"); 98 LOG_DEBUG(Service_AM, "called");
108 99
109 const auto message = msg_queue->PopMessage(); 100 const auto message = applet->message_queue.PopMessage();
110 IPC::ResponseBuilder rb{ctx, 3}; 101 IPC::ResponseBuilder rb{ctx, 3};
111 102
112 if (message == AppletMessageQueue::AppletMessage::None) { 103 if (message == AppletMessageQueue::AppletMessage::None) {
@@ -123,9 +114,11 @@ void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
123void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) { 114void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
124 LOG_DEBUG(Service_AM, "(STUBBED) called"); 115 LOG_DEBUG(Service_AM, "(STUBBED) called");
125 116
117 std::scoped_lock lk{applet->lock};
118
126 IPC::ResponseBuilder rb{ctx, 3}; 119 IPC::ResponseBuilder rb{ctx, 3};
127 rb.Push(ResultSuccess); 120 rb.Push(ResultSuccess);
128 rb.Push(static_cast<u8>(FocusState::InFocus)); 121 rb.Push(static_cast<u8>(applet->focus_state));
129} 122}
130 123
131void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) { 124void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
@@ -149,7 +142,7 @@ void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
149 LOG_WARNING(Service_AM, "(STUBBED) called"); 142 LOG_WARNING(Service_AM, "(STUBBED) called");
150 143
151 // Sleep lock is acquired immediately. 144 // Sleep lock is acquired immediately.
152 sleep_lock_event->Signal(); 145 applet->sleep_lock_event.Signal();
153 146
154 IPC::ResponseBuilder rb{ctx, 2}; 147 IPC::ResponseBuilder rb{ctx, 2};
155 rb.Push(ResultSuccess); 148 rb.Push(ResultSuccess);
@@ -172,22 +165,25 @@ void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
172 165
173 IPC::ResponseBuilder rb{ctx, 2, 1}; 166 IPC::ResponseBuilder rb{ctx, 2, 1};
174 rb.Push(ResultSuccess); 167 rb.Push(ResultSuccess);
175 rb.PushCopyObjects(sleep_lock_event->GetReadableEvent()); 168 rb.PushCopyObjects(applet->sleep_lock_event.GetHandle());
176} 169}
177 170
178void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { 171void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
179 LOG_DEBUG(Service_AM, "called"); 172 LOG_DEBUG(Service_AM, "called");
180 173
174 std::scoped_lock lk{applet->lock};
175
181 IPC::ResponseBuilder rb{ctx, 3}; 176 IPC::ResponseBuilder rb{ctx, 3};
182 rb.Push(ResultSuccess); 177 rb.Push(ResultSuccess);
183 rb.Push(vr_mode_state); 178 rb.Push(applet->vr_mode_enabled);
184} 179}
185 180
186void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) { 181void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
187 IPC::RequestParser rp{ctx}; 182 IPC::RequestParser rp{ctx};
188 vr_mode_state = rp.Pop<bool>();
189 183
190 LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off"); 184 std::scoped_lock lk{applet->lock};
185 applet->vr_mode_enabled = rp.Pop<bool>();
186 LOG_WARNING(Service_AM, "VR Mode is {}", applet->vr_mode_enabled ? "on" : "off");
191 187
192 IPC::ResponseBuilder rb{ctx, 2}; 188 IPC::ResponseBuilder rb{ctx, 2};
193 rb.Push(ResultSuccess); 189 rb.Push(ResultSuccess);
@@ -207,6 +203,9 @@ void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) {
207void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) { 203void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
208 LOG_WARNING(Service_AM, "(STUBBED) called"); 204 LOG_WARNING(Service_AM, "(STUBBED) called");
209 205
206 std::scoped_lock lk{applet->lock};
207 applet->vr_mode_enabled = true;
208
210 IPC::ResponseBuilder rb{ctx, 2}; 209 IPC::ResponseBuilder rb{ctx, 2};
211 rb.Push(ResultSuccess); 210 rb.Push(ResultSuccess);
212} 211}
@@ -214,6 +213,9 @@ void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
214void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) { 213void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
215 LOG_WARNING(Service_AM, "(STUBBED) called"); 214 LOG_WARNING(Service_AM, "(STUBBED) called");
216 215
216 std::scoped_lock lk{applet->lock};
217 applet->vr_mode_enabled = false;
218
217 IPC::ResponseBuilder rb{ctx, 2}; 219 IPC::ResponseBuilder rb{ctx, 2};
218 rb.Push(ResultSuccess); 220 rb.Push(ResultSuccess);
219} 221}
@@ -223,7 +225,7 @@ void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContex
223 225
224 IPC::ResponseBuilder rb{ctx, 2, 1}; 226 IPC::ResponseBuilder rb{ctx, 2, 1};
225 rb.Push(ResultSuccess); 227 rb.Push(ResultSuccess);
226 rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent()); 228 rb.PushCopyObjects(applet->message_queue.GetOperationModeChangedEvent());
227} 229}
228 230
229void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) { 231void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
@@ -281,6 +283,9 @@ void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnable
281 HLERequestContext& ctx) { 283 HLERequestContext& ctx) {
282 LOG_WARNING(Service_AM, "(STUBBED) called"); 284 LOG_WARNING(Service_AM, "(STUBBED) called");
283 285
286 std::scoped_lock lk{applet->lock};
287 applet->request_exit_to_library_applet_at_execute_next_program_enabled = true;
288
284 IPC::ResponseBuilder rb{ctx, 2}; 289 IPC::ResponseBuilder rb{ctx, 2};
285 rb.Push(ResultSuccess); 290 rb.Push(ResultSuccess);
286} 291}
diff --git a/src/core/hle/service/am/common_state_getter.h b/src/core/hle/service/am/common_state_getter.h
index 11d66f10a..643ca4dc5 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 @@
10 10
11namespace Service::AM { 11namespace Service::AM {
12 12
13struct Applet;
14
13class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { 15class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
14public: 16public:
15 explicit ICommonStateGetter(Core::System& system_, 17 explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_);
16 std::shared_ptr<AppletMessageQueue> msg_queue_);
17 ~ICommonStateGetter() override; 18 ~ICommonStateGetter() override;
18 19
19private: 20private:
@@ -69,10 +70,7 @@ private:
69 void GetSettingsPlatformRegion(HLERequestContext& ctx); 70 void GetSettingsPlatformRegion(HLERequestContext& ctx);
70 void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx); 71 void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
71 72
72 std::shared_ptr<AppletMessageQueue> msg_queue; 73 const std::shared_ptr<Applet> applet;
73 bool vr_mode_state{};
74 Kernel::KEvent* sleep_lock_event;
75 KernelHelpers::ServiceContext service_context;
76}; 74};
77 75
78} // namespace Service::AM 76} // namespace Service::AM
diff --git a/src/core/hle/service/am/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp
index 4e8f806d7..38495ee19 100644
--- a/src/core/hle/service/am/frontend/applets.cpp
+++ b/src/core/hle/service/am/frontend/applets.cpp
@@ -16,6 +16,7 @@
16#include "core/hle/kernel/k_event.h" 16#include "core/hle/kernel/k_event.h"
17#include "core/hle/service/am/am.h" 17#include "core/hle/service/am/am.h"
18#include "core/hle/service/am/applet_ae.h" 18#include "core/hle/service/am/applet_ae.h"
19#include "core/hle/service/am/applet_manager.h"
19#include "core/hle/service/am/applet_message_queue.h" 20#include "core/hle/service/am/applet_message_queue.h"
20#include "core/hle/service/am/applet_oe.h" 21#include "core/hle/service/am/applet_oe.h"
21#include "core/hle/service/am/frontend/applet_cabinet.h" 22#include "core/hle/service/am/frontend/applet_cabinet.h"
@@ -122,21 +123,11 @@ void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&&
122void AppletDataBroker::SignalStateChanged() { 123void AppletDataBroker::SignalStateChanged() {
123 state_changed_event->Signal(); 124 state_changed_event->Signal();
124 125
126 // TODO proper window management
125 switch (applet_mode) { 127 switch (applet_mode) {
126 case LibraryAppletMode::AllForeground: 128 case LibraryAppletMode::AllForeground:
127 case LibraryAppletMode::AllForegroundInitiallyHidden: { 129 case LibraryAppletMode::AllForegroundInitiallyHidden: {
128 auto applet_oe = system.ServiceManager().GetService<AppletOE>("appletOE"); 130 system.GetAppletManager().FocusStateChanged();
129 auto applet_ae = system.ServiceManager().GetService<AppletAE>("appletAE");
130
131 if (applet_oe) {
132 applet_oe->GetMessageQueue()->FocusStateChanged();
133 break;
134 }
135
136 if (applet_ae) {
137 applet_ae->GetMessageQueue()->FocusStateChanged();
138 break;
139 }
140 break; 131 break;
141 } 132 }
142 default: 133 default:
@@ -255,11 +246,6 @@ void FrontendAppletHolder::SetCurrentAppletId(AppletId applet_id) {
255 current_applet_id = applet_id; 246 current_applet_id = applet_id;
256} 247}
257 248
258void FrontendAppletHolder::SetDefaultAppletFrontendSet() {
259 ClearAll();
260 SetDefaultAppletsIfMissing();
261}
262
263void FrontendAppletHolder::SetDefaultAppletsIfMissing() { 249void FrontendAppletHolder::SetDefaultAppletsIfMissing() {
264 if (frontend.cabinet == nullptr) { 250 if (frontend.cabinet == nullptr) {
265 frontend.cabinet = std::make_unique<Core::Frontend::DefaultCabinetApplet>(); 251 frontend.cabinet = std::make_unique<Core::Frontend::DefaultCabinetApplet>();
diff --git a/src/core/hle/service/am/frontend/applets.h b/src/core/hle/service/am/frontend/applets.h
index f58147955..dec1d63b2 100644
--- a/src/core/hle/service/am/frontend/applets.h
+++ b/src/core/hle/service/am/frontend/applets.h
@@ -188,7 +188,6 @@ public:
188 void SetFrontendAppletSet(FrontendAppletSet set); 188 void SetFrontendAppletSet(FrontendAppletSet set);
189 void SetCabinetMode(NFP::CabinetMode mode); 189 void SetCabinetMode(NFP::CabinetMode mode);
190 void SetCurrentAppletId(AppletId applet_id); 190 void SetCurrentAppletId(AppletId applet_id);
191 void SetDefaultAppletFrontendSet();
192 void SetDefaultAppletsIfMissing(); 191 void SetDefaultAppletsIfMissing();
193 void ClearAll(); 192 void ClearAll();
194 193
diff --git a/src/core/hle/service/am/library_applet_accessor.cpp b/src/core/hle/service/am/library_applet_accessor.cpp
index dabbd6dbe..d3be493e6 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 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/scope_exit.h"
4#include "core/hle/service/am/am_results.h" 5#include "core/hle/service/am/am_results.h"
6#include "core/hle/service/am/frontend/applets.h"
5#include "core/hle/service/am/library_applet_accessor.h" 7#include "core/hle/service/am/library_applet_accessor.h"
6#include "core/hle/service/am/storage.h" 8#include "core/hle/service/am/storage.h"
7#include "core/hle/service/ipc_helpers.h" 9#include "core/hle/service/ipc_helpers.h"
@@ -9,8 +11,10 @@
9namespace Service::AM { 11namespace Service::AM {
10 12
11ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_, 13ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
12 std::shared_ptr<Frontend::FrontendApplet> applet_) 14 std::shared_ptr<AppletStorageHolder> storage_,
13 : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} { 15 std::shared_ptr<Applet> applet_)
16 : ServiceFramework{system_, "ILibraryAppletAccessor"}, storage{std::move(storage_)},
17 applet{std::move(applet_)} {
14 // clang-format off 18 // clang-format off
15 static const FunctionInfo functions[] = { 19 static const FunctionInfo functions[] = {
16 {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, 20 {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
@@ -38,27 +42,31 @@ ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
38 RegisterHandlers(functions); 42 RegisterHandlers(functions);
39} 43}
40 44
45ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
46
41void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) { 47void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) {
42 LOG_DEBUG(Service_AM, "called"); 48 LOG_DEBUG(Service_AM, "called");
43 49
44 IPC::ResponseBuilder rb{ctx, 2, 1}; 50 IPC::ResponseBuilder rb{ctx, 2, 1};
45 rb.Push(ResultSuccess); 51 rb.Push(ResultSuccess);
46 rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent()); 52 rb.PushCopyObjects(storage->state_changed_event.GetHandle());
47} 53}
48 54
49void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) { 55void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) {
50 LOG_DEBUG(Service_AM, "called"); 56 LOG_DEBUG(Service_AM, "called");
51 57
58 std::scoped_lock lk{applet->lock};
59
52 IPC::ResponseBuilder rb{ctx, 3}; 60 IPC::ResponseBuilder rb{ctx, 3};
53 rb.Push(ResultSuccess); 61 rb.Push(ResultSuccess);
54 rb.Push<u32>(applet->TransactionComplete()); 62 rb.Push<u32>(applet->is_completed);
55} 63}
56 64
57void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) { 65void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) {
58 LOG_DEBUG(Service_AM, "called"); 66 LOG_DEBUG(Service_AM, "called");
59 67
60 IPC::ResponseBuilder rb{ctx, 2}; 68 IPC::ResponseBuilder rb{ctx, 2};
61 rb.Push(applet->GetStatus()); 69 rb.Push(applet->terminate_result);
62} 70}
63 71
64void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) { 72void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
@@ -71,10 +79,7 @@ void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestConte
71void ILibraryAppletAccessor::Start(HLERequestContext& ctx) { 79void ILibraryAppletAccessor::Start(HLERequestContext& ctx) {
72 LOG_DEBUG(Service_AM, "called"); 80 LOG_DEBUG(Service_AM, "called");
73 81
74 ASSERT(applet != nullptr); 82 applet->process->Run();
75
76 applet->Initialize();
77 applet->Execute();
78 83
79 IPC::ResponseBuilder rb{ctx, 2}; 84 IPC::ResponseBuilder rb{ctx, 2};
80 rb.Push(ResultSuccess); 85 rb.Push(ResultSuccess);
@@ -84,16 +89,17 @@ void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) {
84 LOG_DEBUG(Service_AM, "called"); 89 LOG_DEBUG(Service_AM, "called");
85 90
86 ASSERT(applet != nullptr); 91 ASSERT(applet != nullptr);
92 applet->message_queue.RequestExit();
87 93
88 IPC::ResponseBuilder rb{ctx, 2}; 94 IPC::ResponseBuilder rb{ctx, 2};
89 rb.Push(applet->RequestExit()); 95 rb.Push(ResultSuccess);
90} 96}
91 97
92void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) { 98void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
93 LOG_DEBUG(Service_AM, "called"); 99 LOG_DEBUG(Service_AM, "called");
94 100
95 IPC::RequestParser rp{ctx}; 101 IPC::RequestParser rp{ctx};
96 applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>().lock()); 102 storage->in_data.PushData(rp.PopIpcInterface<IStorage>().lock());
97 103
98 IPC::ResponseBuilder rb{ctx, 2}; 104 IPC::ResponseBuilder rb{ctx, 2};
99 rb.Push(ResultSuccess); 105 rb.Push(ResultSuccess);
@@ -102,29 +108,24 @@ void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
102void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) { 108void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) {
103 LOG_DEBUG(Service_AM, "called"); 109 LOG_DEBUG(Service_AM, "called");
104 110
105 auto storage = applet->GetBroker().PopNormalDataToGame(); 111 std::shared_ptr<IStorage> data;
106 if (storage == nullptr) { 112 const auto res = storage->out_data.PopData(&data);
107 LOG_DEBUG(Service_AM, 113
108 "storage is a nullptr. There is no data in the current normal channel"); 114 if (res.IsSuccess()) {
115 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
116 rb.Push(res);
117 rb.PushIpcInterface(std::move(data));
118 } else {
109 IPC::ResponseBuilder rb{ctx, 2}; 119 IPC::ResponseBuilder rb{ctx, 2};
110 rb.Push(AM::ResultNoDataInChannel); 120 rb.Push(res);
111 return;
112 } 121 }
113
114 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
115 rb.Push(ResultSuccess);
116 rb.PushIpcInterface<IStorage>(std::move(storage));
117} 122}
118 123
119void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) { 124void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
120 LOG_DEBUG(Service_AM, "called"); 125 LOG_DEBUG(Service_AM, "called");
121 126
122 IPC::RequestParser rp{ctx}; 127 IPC::RequestParser rp{ctx};
123 applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>().lock()); 128 storage->interactive_in_data.PushData(rp.PopIpcInterface<IStorage>().lock());
124
125 ASSERT(applet->IsInitialized());
126 applet->ExecuteInteractive();
127 applet->Execute();
128 129
129 IPC::ResponseBuilder rb{ctx, 2}; 130 IPC::ResponseBuilder rb{ctx, 2};
130 rb.Push(ResultSuccess); 131 rb.Push(ResultSuccess);
@@ -133,18 +134,17 @@ void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
133void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) { 134void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) {
134 LOG_DEBUG(Service_AM, "called"); 135 LOG_DEBUG(Service_AM, "called");
135 136
136 auto storage = applet->GetBroker().PopInteractiveDataToGame(); 137 std::shared_ptr<IStorage> data;
137 if (storage == nullptr) { 138 const auto res = storage->interactive_out_data.PopData(&data);
138 LOG_DEBUG(Service_AM, 139
139 "storage is a nullptr. There is no data in the current interactive channel"); 140 if (res.IsSuccess()) {
141 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
142 rb.Push(res);
143 rb.PushIpcInterface(std::move(data));
144 } else {
140 IPC::ResponseBuilder rb{ctx, 2}; 145 IPC::ResponseBuilder rb{ctx, 2};
141 rb.Push(AM::ResultNoDataInChannel); 146 rb.Push(res);
142 return;
143 } 147 }
144
145 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
146 rb.Push(ResultSuccess);
147 rb.PushIpcInterface<IStorage>(std::move(storage));
148} 148}
149 149
150void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) { 150void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
@@ -152,7 +152,7 @@ void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
152 152
153 IPC::ResponseBuilder rb{ctx, 2, 1}; 153 IPC::ResponseBuilder rb{ctx, 2, 1};
154 rb.Push(ResultSuccess); 154 rb.Push(ResultSuccess);
155 rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent()); 155 rb.PushCopyObjects(storage->out_data.GetEvent());
156} 156}
157 157
158void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) { 158void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
@@ -160,7 +160,7 @@ void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ct
160 160
161 IPC::ResponseBuilder rb{ctx, 2, 1}; 161 IPC::ResponseBuilder rb{ctx, 2, 1};
162 rb.Push(ResultSuccess); 162 rb.Push(ResultSuccess);
163 rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent()); 163 rb.PushCopyObjects(storage->interactive_out_data.GetEvent());
164} 164}
165 165
166void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) { 166void 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 77f62906c..c34a1cbca 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 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/am/frontend/applets.h"
7#include "core/hle/service/service.h" 6#include "core/hle/service/service.h"
8 7
9namespace Service::AM { 8namespace Service::AM {
10 9
10struct AppletStorageHolder;
11struct Applet;
12
11class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { 13class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
12public: 14public:
13 explicit ILibraryAppletAccessor(Core::System& system_, 15 explicit ILibraryAppletAccessor(Core::System& system_,
14 std::shared_ptr<Frontend::FrontendApplet> applet_); 16 std::shared_ptr<AppletStorageHolder> storage_,
17 std::shared_ptr<Applet> applet_);
18 ~ILibraryAppletAccessor();
15 19
16private: 20protected:
17 void GetAppletStateChangedEvent(HLERequestContext& ctx); 21 void GetAppletStateChangedEvent(HLERequestContext& ctx);
18 void IsCompleted(HLERequestContext& ctx); 22 void IsCompleted(HLERequestContext& ctx);
19 void GetResult(HLERequestContext& ctx); 23 void GetResult(HLERequestContext& ctx);
@@ -28,7 +32,8 @@ private:
28 void GetPopInteractiveOutDataEvent(HLERequestContext& ctx); 32 void GetPopInteractiveOutDataEvent(HLERequestContext& ctx);
29 void GetIndirectLayerConsumerHandle(HLERequestContext& ctx); 33 void GetIndirectLayerConsumerHandle(HLERequestContext& ctx);
30 34
31 std::shared_ptr<Frontend::FrontendApplet> applet; 35 const std::shared_ptr<AppletStorageHolder> storage;
36 const std::shared_ptr<Applet> applet;
32}; 37};
33 38
34} // namespace Service::AM 39} // 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 f80887517..e4332e244 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 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/kernel/k_transfer_memory.h" 4#include "core/hle/kernel/k_transfer_memory.h"
5#include "core/hle/service/am/applet_manager.h"
5#include "core/hle/service/am/frontend/applets.h" 6#include "core/hle/service/am/frontend/applets.h"
6#include "core/hle/service/am/library_applet_accessor.h" 7#include "core/hle/service/am/library_applet_accessor.h"
7#include "core/hle/service/am/library_applet_creator.h" 8#include "core/hle/service/am/library_applet_creator.h"
8#include "core/hle/service/am/storage.h" 9#include "core/hle/service/am/storage.h"
9#include "core/hle/service/ipc_helpers.h" 10#include "core/hle/service/ipc_helpers.h"
11#include "core/hle/service/sm/sm.h"
10 12
11namespace Service::AM { 13namespace Service::AM {
12 14
13ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) 15namespace {
14 : ServiceFramework{system_, "ILibraryAppletCreator"} { 16
17AppletProgramId AppletIdToProgramId(AppletId applet_id) {
18 switch (applet_id) {
19 case AppletId::OverlayDisplay:
20 return AppletProgramId::OverlayDisplay;
21 case AppletId::QLaunch:
22 return AppletProgramId::QLaunch;
23 case AppletId::Starter:
24 return AppletProgramId::Starter;
25 case AppletId::Auth:
26 return AppletProgramId::Auth;
27 case AppletId::Cabinet:
28 return AppletProgramId::Cabinet;
29 case AppletId::Controller:
30 return AppletProgramId::Controller;
31 case AppletId::DataErase:
32 return AppletProgramId::DataErase;
33 case AppletId::Error:
34 return AppletProgramId::Error;
35 case AppletId::NetConnect:
36 return AppletProgramId::NetConnect;
37 case AppletId::ProfileSelect:
38 return AppletProgramId::ProfileSelect;
39 case AppletId::SoftwareKeyboard:
40 return AppletProgramId::SoftwareKeyboard;
41 case AppletId::MiiEdit:
42 return AppletProgramId::MiiEdit;
43 case AppletId::Web:
44 return AppletProgramId::Web;
45 case AppletId::Shop:
46 return AppletProgramId::Shop;
47 case AppletId::PhotoViewer:
48 return AppletProgramId::PhotoViewer;
49 case AppletId::Settings:
50 return AppletProgramId::Settings;
51 case AppletId::OfflineWeb:
52 return AppletProgramId::OfflineWeb;
53 case AppletId::LoginShare:
54 return AppletProgramId::LoginShare;
55 case AppletId::WebAuth:
56 return AppletProgramId::WebAuth;
57 case AppletId::MyPage:
58 return AppletProgramId::MyPage;
59 default:
60 return static_cast<AppletProgramId>(0);
61 }
62}
63
64std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
65 std::shared_ptr<Applet> caller_applet,
66 AppletId applet_id,
67 LibraryAppletMode mode) {
68 const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
69 if (program_id == 0) {
70 // Unknown applet
71 return {};
72 }
73
74 auto process = std::make_unique<Process>(system);
75 if (!process->Initialize(program_id)) {
76 // Couldn't initialize the guest process
77 return {};
78 }
79
80 const auto applet = std::make_shared<Applet>(system, std::move(process));
81 applet->program_id = program_id;
82 applet->applet_id = applet_id;
83 applet->type = AppletType::LibraryApplet;
84 applet->library_applet_mode = mode;
85
86 // Library applet should be foreground
87 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
88 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
89 applet->focus_state = FocusState::InFocus;
90
91 auto storage = std::make_shared<AppletStorageHolder>(system);
92 applet->caller_applet = caller_applet;
93 applet->caller_applet_storage = storage;
94
95 system.GetAppletManager().InsertApplet(applet);
96
97 return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
98}
99
100std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
101 AppletId applet_id,
102 LibraryAppletMode mode) {
103 UNREACHABLE();
104 return {};
105}
106
107} // namespace
108
109ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_)
110 : ServiceFramework{system_, "ILibraryAppletCreator"}, applet{std::move(applet_)} {
15 static const FunctionInfo functions[] = { 111 static const FunctionInfo functions[] = {
16 {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, 112 {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
17 {1, nullptr, "TerminateAllLibraryApplets"}, 113 {1, nullptr, "TerminateAllLibraryApplets"},
@@ -34,10 +130,11 @@ void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
34 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, 130 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
35 applet_mode); 131 applet_mode);
36 132
37 const auto& holder{system.GetFrontendAppletHolder()}; 133 auto library_applet = CreateGuestApplet(system, applet, applet_id, applet_mode);
38 const auto applet = holder.GetApplet(applet_id, applet_mode); 134 if (!library_applet) {
39 135 library_applet = CreateFrontendApplet(system, applet_id, applet_mode);
40 if (applet == nullptr) { 136 }
137 if (!library_applet) {
41 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); 138 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
42 139
43 IPC::ResponseBuilder rb{ctx, 2}; 140 IPC::ResponseBuilder rb{ctx, 2};
@@ -45,10 +142,12 @@ void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
45 return; 142 return;
46 } 143 }
47 144
48 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 145 // Applet is created, can now be launched.
146 applet->library_applet_launchable_event.Signal();
49 147
148 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
50 rb.Push(ResultSuccess); 149 rb.Push(ResultSuccess);
51 rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); 150 rb.PushIpcInterface<ILibraryAppletAccessor>(library_applet);
52} 151}
53 152
54void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) { 153void 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 97f236fbc..551f287bd 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 @@
7 7
8namespace Service::AM { 8namespace Service::AM {
9 9
10struct Applet;
11
10class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { 12class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
11public: 13public:
12 explicit ILibraryAppletCreator(Core::System& system_); 14 explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_);
13 ~ILibraryAppletCreator() override; 15 ~ILibraryAppletCreator() override;
14 16
15private: 17private:
@@ -17,6 +19,8 @@ private:
17 void CreateStorage(HLERequestContext& ctx); 19 void CreateStorage(HLERequestContext& ctx);
18 void CreateTransferMemoryStorage(HLERequestContext& ctx); 20 void CreateTransferMemoryStorage(HLERequestContext& ctx);
19 void CreateHandleStorage(HLERequestContext& ctx); 21 void CreateHandleStorage(HLERequestContext& ctx);
22
23 const std::shared_ptr<Applet> applet;
20}; 24};
21 25
22} // namespace Service::AM 26} // 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 047fc40f4..1d88dd78c 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 @@
19namespace Service::AM { 19namespace Service::AM {
20 20
21ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, 21ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
22 std::shared_ptr<AppletMessageQueue> msg_queue_, 22 std::shared_ptr<Applet> applet_, Core::System& system_)
23 Core::System& system_) 23 : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
24 : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, 24 applet_)} {
25 msg_queue{std::move(msg_queue_)} {
26 // clang-format off 25 // clang-format off
27 static const FunctionInfo functions[] = { 26 static const FunctionInfo functions[] = {
28 {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, 27 {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
@@ -43,12 +42,14 @@ ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
43 RegisterHandlers(functions); 42 RegisterHandlers(functions);
44} 43}
45 44
45ILibraryAppletProxy::~ILibraryAppletProxy() = default;
46
46void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { 47void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
47 LOG_DEBUG(Service_AM, "called"); 48 LOG_DEBUG(Service_AM, "called");
48 49
49 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 50 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
50 rb.Push(ResultSuccess); 51 rb.Push(ResultSuccess);
51 rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); 52 rb.PushIpcInterface<ICommonStateGetter>(system, applet);
52} 53}
53 54
54void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) { 55void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
@@ -56,7 +57,7 @@ void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
56 57
57 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 58 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
58 rb.Push(ResultSuccess); 59 rb.Push(ResultSuccess);
59 rb.PushIpcInterface<ISelfController>(system, nvnflinger); 60 rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
60} 61}
61 62
62void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) { 63void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) {
@@ -64,7 +65,7 @@ void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) {
64 65
65 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 66 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
66 rb.Push(ResultSuccess); 67 rb.Push(ResultSuccess);
67 rb.PushIpcInterface<IWindowController>(system); 68 rb.PushIpcInterface<IWindowController>(system, applet);
68} 69}
69 70
70void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) { 71void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) {
@@ -88,7 +89,7 @@ void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) {
88 89
89 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 90 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
90 rb.Push(ResultSuccess); 91 rb.Push(ResultSuccess);
91 rb.PushIpcInterface<IProcessWindingController>(system); 92 rb.PushIpcInterface<IProcessWindingController>(system, applet);
92} 93}
93 94
94void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { 95void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
@@ -96,7 +97,7 @@ void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
96 97
97 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 98 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
98 rb.Push(ResultSuccess); 99 rb.Push(ResultSuccess);
99 rb.PushIpcInterface<ILibraryAppletCreator>(system); 100 rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
100} 101}
101 102
102void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { 103void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
@@ -104,7 +105,7 @@ void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx)
104 105
105 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 106 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
106 rb.Push(ResultSuccess); 107 rb.Push(ResultSuccess);
107 rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system); 108 rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system, applet);
108} 109}
109 110
110void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { 111void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
@@ -112,7 +113,7 @@ void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
112 113
113 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 114 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
114 rb.Push(ResultSuccess); 115 rb.Push(ResultSuccess);
115 rb.PushIpcInterface<IAppletCommonFunctions>(system); 116 rb.PushIpcInterface<IAppletCommonFunctions>(system, applet);
116} 117}
117 118
118void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { 119void 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 cd9e6d02b..8f7a25897 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 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/am/applet_message_queue.h"
7#include "core/hle/service/service.h" 6#include "core/hle/service/service.h"
8 7
9namespace Service::AM { 8namespace Service::AM {
10 9
10struct Applet;
11
11class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { 12class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
12public: 13public:
13 explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, 14 explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
14 std::shared_ptr<AppletMessageQueue> msg_queue_, 15 std::shared_ptr<Applet> applet_, Core::System& system_);
15 Core::System& system_); 16 ~ILibraryAppletProxy();
16 17
17private: 18private:
18 void GetCommonStateGetter(HLERequestContext& ctx); 19 void GetCommonStateGetter(HLERequestContext& ctx);
@@ -29,7 +30,7 @@ private:
29 void GetDebugFunctions(HLERequestContext& ctx); 30 void GetDebugFunctions(HLERequestContext& ctx);
30 31
31 Nvnflinger::Nvnflinger& nvnflinger; 32 Nvnflinger::Nvnflinger& nvnflinger;
32 std::shared_ptr<AppletMessageQueue> msg_queue; 33 std::shared_ptr<Applet> applet;
33}; 34};
34 35
35} // namespace Service::AM 36} // 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 c36f141f4..74ee33213 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 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/scope_exit.h"
4#include "core/core_timing.h" 5#include "core/core_timing.h"
5#include "core/hle/service/acc/profile_manager.h" 6#include "core/hle/service/acc/profile_manager.h"
6#include "core/hle/service/am/am_results.h" 7#include "core/hle/service/am/am_results.h"
8#include "core/hle/service/am/applet_manager.h"
7#include "core/hle/service/am/frontend/applet_cabinet.h" 9#include "core/hle/service/am/frontend/applet_cabinet.h"
8#include "core/hle/service/am/frontend/applet_controller.h" 10#include "core/hle/service/am/frontend/applet_controller.h"
9#include "core/hle/service/am/frontend/applet_mii_edit_types.h" 11#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
@@ -16,16 +18,44 @@
16 18
17namespace Service::AM { 19namespace Service::AM {
18 20
19ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) 21namespace {
20 : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} { 22
23struct AppletIdentityInfo {
24 AppletId applet_id;
25 INSERT_PADDING_BYTES(0x4);
26 u64 application_id;
27};
28static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
29
30AppletIdentityInfo GetCallerIdentity(std::shared_ptr<Applet> applet) {
31 if (const auto caller_applet = applet->caller_applet.lock(); caller_applet) {
32 // TODO: is this actually the application ID?
33 return {
34 .applet_id = applet->applet_id,
35 .application_id = applet->program_id,
36 };
37 } else {
38 return {
39 .applet_id = AppletId::QLaunch,
40 .application_id = 0x0100000000001000ull,
41 };
42 }
43}
44
45} // namespace
46
47ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_,
48 std::shared_ptr<Applet> applet_)
49 : ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, applet{std::move(applet_)},
50 storage{applet->caller_applet_storage} {
21 // clang-format off 51 // clang-format off
22 static const FunctionInfo functions[] = { 52 static const FunctionInfo functions[] = {
23 {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"}, 53 {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
24 {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"}, 54 {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
25 {2, nullptr, "PopInteractiveInData"}, 55 {2, &ILibraryAppletSelfAccessor::PopInteractiveInData, "PopInteractiveInData"},
26 {3, nullptr, "PushInteractiveOutData"}, 56 {3, &ILibraryAppletSelfAccessor::PushInteractiveOutData, "PushInteractiveOutData"},
27 {5, nullptr, "GetPopInDataEvent"}, 57 {5, &ILibraryAppletSelfAccessor::GetPopInDataEvent, "GetPopInDataEvent"},
28 {6, nullptr, "GetPopInteractiveInDataEvent"}, 58 {6, &ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent, "GetPopInteractiveInDataEvent"},
29 {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, 59 {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
30 {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, 60 {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
31 {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"}, 61 {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
@@ -58,26 +88,6 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
58 }; 88 };
59 // clang-format on 89 // clang-format on
60 RegisterHandlers(functions); 90 RegisterHandlers(functions);
61
62 switch (system.GetFrontendAppletHolder().GetCurrentAppletId()) {
63 case AppletId::Cabinet:
64 PushInShowCabinetData();
65 break;
66 case AppletId::MiiEdit:
67 PushInShowMiiEditData();
68 break;
69 case AppletId::PhotoViewer:
70 PushInShowAlbum();
71 break;
72 case AppletId::SoftwareKeyboard:
73 PushInShowSoftwareKeyboard();
74 break;
75 case AppletId::Controller:
76 PushInShowController();
77 break;
78 default:
79 break;
80 }
81} 91}
82 92
83ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; 93ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
@@ -85,31 +95,81 @@ ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
85void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) { 95void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
86 LOG_INFO(Service_AM, "called"); 96 LOG_INFO(Service_AM, "called");
87 97
88 if (queue_data.empty()) { 98 std::shared_ptr<IStorage> data;
99 const auto res = storage->in_data.PopData(&data);
100
101 if (res.IsSuccess()) {
102 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
103 rb.Push(res);
104 rb.PushIpcInterface(std::move(data));
105 } else {
89 IPC::ResponseBuilder rb{ctx, 2}; 106 IPC::ResponseBuilder rb{ctx, 2};
90 rb.Push(AM::ResultNoDataInChannel); 107 rb.Push(res);
91 return;
92 } 108 }
109}
110
111void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
112 LOG_INFO(Service_AM, "called");
93 113
94 auto data = queue_data.front(); 114 IPC::RequestParser rp{ctx};
95 queue_data.pop_front(); 115 storage->out_data.PushData(rp.PopIpcInterface<IStorage>().lock());
96 116
97 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 117 IPC::ResponseBuilder rb{ctx, 2};
98 rb.Push(ResultSuccess); 118 rb.Push(ResultSuccess);
99 rb.PushIpcInterface<IStorage>(system, std::move(data));
100} 119}
101 120
102void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) { 121void ILibraryAppletSelfAccessor::PopInteractiveInData(HLERequestContext& ctx) {
103 LOG_WARNING(Service_AM, "(STUBBED) called"); 122 LOG_INFO(Service_AM, "called");
123
124 std::shared_ptr<IStorage> data;
125 const auto res = storage->interactive_in_data.PopData(&data);
126
127 if (res.IsSuccess()) {
128 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
129 rb.Push(res);
130 rb.PushIpcInterface(std::move(data));
131 } else {
132 IPC::ResponseBuilder rb{ctx, 2};
133 rb.Push(res);
134 }
135}
136
137void ILibraryAppletSelfAccessor::PushInteractiveOutData(HLERequestContext& ctx) {
138 LOG_INFO(Service_AM, "called");
139
140 IPC::RequestParser rp{ctx};
141 storage->interactive_out_data.PushData(rp.PopIpcInterface<IStorage>().lock());
104 142
105 IPC::ResponseBuilder rb{ctx, 2}; 143 IPC::ResponseBuilder rb{ctx, 2};
106 rb.Push(ResultSuccess); 144 rb.Push(ResultSuccess);
107} 145}
108 146
147void ILibraryAppletSelfAccessor::GetPopInDataEvent(HLERequestContext& ctx) {
148 LOG_INFO(Service_AM, "called");
149
150 IPC::ResponseBuilder rb{ctx, 2, 1};
151 rb.Push(ResultSuccess);
152 rb.PushCopyObjects(storage->in_data.GetEvent());
153}
154
155void ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(HLERequestContext& ctx) {
156 LOG_INFO(Service_AM, "called");
157
158 IPC::ResponseBuilder rb{ctx, 2, 1};
159 rb.Push(ResultSuccess);
160 rb.PushCopyObjects(storage->interactive_in_data.GetEvent());
161}
162
109void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) { 163void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
110 LOG_WARNING(Service_AM, "(STUBBED) called"); 164 LOG_INFO(Service_AM, "called");
165
166 system.GetAppletManager().TerminateAndRemoveApplet(applet->aruid);
111 167
112 system.Exit(); 168 {
169 std::scoped_lock lk{applet->lock};
170 applet->is_completed = true;
171 storage->state_changed_event.Signal();
172 }
113 173
114 IPC::ResponseBuilder rb{ctx, 2}; 174 IPC::ResponseBuilder rb{ctx, 2};
115 rb.Push(ResultSuccess); 175 rb.Push(ResultSuccess);
@@ -124,8 +184,8 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
124 LOG_WARNING(Service_AM, "(STUBBED) called"); 184 LOG_WARNING(Service_AM, "(STUBBED) called");
125 185
126 const LibraryAppletInfo applet_info{ 186 const LibraryAppletInfo applet_info{
127 .applet_id = system.GetFrontendAppletHolder().GetCurrentAppletId(), 187 .applet_id = applet->applet_id,
128 .library_applet_mode = LibraryAppletMode::AllForeground, 188 .library_applet_mode = applet->library_applet_mode,
129 }; 189 };
130 190
131 IPC::ResponseBuilder rb{ctx, 4}; 191 IPC::ResponseBuilder rb{ctx, 4};
@@ -134,13 +194,6 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
134} 194}
135 195
136void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) { 196void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
137 struct AppletIdentityInfo {
138 AppletId applet_id;
139 INSERT_PADDING_BYTES(0x4);
140 u64 application_id;
141 };
142 static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
143
144 LOG_WARNING(Service_AM, "(STUBBED) called"); 197 LOG_WARNING(Service_AM, "(STUBBED) called");
145 198
146 const AppletIdentityInfo applet_info{ 199 const AppletIdentityInfo applet_info{
@@ -154,22 +207,11 @@ void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ct
154} 207}
155 208
156void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { 209void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
157 struct AppletIdentityInfo {
158 AppletId applet_id;
159 INSERT_PADDING_BYTES(0x4);
160 u64 application_id;
161 };
162 static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
163 LOG_WARNING(Service_AM, "(STUBBED) called"); 210 LOG_WARNING(Service_AM, "(STUBBED) called");
164 211
165 const AppletIdentityInfo applet_info{
166 .applet_id = AppletId::QLaunch,
167 .application_id = 0x0100000000001000ull,
168 };
169
170 IPC::ResponseBuilder rb{ctx, 6}; 212 IPC::ResponseBuilder rb{ctx, 6};
171 rb.Push(ResultSuccess); 213 rb.Push(ResultSuccess);
172 rb.PushRaw(applet_info); 214 rb.PushRaw(GetCallerIdentity(applet));
173} 215}
174 216
175void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) { 217void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
@@ -207,176 +249,4 @@ void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext
207 rb.Push<u8>(0); 249 rb.Push<u8>(0);
208} 250}
209 251
210void ILibraryAppletSelfAccessor::PushInShowAlbum() {
211 const CommonArguments arguments{
212 .arguments_version = CommonArgumentVersion::Version3,
213 .size = CommonArgumentSize::Version3,
214 .library_version = 1,
215 .theme_color = ThemeColor::BasicBlack,
216 .play_startup_sound = true,
217 .system_tick = system.CoreTiming().GetClockTicks(),
218 };
219
220 std::vector<u8> argument_data(sizeof(arguments));
221 std::vector<u8> settings_data{2};
222 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
223 queue_data.emplace_back(std::move(argument_data));
224 queue_data.emplace_back(std::move(settings_data));
225}
226
227void ILibraryAppletSelfAccessor::PushInShowController() {
228 const CommonArguments common_args = {
229 .arguments_version = CommonArgumentVersion::Version3,
230 .size = CommonArgumentSize::Version3,
231 .library_version = static_cast<u32>(Frontend::ControllerAppletVersion::Version8),
232 .theme_color = ThemeColor::BasicBlack,
233 .play_startup_sound = true,
234 .system_tick = system.CoreTiming().GetClockTicks(),
235 };
236
237 Frontend::ControllerSupportArgNew user_args = {
238 .header = {.player_count_min = 1,
239 .player_count_max = 4,
240 .enable_take_over_connection = true,
241 .enable_left_justify = false,
242 .enable_permit_joy_dual = true,
243 .enable_single_mode = false,
244 .enable_identification_color = false},
245 .identification_colors = {},
246 .enable_explain_text = false,
247 .explain_text = {},
248 };
249
250 Frontend::ControllerSupportArgPrivate private_args = {
251 .arg_private_size = sizeof(Frontend::ControllerSupportArgPrivate),
252 .arg_size = sizeof(Frontend::ControllerSupportArgNew),
253 .is_home_menu = true,
254 .flag_1 = true,
255 .mode = Frontend::ControllerSupportMode::ShowControllerSupport,
256 .caller = Frontend::ControllerSupportCaller::
257 Application, // switchbrew: Always zero except with
258 // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem,
259 // which sets this to the input param
260 .style_set = Core::HID::NpadStyleSet::None,
261 .joy_hold_type = 0,
262 };
263 std::vector<u8> common_args_data(sizeof(common_args));
264 std::vector<u8> private_args_data(sizeof(private_args));
265 std::vector<u8> user_args_data(sizeof(user_args));
266
267 std::memcpy(common_args_data.data(), &common_args, sizeof(common_args));
268 std::memcpy(private_args_data.data(), &private_args, sizeof(private_args));
269 std::memcpy(user_args_data.data(), &user_args, sizeof(user_args));
270
271 queue_data.emplace_back(std::move(common_args_data));
272 queue_data.emplace_back(std::move(private_args_data));
273 queue_data.emplace_back(std::move(user_args_data));
274}
275
276void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
277 const CommonArguments arguments{
278 .arguments_version = CommonArgumentVersion::Version3,
279 .size = CommonArgumentSize::Version3,
280 .library_version = static_cast<u32>(Frontend::CabinetAppletVersion::Version1),
281 .theme_color = ThemeColor::BasicBlack,
282 .play_startup_sound = true,
283 .system_tick = system.CoreTiming().GetClockTicks(),
284 };
285
286 const Frontend::StartParamForAmiiboSettings amiibo_settings{
287 .param_1 = 0,
288 .applet_mode = system.GetFrontendAppletHolder().GetCabinetMode(),
289 .flags = Frontend::CabinetFlags::None,
290 .amiibo_settings_1 = 0,
291 .device_handle = 0,
292 .tag_info{},
293 .register_info{},
294 .amiibo_settings_3{},
295 };
296
297 std::vector<u8> argument_data(sizeof(arguments));
298 std::vector<u8> settings_data(sizeof(amiibo_settings));
299 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
300 std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
301 queue_data.emplace_back(std::move(argument_data));
302 queue_data.emplace_back(std::move(settings_data));
303}
304
305void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
306 struct MiiEditV3 {
307 Frontend::MiiEditAppletInputCommon common;
308 Frontend::MiiEditAppletInputV3 input;
309 };
310 static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
311
312 MiiEditV3 mii_arguments{
313 .common =
314 {
315 .version = Frontend::MiiEditAppletVersion::Version3,
316 .applet_mode = Frontend::MiiEditAppletMode::ShowMiiEdit,
317 },
318 .input{},
319 };
320
321 std::vector<u8> argument_data(sizeof(mii_arguments));
322 std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));
323
324 queue_data.emplace_back(std::move(argument_data));
325}
326
327void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() {
328 const CommonArguments arguments{
329 .arguments_version = CommonArgumentVersion::Version3,
330 .size = CommonArgumentSize::Version3,
331 .library_version = static_cast<u32>(Frontend::SwkbdAppletVersion::Version524301),
332 .theme_color = ThemeColor::BasicBlack,
333 .play_startup_sound = true,
334 .system_tick = system.CoreTiming().GetClockTicks(),
335 };
336
337 std::vector<char16_t> initial_string(0);
338
339 const Frontend::SwkbdConfigCommon swkbd_config{
340 .type = Frontend::SwkbdType::Qwerty,
341 .ok_text{},
342 .left_optional_symbol_key{},
343 .right_optional_symbol_key{},
344 .use_prediction = false,
345 .key_disable_flags{},
346 .initial_cursor_position = Frontend::SwkbdInitialCursorPosition::Start,
347 .header_text{},
348 .sub_text{},
349 .guide_text{},
350 .max_text_length = 500,
351 .min_text_length = 0,
352 .password_mode = Frontend::SwkbdPasswordMode::Disabled,
353 .text_draw_type = Frontend::SwkbdTextDrawType::Box,
354 .enable_return_button = true,
355 .use_utf8 = false,
356 .use_blur_background = true,
357 .initial_string_offset{},
358 .initial_string_length = static_cast<u32>(initial_string.size()),
359 .user_dictionary_offset{},
360 .user_dictionary_entries{},
361 .use_text_check = false,
362 };
363
364 Frontend::SwkbdConfigNew swkbd_config_new{};
365
366 std::vector<u8> argument_data(sizeof(arguments));
367 std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new));
368 std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t));
369
370 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
371 std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config));
372 std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new,
373 sizeof(Frontend::SwkbdConfigNew));
374 std::memcpy(work_buffer.data(), initial_string.data(),
375 swkbd_config.initial_string_length * sizeof(char16_t));
376
377 queue_data.emplace_back(std::move(argument_data));
378 queue_data.emplace_back(std::move(swkbd_data));
379 queue_data.emplace_back(std::move(work_buffer));
380}
381
382} // namespace Service::AM 252} // 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 45b325b77..b15040539 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 @@
10 10
11namespace Service::AM { 11namespace Service::AM {
12 12
13struct AppletStorageHolder;
14struct Applet;
15
13class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> { 16class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
14public: 17public:
15 explicit ILibraryAppletSelfAccessor(Core::System& system_); 18 explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet_);
16 ~ILibraryAppletSelfAccessor() override; 19 ~ILibraryAppletSelfAccessor() override;
17 20
18private: 21private:
19 void PopInData(HLERequestContext& ctx); 22 void PopInData(HLERequestContext& ctx);
20 void PushOutData(HLERequestContext& ctx); 23 void PushOutData(HLERequestContext& ctx);
24 void PopInteractiveInData(HLERequestContext& ctx);
25 void PushInteractiveOutData(HLERequestContext& ctx);
26 void GetPopInDataEvent(HLERequestContext& ctx);
27 void GetPopInteractiveInDataEvent(HLERequestContext& ctx);
21 void GetLibraryAppletInfo(HLERequestContext& ctx); 28 void GetLibraryAppletInfo(HLERequestContext& ctx);
22 void GetMainAppletIdentityInfo(HLERequestContext& ctx); 29 void GetMainAppletIdentityInfo(HLERequestContext& ctx);
23 void ExitProcessAndReturn(HLERequestContext& ctx); 30 void ExitProcessAndReturn(HLERequestContext& ctx);
@@ -26,13 +33,8 @@ private:
26 void GetMainAppletAvailableUsers(HLERequestContext& ctx); 33 void GetMainAppletAvailableUsers(HLERequestContext& ctx);
27 void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx); 34 void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
28 35
29 void PushInShowAlbum(); 36 const std::shared_ptr<Applet> applet;
30 void PushInShowCabinetData(); 37 const std::shared_ptr<AppletStorageHolder> storage;
31 void PushInShowMiiEditData();
32 void PushInShowSoftwareKeyboard();
33 void PushInShowController();
34
35 std::deque<std::vector<u8>> queue_data;
36}; 38};
37 39
38} // namespace Service::AM 40} // 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 7954abd7a..f5ccc4643 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 @@
8 8
9namespace Service::AM { 9namespace Service::AM {
10 10
11IProcessWindingController::IProcessWindingController(Core::System& system_) 11IProcessWindingController::IProcessWindingController(Core::System& system_,
12 : ServiceFramework{system_, "IProcessWindingController"} { 12 std::shared_ptr<Applet> applet_)
13 : ServiceFramework{system_, "IProcessWindingController"}, applet{std::move(applet_)} {
13 // clang-format off 14 // clang-format off
14 static const FunctionInfo functions[] = { 15 static const FunctionInfo functions[] = {
15 {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"}, 16 {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
@@ -31,34 +32,15 @@ IProcessWindingController::~IProcessWindingController() = default;
31void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) { 32void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
32 LOG_WARNING(Service_AM, "(STUBBED) called"); 33 LOG_WARNING(Service_AM, "(STUBBED) called");
33 34
34 struct AppletProcessLaunchReason {
35 u8 flag;
36 INSERT_PADDING_BYTES(3);
37 };
38 static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
39 "AppletProcessLaunchReason is an invalid size");
40
41 AppletProcessLaunchReason reason{
42 .flag = 0,
43 };
44
45 IPC::ResponseBuilder rb{ctx, 3}; 35 IPC::ResponseBuilder rb{ctx, 3};
46 rb.Push(ResultSuccess); 36 rb.Push(ResultSuccess);
47 rb.PushRaw(reason); 37 rb.PushRaw(applet->launch_reason);
48} 38}
49 39
50void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { 40void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
51 const auto applet_id = system.GetFrontendAppletHolder().GetCurrentAppletId(); 41 const auto caller_applet = applet->caller_applet.lock();
52 const auto applet_mode = LibraryAppletMode::AllForeground; 42 if (caller_applet == nullptr) {
53 43 LOG_ERROR(Service_AM, "No calling applet available");
54 LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
55 applet_mode);
56
57 const auto& holder{system.GetFrontendAppletHolder()};
58 const auto applet = holder.GetApplet(applet_id, applet_mode);
59
60 if (applet == nullptr) {
61 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
62 44
63 IPC::ResponseBuilder rb{ctx, 2}; 45 IPC::ResponseBuilder rb{ctx, 2};
64 rb.Push(ResultUnknown); 46 rb.Push(ResultUnknown);
@@ -67,7 +49,8 @@ void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx)
67 49
68 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 50 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
69 rb.Push(ResultSuccess); 51 rb.Push(ResultSuccess);
70 rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); 52 rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet->caller_applet_storage,
53 caller_applet);
71} 54}
72 55
73} // namespace Service::AM 56} // 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 9b9704201..71ae4c4f5 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 @@
7 7
8namespace Service::AM { 8namespace Service::AM {
9 9
10struct Applet;
11
10class IProcessWindingController final : public ServiceFramework<IProcessWindingController> { 12class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
11public: 13public:
12 explicit IProcessWindingController(Core::System& system_); 14 explicit IProcessWindingController(Core::System& system_, std::shared_ptr<Applet> applet_);
13 ~IProcessWindingController() override; 15 ~IProcessWindingController() override;
14 16
15private: 17private:
16 void GetLaunchReason(HLERequestContext& ctx); 18 void GetLaunchReason(HLERequestContext& ctx);
17 void OpenCallingLibraryApplet(HLERequestContext& ctx); 19 void OpenCallingLibraryApplet(HLERequestContext& ctx);
20
21 const std::shared_ptr<Applet> applet;
18}; 22};
19 23
20} // namespace Service::AM 24} // namespace Service::AM
diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp
index d5de1bb2f..3ac967b4d 100644
--- a/src/core/hle/service/am/self_controller.cpp
+++ b/src/core/hle/service/am/self_controller.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/am/am_results.h"
4#include "core/hle/service/am/frontend/applets.h" 5#include "core/hle/service/am/frontend/applets.h"
5#include "core/hle/service/am/self_controller.h" 6#include "core/hle/service/am/self_controller.h"
6#include "core/hle/service/caps/caps_su.h" 7#include "core/hle/service/caps/caps_su.h"
@@ -12,9 +13,10 @@
12 13
13namespace Service::AM { 14namespace Service::AM {
14 15
15ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) 16ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_,
16 : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, 17 Nvnflinger::Nvnflinger& nvnflinger_)
17 service_context{system, "ISelfController"} { 18 : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, applet{std::move(
19 applet_)} {
18 // clang-format off 20 // clang-format off
19 static const FunctionInfo functions[] = { 21 static const FunctionInfo functions[] = {
20 {0, &ISelfController::Exit, "Exit"}, 22 {0, &ISelfController::Exit, "Exit"},
@@ -69,24 +71,9 @@ ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger&
69 // clang-format on 71 // clang-format on
70 72
71 RegisterHandlers(functions); 73 RegisterHandlers(functions);
72
73 launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent");
74
75 // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
76 // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
77 // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
78 // suspended if the event has previously been created by a call to
79 // GetAccumulatedSuspendedTickChangedEvent.
80
81 accumulated_suspended_tick_changed_event =
82 service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent");
83 accumulated_suspended_tick_changed_event->Signal();
84} 74}
85 75
86ISelfController::~ISelfController() { 76ISelfController::~ISelfController() = default;
87 service_context.CloseEvent(launchable_event);
88 service_context.CloseEvent(accumulated_suspended_tick_changed_event);
89}
90 77
91void ISelfController::Exit(HLERequestContext& ctx) { 78void ISelfController::Exit(HLERequestContext& ctx) {
92 LOG_DEBUG(Service_AM, "called"); 79 LOG_DEBUG(Service_AM, "called");
@@ -94,6 +81,7 @@ void ISelfController::Exit(HLERequestContext& ctx) {
94 IPC::ResponseBuilder rb{ctx, 2}; 81 IPC::ResponseBuilder rb{ctx, 2};
95 rb.Push(ResultSuccess); 82 rb.Push(ResultSuccess);
96 83
84 // TODO
97 system.Exit(); 85 system.Exit();
98} 86}
99 87
@@ -120,8 +108,10 @@ void ISelfController::UnlockExit(HLERequestContext& ctx) {
120} 108}
121 109
122void ISelfController::EnterFatalSection(HLERequestContext& ctx) { 110void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
123 ++num_fatal_sections_entered; 111
124 LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); 112 std::scoped_lock lk{applet->lock};
113 applet->fatal_section_count++;
114 LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", applet->fatal_section_count);
125 115
126 IPC::ResponseBuilder rb{ctx, 2}; 116 IPC::ResponseBuilder rb{ctx, 2};
127 rb.Push(ResultSuccess); 117 rb.Push(ResultSuccess);
@@ -131,13 +121,14 @@ void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
131 LOG_DEBUG(Service_AM, "called."); 121 LOG_DEBUG(Service_AM, "called.");
132 122
133 // Entry and exit of fatal sections must be balanced. 123 // Entry and exit of fatal sections must be balanced.
134 if (num_fatal_sections_entered == 0) { 124 std::scoped_lock lk{applet->lock};
125 if (applet->fatal_section_count == 0) {
135 IPC::ResponseBuilder rb{ctx, 2}; 126 IPC::ResponseBuilder rb{ctx, 2};
136 rb.Push(Result{ErrorModule::AM, 512}); 127 rb.Push(AM::ResultFatalSectionCountImbalance);
137 return; 128 return;
138 } 129 }
139 130
140 --num_fatal_sections_entered; 131 applet->fatal_section_count--;
141 132
142 IPC::ResponseBuilder rb{ctx, 2}; 133 IPC::ResponseBuilder rb{ctx, 2};
143 rb.Push(ResultSuccess); 134 rb.Push(ResultSuccess);
@@ -146,11 +137,11 @@ void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
146void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { 137void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
147 LOG_WARNING(Service_AM, "(STUBBED) called"); 138 LOG_WARNING(Service_AM, "(STUBBED) called");
148 139
149 launchable_event->Signal(); 140 applet->library_applet_launchable_event.Signal();
150 141
151 IPC::ResponseBuilder rb{ctx, 2, 1}; 142 IPC::ResponseBuilder rb{ctx, 2, 1};
152 rb.Push(ResultSuccess); 143 rb.Push(ResultSuccess);
153 rb.PushCopyObjects(launchable_event->GetReadableEvent()); 144 rb.PushCopyObjects(applet->library_applet_launchable_event.GetHandle());
154} 145}
155 146
156void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { 147void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
@@ -158,7 +149,8 @@ void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
158 const auto permission = rp.PopEnum<ScreenshotPermission>(); 149 const auto permission = rp.PopEnum<ScreenshotPermission>();
159 LOG_DEBUG(Service_AM, "called, permission={}", permission); 150 LOG_DEBUG(Service_AM, "called, permission={}", permission);
160 151
161 screenshot_permission = permission; 152 std::scoped_lock lk{applet->lock};
153 applet->screenshot_permission = permission;
162 154
163 IPC::ResponseBuilder rb{ctx, 2}; 155 IPC::ResponseBuilder rb{ctx, 2};
164 rb.Push(ResultSuccess); 156 rb.Push(ResultSuccess);
@@ -167,8 +159,11 @@ void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
167void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { 159void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
168 IPC::RequestParser rp{ctx}; 160 IPC::RequestParser rp{ctx};
169 161
170 bool flag = rp.Pop<bool>(); 162 const bool notification_enabled = rp.Pop<bool>();
171 LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); 163 LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled);
164
165 std::scoped_lock lk{applet->lock};
166 applet->operation_mode_changed_notification_enabled = notification_enabled;
172 167
173 IPC::ResponseBuilder rb{ctx, 2}; 168 IPC::ResponseBuilder rb{ctx, 2};
174 rb.Push(ResultSuccess); 169 rb.Push(ResultSuccess);
@@ -177,28 +172,27 @@ void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx
177void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { 172void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
178 IPC::RequestParser rp{ctx}; 173 IPC::RequestParser rp{ctx};
179 174
180 bool flag = rp.Pop<bool>(); 175 const bool notification_enabled = rp.Pop<bool>();
181 LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); 176 LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled);
177
178 std::scoped_lock lk{applet->lock};
179 applet->performance_mode_changed_notification_enabled = notification_enabled;
182 180
183 IPC::ResponseBuilder rb{ctx, 2}; 181 IPC::ResponseBuilder rb{ctx, 2};
184 rb.Push(ResultSuccess); 182 rb.Push(ResultSuccess);
185} 183}
186 184
187void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { 185void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
188 // Takes 3 input u8s with each field located immediately after the previous
189 // u8, these are bool flags. No output.
190 IPC::RequestParser rp{ctx}; 186 IPC::RequestParser rp{ctx};
191 187
192 struct FocusHandlingModeParams { 188 const auto flags = rp.PopRaw<FocusHandlingMode>();
193 u8 unknown0;
194 u8 unknown1;
195 u8 unknown2;
196 };
197 const auto flags = rp.PopRaw<FocusHandlingModeParams>();
198 189
199 LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}", 190 LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
200 flags.unknown0, flags.unknown1, flags.unknown2); 191 flags.unknown0, flags.unknown1, flags.unknown2);
201 192
193 std::scoped_lock lk{applet->lock};
194 applet->focus_handling_mode = flags;
195
202 IPC::ResponseBuilder rb{ctx, 2}; 196 IPC::ResponseBuilder rb{ctx, 2};
203 rb.Push(ResultSuccess); 197 rb.Push(ResultSuccess);
204} 198}
@@ -206,24 +200,35 @@ void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
206void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { 200void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
207 LOG_WARNING(Service_AM, "(STUBBED) called"); 201 LOG_WARNING(Service_AM, "(STUBBED) called");
208 202
203 std::scoped_lock lk{applet->lock};
204 applet->restart_message_enabled = true;
205
209 IPC::ResponseBuilder rb{ctx, 2}; 206 IPC::ResponseBuilder rb{ctx, 2};
210 rb.Push(ResultSuccess); 207 rb.Push(ResultSuccess);
211} 208}
212 209
213void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { 210void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) {
214 // Takes 3 input u8s with each field located immediately after the previous
215 // u8, these are bool flags. No output.
216 IPC::RequestParser rp{ctx}; 211 IPC::RequestParser rp{ctx};
217 212
218 bool enabled = rp.Pop<bool>(); 213 const bool enabled = rp.Pop<bool>();
219 LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); 214 LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
220 215
216 std::scoped_lock lk{applet->lock};
217 ASSERT(applet->type == AppletType::Application);
218 applet->out_of_focus_suspension_enabled = enabled;
219
221 IPC::ResponseBuilder rb{ctx, 2}; 220 IPC::ResponseBuilder rb{ctx, 2};
222 rb.Push(ResultSuccess); 221 rb.Push(ResultSuccess);
223} 222}
224 223
225void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { 224void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
226 LOG_WARNING(Service_AM, "(STUBBED) called"); 225 IPC::RequestParser rp{ctx};
226
227 const auto orientation = rp.PopRaw<Capture::AlbumImageOrientation>();
228 LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", static_cast<s32>(orientation));
229
230 std::scoped_lock lk{applet->lock};
231 applet->album_image_orientation = orientation;
227 232
228 IPC::ResponseBuilder rb{ctx, 2}; 233 IPC::ResponseBuilder rb{ctx, 2};
229 rb.Push(ResultSuccess); 234 rb.Push(ResultSuccess);
@@ -232,14 +237,13 @@ void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
232void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { 237void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
233 LOG_WARNING(Service_AM, "(STUBBED) called"); 238 LOG_WARNING(Service_AM, "(STUBBED) called");
234 239
235 // TODO(Subv): Find out how AM determines the display to use, for now just 240 u64 layer_id{};
236 // create the layer in the Default display. 241 applet->managed_layer_holder.Initialize(&nvnflinger);
237 const auto display_id = nvnflinger.OpenDisplay("Default"); 242 applet->managed_layer_holder.CreateManagedDisplayLayer(&layer_id);
238 const auto layer_id = nvnflinger.CreateLayer(*display_id);
239 243
240 IPC::ResponseBuilder rb{ctx, 4}; 244 IPC::ResponseBuilder rb{ctx, 4};
241 rb.Push(ResultSuccess); 245 rb.Push(ResultSuccess);
242 rb.Push(*layer_id); 246 rb.Push(layer_id);
243} 247}
244 248
245void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { 249void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
@@ -252,56 +256,46 @@ void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
252void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { 256void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
253 LOG_WARNING(Service_AM, "(STUBBED) called"); 257 LOG_WARNING(Service_AM, "(STUBBED) called");
254 258
259 u64 buffer_id, layer_id;
260 applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id);
261
255 IPC::ResponseBuilder rb{ctx, 6}; 262 IPC::ResponseBuilder rb{ctx, 6};
256 rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); 263 rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
257 rb.Push<s64>(system_shared_buffer_id); 264 rb.Push<s64>(buffer_id);
258 rb.Push<s64>(system_shared_layer_id); 265 rb.Push<s64>(layer_id);
259} 266}
260 267
261void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { 268void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
262 LOG_WARNING(Service_AM, "(STUBBED) called"); 269 LOG_WARNING(Service_AM, "(STUBBED) called");
263 270
271 u64 buffer_id, layer_id;
272 applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id);
273
264 IPC::ResponseBuilder rb{ctx, 4}; 274 IPC::ResponseBuilder rb{ctx, 4};
265 rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); 275 rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
266 rb.Push<s64>(system_shared_buffer_id); 276 rb.Push<s64>(buffer_id);
267} 277}
268 278
269Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { 279Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) {
270 if (buffer_sharing_enabled) { 280 if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id)) {
271 return ResultSuccess; 281 return ResultSuccess;
272 } 282 }
273 283
274 if (system.GetFrontendAppletHolder().GetCurrentAppletId() <= AppletId::Application) { 284 return VI::ResultOperationFailed;
275 return VI::ResultOperationFailed;
276 }
277
278 const auto display_id = nvnflinger.OpenDisplay("Default");
279 const auto result = nvnflinger.GetSystemBufferManager().Initialize(
280 &system_shared_buffer_id, &system_shared_layer_id, *display_id);
281
282 if (result.IsSuccess()) {
283 buffer_sharing_enabled = true;
284 }
285
286 return result;
287} 285}
288 286
289void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { 287void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
290 LOG_WARNING(Service_AM, "(STUBBED) called"); 288 LOG_WARNING(Service_AM, "(STUBBED) called");
291 289
292 // TODO(Subv): Find out how AM determines the display to use, for now just 290 u64 layer_id{};
293 // create the layer in the Default display. 291 u64 recording_layer_id{};
294 // This calls nn::vi::CreateRecordingLayer() which creates another layer. 292 applet->managed_layer_holder.Initialize(&nvnflinger);
295 // Currently we do not support more than 1 layer per display, output 1 layer id for now. 293 applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(&layer_id, &recording_layer_id);
296 // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
297 // side effects.
298 // TODO: Support multiple layers
299 const auto display_id = nvnflinger.OpenDisplay("Default");
300 const auto layer_id = nvnflinger.CreateLayer(*display_id);
301 294
302 IPC::ResponseBuilder rb{ctx, 4}; 295 IPC::ResponseBuilder rb{ctx, 6};
303 rb.Push(ResultSuccess); 296 rb.Push(ResultSuccess);
304 rb.Push(*layer_id); 297 rb.Push(layer_id);
298 rb.Push(recording_layer_id);
305} 299}
306 300
307void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { 301void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
@@ -320,9 +314,12 @@ void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
320 314
321void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { 315void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
322 IPC::RequestParser rp{ctx}; 316 IPC::RequestParser rp{ctx};
323 idle_time_detection_extension = rp.Pop<u32>(); 317
324 LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}", 318 const auto extension = rp.PopRaw<IdleTimeDetectionExtension>();
325 idle_time_detection_extension); 319 LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", extension);
320
321 std::scoped_lock lk{applet->lock};
322 applet->idle_time_detection_extension = extension;
326 323
327 IPC::ResponseBuilder rb{ctx, 2}; 324 IPC::ResponseBuilder rb{ctx, 2};
328 rb.Push(ResultSuccess); 325 rb.Push(ResultSuccess);
@@ -331,9 +328,11 @@ void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
331void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { 328void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
332 LOG_WARNING(Service_AM, "(STUBBED) called"); 329 LOG_WARNING(Service_AM, "(STUBBED) called");
333 330
331 std::scoped_lock lk{applet->lock};
332
334 IPC::ResponseBuilder rb{ctx, 3}; 333 IPC::ResponseBuilder rb{ctx, 3};
335 rb.Push(ResultSuccess); 334 rb.Push(ResultSuccess);
336 rb.Push<u32>(idle_time_detection_extension); 335 rb.PushRaw<IdleTimeDetectionExtension>(applet->idle_time_detection_extension);
337} 336}
338 337
339void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { 338void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
@@ -345,7 +344,9 @@ void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
345 344
346void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { 345void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
347 IPC::RequestParser rp{ctx}; 346 IPC::RequestParser rp{ctx};
348 is_auto_sleep_disabled = rp.Pop<bool>(); 347
348 std::scoped_lock lk{applet->lock};
349 applet->auto_sleep_disabled = rp.Pop<bool>();
349 350
350 // On the system itself, if the previous state of is_auto_sleep_disabled 351 // On the system itself, if the previous state of is_auto_sleep_disabled
351 // differed from the current value passed in, it'd signify the internal 352 // differed from the current value passed in, it'd signify the internal
@@ -357,7 +358,7 @@ void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
357 // and it's sufficient to simply set the member variable for querying via 358 // and it's sufficient to simply set the member variable for querying via
358 // IsAutoSleepDisabled(). 359 // IsAutoSleepDisabled().
359 360
360 LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled); 361 LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", applet->auto_sleep_disabled);
361 362
362 IPC::ResponseBuilder rb{ctx, 2}; 363 IPC::ResponseBuilder rb{ctx, 2};
363 rb.Push(ResultSuccess); 364 rb.Push(ResultSuccess);
@@ -366,20 +367,23 @@ void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
366void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { 367void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
367 LOG_DEBUG(Service_AM, "called."); 368 LOG_DEBUG(Service_AM, "called.");
368 369
370 std::scoped_lock lk{applet->lock};
371
369 IPC::ResponseBuilder rb{ctx, 3}; 372 IPC::ResponseBuilder rb{ctx, 3};
370 rb.Push(ResultSuccess); 373 rb.Push(ResultSuccess);
371 rb.Push(is_auto_sleep_disabled); 374 rb.Push(applet->auto_sleep_disabled);
372} 375}
373 376
374void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { 377void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
375 LOG_DEBUG(Service_AM, "called."); 378 LOG_DEBUG(Service_AM, "called.");
376 379
380 std::scoped_lock lk{applet->lock};
377 // This command returns the total number of system ticks since ISelfController creation 381 // This command returns the total number of system ticks since ISelfController creation
378 // where the game was suspended. Since Yuzu doesn't implement game suspension, this command 382 // where the game was suspended. Since Yuzu doesn't implement game suspension, this command
379 // can just always return 0 ticks. 383 // can just always return 0 ticks.
380 IPC::ResponseBuilder rb{ctx, 4}; 384 IPC::ResponseBuilder rb{ctx, 4};
381 rb.Push(ResultSuccess); 385 rb.Push(ResultSuccess);
382 rb.Push<u64>(0); 386 rb.Push<u64>(applet->suspended_ticks);
383} 387}
384 388
385void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { 389void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
@@ -387,7 +391,7 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext&
387 391
388 IPC::ResponseBuilder rb{ctx, 2, 1}; 392 IPC::ResponseBuilder rb{ctx, 2, 1};
389 rb.Push(ResultSuccess); 393 rb.Push(ResultSuccess);
390 rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); 394 rb.PushCopyObjects(applet->accumulated_suspended_tick_changed_event.GetHandle());
391} 395}
392 396
393void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { 397void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) {
@@ -396,10 +400,11 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& c
396 // This service call sets an internal flag whether a notification is shown when an image is 400 // This service call sets an internal flag whether a notification is shown when an image is
397 // captured. Currently we do not support capturing images via the capture button, so this can be 401 // captured. Currently we do not support capturing images via the capture button, so this can be
398 // stubbed for now. 402 // stubbed for now.
399 const bool album_image_taken_notification_enabled = rp.Pop<bool>(); 403 const bool enabled = rp.Pop<bool>();
404 LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
400 405
401 LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}", 406 std::scoped_lock lk{applet->lock};
402 album_image_taken_notification_enabled); 407 applet->album_image_taken_notification_enabled = enabled;
403 408
404 IPC::ResponseBuilder rb{ctx, 2}; 409 IPC::ResponseBuilder rb{ctx, 2};
405 rb.Push(ResultSuccess); 410 rb.Push(ResultSuccess);
@@ -427,9 +432,11 @@ void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
427void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { 432void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) {
428 IPC::RequestParser rp{ctx}; 433 IPC::RequestParser rp{ctx};
429 434
430 const auto is_record_volume_muted = rp.Pop<bool>(); 435 const auto enabled = rp.Pop<bool>();
436 LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
431 437
432 LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted); 438 std::scoped_lock lk{applet->lock};
439 applet->record_volume_muted = enabled;
433 440
434 IPC::ResponseBuilder rb{ctx, 2}; 441 IPC::ResponseBuilder rb{ctx, 2};
435 rb.Push(ResultSuccess); 442 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h
index f157bb826..6e6975264 100644
--- a/src/core/hle/service/am/self_controller.h
+++ b/src/core/hle/service/am/self_controller.h
@@ -8,9 +8,12 @@
8 8
9namespace Service::AM { 9namespace Service::AM {
10 10
11struct Applet;
12
11class ISelfController final : public ServiceFramework<ISelfController> { 13class ISelfController final : public ServiceFramework<ISelfController> {
12public: 14public:
13 explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); 15 explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_,
16 Nvnflinger::Nvnflinger& nvnflinger_);
14 ~ISelfController() override; 17 ~ISelfController() override;
15 18
16private: 19private:
@@ -47,26 +50,8 @@ private:
47 50
48 Result EnsureBufferSharingEnabled(Kernel::KProcess* process); 51 Result EnsureBufferSharingEnabled(Kernel::KProcess* process);
49 52
50 enum class ScreenshotPermission : u32 {
51 Inherit = 0,
52 Enable = 1,
53 Disable = 2,
54 };
55
56 Nvnflinger::Nvnflinger& nvnflinger; 53 Nvnflinger::Nvnflinger& nvnflinger;
57 54 const std::shared_ptr<Applet> applet;
58 KernelHelpers::ServiceContext service_context;
59
60 Kernel::KEvent* launchable_event;
61 Kernel::KEvent* accumulated_suspended_tick_changed_event;
62
63 u32 idle_time_detection_extension = 0;
64 u64 num_fatal_sections_entered = 0;
65 u64 system_shared_buffer_id = 0;
66 u64 system_shared_layer_id = 0;
67 bool is_auto_sleep_disabled = false;
68 bool buffer_sharing_enabled = false;
69 ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
70}; 55};
71 56
72} // namespace Service::AM 57} // 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 d51a2c8db..e3013271b 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 @@
20namespace Service::AM { 20namespace Service::AM {
21 21
22ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, 22ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
23 std::shared_ptr<AppletMessageQueue> msg_queue_, 23 std::shared_ptr<Applet> applet_, Core::System& system_)
24 Core::System& system_) 24 : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
25 : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_}, 25 applet_)} {
26 msg_queue{std::move(msg_queue_)} {
27 // clang-format off 26 // clang-format off
28 static const FunctionInfo functions[] = { 27 static const FunctionInfo functions[] = {
29 {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, 28 {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
@@ -44,12 +43,14 @@ ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
44 RegisterHandlers(functions); 43 RegisterHandlers(functions);
45} 44}
46 45
46ISystemAppletProxy::~ISystemAppletProxy() = default;
47
47void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { 48void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
48 LOG_DEBUG(Service_AM, "called"); 49 LOG_DEBUG(Service_AM, "called");
49 50
50 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 51 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
51 rb.Push(ResultSuccess); 52 rb.Push(ResultSuccess);
52 rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); 53 rb.PushIpcInterface<ICommonStateGetter>(system, applet);
53} 54}
54 55
55void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) { 56void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) {
@@ -57,7 +58,7 @@ void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) {
57 58
58 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 59 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
59 rb.Push(ResultSuccess); 60 rb.Push(ResultSuccess);
60 rb.PushIpcInterface<ISelfController>(system, nvnflinger); 61 rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
61} 62}
62 63
63void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) { 64void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) {
@@ -65,7 +66,7 @@ void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) {
65 66
66 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 67 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
67 rb.Push(ResultSuccess); 68 rb.Push(ResultSuccess);
68 rb.PushIpcInterface<IWindowController>(system); 69 rb.PushIpcInterface<IWindowController>(system, applet);
69} 70}
70 71
71void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) { 72void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) {
@@ -89,7 +90,7 @@ void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
89 90
90 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 91 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
91 rb.Push(ResultSuccess); 92 rb.Push(ResultSuccess);
92 rb.PushIpcInterface<ILibraryAppletCreator>(system); 93 rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
93} 94}
94 95
95void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { 96void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
@@ -121,7 +122,7 @@ void ISystemAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
121 122
122 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 123 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
123 rb.Push(ResultSuccess); 124 rb.Push(ResultSuccess);
124 rb.PushIpcInterface<IAppletCommonFunctions>(system); 125 rb.PushIpcInterface<IAppletCommonFunctions>(system, applet);
125} 126}
126 127
127void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) { 128void 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 b8855b1d6..0390cd1e5 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 @@
8 8
9namespace Service::AM { 9namespace Service::AM {
10 10
11struct Applet;
12
11class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { 13class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
12public: 14public:
13 explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, 15 explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
14 std::shared_ptr<AppletMessageQueue> msg_queue_, 16 std::shared_ptr<Applet> applet_, Core::System& system_);
15 Core::System& system_); 17 ~ISystemAppletProxy();
16 18
17private: 19private:
18 void GetCommonStateGetter(HLERequestContext& ctx); 20 void GetCommonStateGetter(HLERequestContext& ctx);
@@ -28,7 +30,7 @@ private:
28 void GetDebugFunctions(HLERequestContext& ctx); 30 void GetDebugFunctions(HLERequestContext& ctx);
29 31
30 Nvnflinger::Nvnflinger& nvnflinger; 32 Nvnflinger::Nvnflinger& nvnflinger;
31 std::shared_ptr<AppletMessageQueue> msg_queue; 33 std::shared_ptr<Applet> applet;
32}; 34};
33 35
34} // namespace Service::AM 36} // namespace Service::AM
diff --git a/src/core/hle/service/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp
index f2ba3c134..430ca180b 100644
--- a/src/core/hle/service/am/window_controller.cpp
+++ b/src/core/hle/service/am/window_controller.cpp
@@ -1,13 +1,14 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/am/applet.h"
4#include "core/hle/service/am/window_controller.h" 5#include "core/hle/service/am/window_controller.h"
5#include "core/hle/service/ipc_helpers.h" 6#include "core/hle/service/ipc_helpers.h"
6 7
7namespace Service::AM { 8namespace Service::AM {
8 9
9IWindowController::IWindowController(Core::System& system_) 10IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_)
10 : ServiceFramework{system_, "IWindowController"} { 11 : ServiceFramework{system_, "IWindowController"}, applet{std::move(applet_)} {
11 // clang-format off 12 // clang-format off
12 static const FunctionInfo functions[] = { 13 static const FunctionInfo functions[] = {
13 {0, nullptr, "CreateWindow"}, 14 {0, nullptr, "CreateWindow"},
@@ -27,23 +28,22 @@ IWindowController::IWindowController(Core::System& system_)
27IWindowController::~IWindowController() = default; 28IWindowController::~IWindowController() = default;
28 29
29void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) { 30void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) {
30 const u64 process_id = system.ApplicationProcess()->GetProcessId();
31
32 LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
33
34 IPC::ResponseBuilder rb{ctx, 4}; 31 IPC::ResponseBuilder rb{ctx, 4};
35 rb.Push(ResultSuccess); 32 rb.Push(ResultSuccess);
36 rb.Push<u64>(process_id); 33 rb.Push<u64>(applet->aruid);
37} 34}
38 35
39void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) { 36void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
40 const u64 process_id = 0; 37 u64 aruid = 0;
38 if (auto caller = applet->caller_applet.lock(); caller) {
39 aruid = caller->aruid;
40 }
41 41
42 LOG_WARNING(Service_AM, "(STUBBED) called"); 42 LOG_WARNING(Service_AM, "(STUBBED) called");
43 43
44 IPC::ResponseBuilder rb{ctx, 4}; 44 IPC::ResponseBuilder rb{ctx, 4};
45 rb.Push(ResultSuccess); 45 rb.Push(ResultSuccess);
46 rb.Push<u64>(process_id); 46 rb.Push<u64>(aruid);
47} 47}
48 48
49void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { 49void 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 07b0e0e17..d97f93737 100644
--- a/src/core/hle/service/am/window_controller.h
+++ b/src/core/hle/service/am/window_controller.h
@@ -7,15 +7,19 @@
7 7
8namespace Service::AM { 8namespace Service::AM {
9 9
10struct Applet;
11
10class IWindowController final : public ServiceFramework<IWindowController> { 12class IWindowController final : public ServiceFramework<IWindowController> {
11public: 13public:
12 explicit IWindowController(Core::System& system_); 14 explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_);
13 ~IWindowController() override; 15 ~IWindowController() override;
14 16
15private: 17private:
16 void GetAppletResourceUserId(HLERequestContext& ctx); 18 void GetAppletResourceUserId(HLERequestContext& ctx);
17 void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx); 19 void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
18 void AcquireForegroundRights(HLERequestContext& ctx); 20 void AcquireForegroundRights(HLERequestContext& ctx);
21
22 const std::shared_ptr<Applet> applet;
19}; 23};
20 24
21} // namespace Service::AM 25} // namespace Service::AM
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 1f3d82c57..73058db9a 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -535,6 +535,12 @@ public:
535 RegisterHandlers(functions); 535 RegisterHandlers(functions);
536 } 536 }
537 537
538 ~IApplicationDisplayService() {
539 for (const auto layer_id : stray_layer_ids) {
540 nvnflinger.DestroyLayer(layer_id);
541 }
542 }
543
538private: 544private:
539 enum class ConvertedScaleMode : u64 { 545 enum class ConvertedScaleMode : u64 {
540 Freeze = 0, 546 Freeze = 0,
@@ -770,6 +776,7 @@ private:
770 return; 776 return;
771 } 777 }
772 778
779 stray_layer_ids.push_back(*layer_id);
773 const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); 780 const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id);
774 if (!buffer_queue_id) { 781 if (!buffer_queue_id) {
775 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); 782 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
@@ -916,6 +923,7 @@ private:
916 923
917 Nvnflinger::Nvnflinger& nvnflinger; 924 Nvnflinger::Nvnflinger& nvnflinger;
918 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; 925 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
926 std::vector<u64> stray_layer_ids;
919 bool vsync_event_fetched{false}; 927 bool vsync_event_fetched{false};
920}; 928};
921 929
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 718534ba1..e28df10bd 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -9,6 +9,7 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/service/am/am.h" 10#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/applet_ae.h" 11#include "core/hle/service/am/applet_ae.h"
12#include "core/hle/service/am/applet_manager.h"
12#include "core/hle/service/am/applet_message_queue.h" 13#include "core/hle/service/am/applet_message_queue.h"
13#include "core/hle/service/am/applet_oe.h" 14#include "core/hle/service/am/applet_oe.h"
14#include "core/hle/service/sm/sm.h" 15#include "core/hle/service/sm/sm.h"
@@ -48,22 +49,8 @@ void OnDockedModeChanged(bool last_state, bool new_state, Core::System& system)
48 if (!system.IsPoweredOn()) { 49 if (!system.IsPoweredOn()) {
49 return; 50 return;
50 } 51 }
51 Service::SM::ServiceManager& sm = system.ServiceManager();
52 52
53 // Message queue is shared between these services, we just need to signal an operation 53 system.GetAppletManager().OperationModeChanged();
54 // change to one and it will handle both automatically
55 auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
56 auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
57 bool has_signalled = false;
58
59 if (applet_oe != nullptr) {
60 applet_oe->GetMessageQueue()->OperationModeChanged();
61 has_signalled = true;
62 }
63
64 if (applet_ae != nullptr && !has_signalled) {
65 applet_ae->GetMessageQueue()->OperationModeChanged();
66 }
67} 54}
68 55
69ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent) 56ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent)
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 02508b20d..4e5c4da53 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -4783,36 +4783,12 @@ void GMainWindow::RequestGameExit() {
4783 return; 4783 return;
4784 } 4784 }
4785 4785
4786 auto& sm{system->ServiceManager()};
4787 auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
4788 auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
4789 bool has_signalled = false;
4790
4791 system->SetExitRequested(true); 4786 system->SetExitRequested(true);
4792 4787 system->GetAppletManager().RequestExit();
4793 if (applet_oe != nullptr) {
4794 applet_oe->GetMessageQueue()->RequestExit();
4795 has_signalled = true;
4796 }
4797
4798 if (applet_ae != nullptr && !has_signalled) {
4799 applet_ae->GetMessageQueue()->RequestExit();
4800 }
4801} 4788}
4802 4789
4803void GMainWindow::RequestGameResume() { 4790void GMainWindow::RequestGameResume() {
4804 auto& sm{system->ServiceManager()}; 4791 system->GetAppletManager().RequestResume();
4805 auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
4806 auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
4807
4808 if (applet_oe != nullptr) {
4809 applet_oe->GetMessageQueue()->RequestResume();
4810 return;
4811 }
4812
4813 if (applet_ae != nullptr) {
4814 applet_ae->GetMessageQueue()->RequestResume();
4815 }
4816} 4792}
4817 4793
4818void GMainWindow::filterBarSetChecked(bool state) { 4794void GMainWindow::filterBarSetChecked(bool state) {