summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Liam2023-12-30 20:51:23 -0500
committerGravatar Liam2024-01-29 18:43:45 -0500
commit7de6b410305fcfcd34078e62fbe0ceedb43663f9 (patch)
treeb5f3dc0d7631852a64466f3765e62e0707b8d0c8 /src
parentMerge pull request #12846 from german77/mii_const (diff)
downloadyuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar.gz
yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar.xz
yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.zip
service: split am into components
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt45
-rw-r--r--src/core/hle/service/am/am.cpp2677
-rw-r--r--src/core/hle/service/am/am.h454
-rw-r--r--src/core/hle/service/am/am_results.h14
-rw-r--r--src/core/hle/service/am/applet_ae.cpp258
-rw-r--r--src/core/hle/service/am/applet_common_functions.cpp47
-rw-r--r--src/core/hle/service/am/applet_common_functions.h19
-rw-r--r--src/core/hle/service/am/applet_message_queue.cpp68
-rw-r--r--src/core/hle/service/am/applet_message_queue.h75
-rw-r--r--src/core/hle/service/am/applet_oe.cpp100
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.cpp6
-rw-r--r--src/core/hle/service/am/applets/applet_controller.cpp1
-rw-r--r--src/core/hle/service/am/applets/applet_error.cpp1
-rw-r--r--src/core/hle/service/am/applets/applet_general_backend.cpp1
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.cpp1
-rw-r--r--src/core/hle/service/am/applets/applet_profile_select.cpp1
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard.cpp1
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.cpp1
-rw-r--r--src/core/hle/service/am/applets/applets.cpp6
-rw-r--r--src/core/hle/service/am/application_creator.cpp25
-rw-r--r--src/core/hle/service/am/application_creator.h16
-rw-r--r--src/core/hle/service/am/application_functions.cpp610
-rw-r--r--src/core/hle/service/am/application_functions.h63
-rw-r--r--src/core/hle/service/am/application_proxy.cpp114
-rw-r--r--src/core/hle/service/am/application_proxy.h32
-rw-r--r--src/core/hle/service/am/audio_controller.cpp91
-rw-r--r--src/core/hle/service/am/audio_controller.h36
-rw-r--r--src/core/hle/service/am/common_state_getter.cpp288
-rw-r--r--src/core/hle/service/am/common_state_getter.h78
-rw-r--r--src/core/hle/service/am/debug_functions.cpp44
-rw-r--r--src/core/hle/service/am/debug_functions.h16
-rw-r--r--src/core/hle/service/am/display_controller.cpp97
-rw-r--r--src/core/hle/service/am/display_controller.h24
-rw-r--r--src/core/hle/service/am/global_state_controller.cpp34
-rw-r--r--src/core/hle/service/am/global_state_controller.h16
-rw-r--r--src/core/hle/service/am/home_menu_functions.cpp57
-rw-r--r--src/core/hle/service/am/home_menu_functions.h25
-rw-r--r--src/core/hle/service/am/library_applet_accessor.cpp178
-rw-r--r--src/core/hle/service/am/library_applet_accessor.h34
-rw-r--r--src/core/hle/service/am/library_applet_creator.cpp145
-rw-r--r--src/core/hle/service/am/library_applet_creator.h22
-rw-r--r--src/core/hle/service/am/library_applet_proxy.cpp142
-rw-r--r--src/core/hle/service/am/library_applet_proxy.h35
-rw-r--r--src/core/hle/service/am/library_applet_self_accessor.cpp382
-rw-r--r--src/core/hle/service/am/library_applet_self_accessor.h38
-rw-r--r--src/core/hle/service/am/lock_accessor.cpp71
-rw-r--r--src/core/hle/service/am/lock_accessor.h28
-rw-r--r--src/core/hle/service/am/process_winding_controller.cpp73
-rw-r--r--src/core/hle/service/am/process_winding_controller.h20
-rw-r--r--src/core/hle/service/am/self_controller.cpp438
-rw-r--r--src/core/hle/service/am/self_controller.h72
-rw-r--r--src/core/hle/service/am/storage.cpp60
-rw-r--r--src/core/hle/service/am/storage.h42
-rw-r--r--src/core/hle/service/am/storage_accessor.cpp82
-rw-r--r--src/core/hle/service/am/storage_accessor.h24
-rw-r--r--src/core/hle/service/am/system_applet_proxy.cpp135
-rw-r--r--src/core/hle/service/am/system_applet_proxy.h34
-rw-r--r--src/core/hle/service/am/window_controller.cpp55
-rw-r--r--src/core/hle/service/am/window_controller.h21
-rw-r--r--src/yuzu/configuration/configure_input.cpp1
-rw-r--r--src/yuzu/main.cpp1
61 files changed, 4093 insertions, 3482 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index ea6b2c285..3a2ba9ed4 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -392,6 +392,7 @@ add_library(core STATIC
392 hle/service/acc/profile_manager.h 392 hle/service/acc/profile_manager.h
393 hle/service/am/am.cpp 393 hle/service/am/am.cpp
394 hle/service/am/am.h 394 hle/service/am/am.h
395 hle/service/am/am_results.h
395 hle/service/am/applet_ae.cpp 396 hle/service/am/applet_ae.cpp
396 hle/service/am/applet_ae.h 397 hle/service/am/applet_ae.h
397 hle/service/am/applet_oe.cpp 398 hle/service/am/applet_oe.cpp
@@ -417,12 +418,56 @@ add_library(core STATIC
417 hle/service/am/applets/applet_web_browser_types.h 418 hle/service/am/applets/applet_web_browser_types.h
418 hle/service/am/applets/applets.cpp 419 hle/service/am/applets/applets.cpp
419 hle/service/am/applets/applets.h 420 hle/service/am/applets/applets.h
421 hle/service/am/applet_common_functions.cpp
422 hle/service/am/applet_common_functions.h
423 hle/service/am/applet_message_queue.cpp
424 hle/service/am/applet_message_queue.h
425 hle/service/am/application_creator.cpp
426 hle/service/am/application_creator.h
427 hle/service/am/application_functions.cpp
428 hle/service/am/application_functions.h
429 hle/service/am/application_proxy.cpp
430 hle/service/am/application_proxy.h
431 hle/service/am/audio_controller.cpp
432 hle/service/am/audio_controller.h
433 hle/service/am/common_state_getter.cpp
434 hle/service/am/common_state_getter.h
435 hle/service/am/debug_functions.cpp
436 hle/service/am/debug_functions.h
437 hle/service/am/display_controller.cpp
438 hle/service/am/display_controller.h
439 hle/service/am/global_state_controller.cpp
440 hle/service/am/global_state_controller.h
441 hle/service/am/home_menu_functions.cpp
442 hle/service/am/home_menu_functions.h
420 hle/service/am/idle.cpp 443 hle/service/am/idle.cpp
421 hle/service/am/idle.h 444 hle/service/am/idle.h
445 hle/service/am/library_applet_accessor.cpp
446 hle/service/am/library_applet_accessor.h
447 hle/service/am/library_applet_creator.cpp
448 hle/service/am/library_applet_creator.h
449 hle/service/am/library_applet_proxy.cpp
450 hle/service/am/library_applet_proxy.h
451 hle/service/am/library_applet_self_accessor.cpp
452 hle/service/am/library_applet_self_accessor.h
453 hle/service/am/lock_accessor.cpp
454 hle/service/am/lock_accessor.h
422 hle/service/am/omm.cpp 455 hle/service/am/omm.cpp
423 hle/service/am/omm.h 456 hle/service/am/omm.h
457 hle/service/am/process_winding_controller.cpp
458 hle/service/am/process_winding_controller.h
459 hle/service/am/self_controller.cpp
460 hle/service/am/self_controller.h
461 hle/service/am/system_applet_proxy.cpp
462 hle/service/am/system_applet_proxy.h
424 hle/service/am/spsm.cpp 463 hle/service/am/spsm.cpp
425 hle/service/am/spsm.h 464 hle/service/am/spsm.h
465 hle/service/am/storage_accessor.cpp
466 hle/service/am/storage_accessor.h
467 hle/service/am/storage.cpp
468 hle/service/am/storage.h
469 hle/service/am/window_controller.cpp
470 hle/service/am/window_controller.h
426 hle/service/aoc/aoc_u.cpp 471 hle/service/aoc/aoc_u.cpp
427 hle/service/aoc/aoc_u.h 472 hle/service/aoc/aoc_u.h
428 hle/service/apm/apm.cpp 473 hle/service/apm/apm.cpp
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 38f67adcd..46bc4f703 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -1,2541 +1,17 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 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 <algorithm>
5#include <array>
6#include <cinttypes>
7#include <cstring>
8#include "common/settings.h"
9#include "common/settings_enums.h"
10#include "core/core.h"
11#include "core/core_timing.h"
12#include "core/file_sys/control_metadata.h"
13#include "core/file_sys/patch_manager.h"
14#include "core/file_sys/registered_cache.h"
15#include "core/file_sys/savedata_factory.h"
16#include "core/hle/kernel/k_event.h"
17#include "core/hle/kernel/k_transfer_memory.h"
18#include "core/hle/result.h"
19#include "core/hle/service/acc/profile_manager.h"
20#include "core/hle/service/am/am.h" 4#include "core/hle/service/am/am.h"
21#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"
22#include "core/hle/service/am/applet_oe.h" 7#include "core/hle/service/am/applet_oe.h"
23#include "core/hle/service/am/applets/applet_cabinet.h"
24#include "core/hle/service/am/applets/applet_controller.h"
25#include "core/hle/service/am/applets/applet_mii_edit_types.h"
26#include "core/hle/service/am/applets/applet_profile_select.h"
27#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
28#include "core/hle/service/am/applets/applet_web_browser.h"
29#include "core/hle/service/am/applets/applets.h"
30#include "core/hle/service/am/idle.h" 8#include "core/hle/service/am/idle.h"
31#include "core/hle/service/am/omm.h" 9#include "core/hle/service/am/omm.h"
32#include "core/hle/service/am/spsm.h" 10#include "core/hle/service/am/spsm.h"
33#include "core/hle/service/apm/apm_controller.h"
34#include "core/hle/service/apm/apm_interface.h"
35#include "core/hle/service/bcat/backend/backend.h"
36#include "core/hle/service/caps/caps_su.h"
37#include "core/hle/service/caps/caps_types.h"
38#include "core/hle/service/filesystem/filesystem.h"
39#include "core/hle/service/filesystem/save_data_controller.h"
40#include "core/hle/service/ipc_helpers.h"
41#include "core/hle/service/ns/ns.h"
42#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
43#include "core/hle/service/nvnflinger/nvnflinger.h"
44#include "core/hle/service/pm/pm.h"
45#include "core/hle/service/server_manager.h" 11#include "core/hle/service/server_manager.h"
46#include "core/hle/service/sm/sm.h"
47#include "core/hle/service/vi/vi.h"
48#include "core/hle/service/vi/vi_results.h"
49#include "core/memory.h"
50#include "hid_core/hid_types.h"
51#include "hid_core/resources/npad/npad.h"
52 12
53namespace Service::AM { 13namespace Service::AM {
54 14
55constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
56constexpr Result ResultNoMessages{ErrorModule::AM, 3};
57constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
58
59enum class LaunchParameterKind : u32 {
60 UserChannel = 1,
61 AccountPreselectedUser = 2,
62};
63
64constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
65
66struct LaunchParameterAccountPreselectedUser {
67 u32_le magic;
68 u32_le is_account_selected;
69 Common::UUID current_user;
70 INSERT_PADDING_BYTES(0x70);
71};
72static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
73
74IWindowController::IWindowController(Core::System& system_)
75 : ServiceFramework{system_, "IWindowController"} {
76 // clang-format off
77 static const FunctionInfo functions[] = {
78 {0, nullptr, "CreateWindow"},
79 {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
80 {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"},
81 {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
82 {11, nullptr, "ReleaseForegroundRights"},
83 {12, nullptr, "RejectToChangeIntoBackground"},
84 {20, nullptr, "SetAppletWindowVisibility"},
85 {21, nullptr, "SetAppletGpuTimeSlice"},
86 };
87 // clang-format on
88
89 RegisterHandlers(functions);
90}
91
92IWindowController::~IWindowController() = default;
93
94void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) {
95 const u64 process_id = system.ApplicationProcess()->GetProcessId();
96
97 LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
98
99 IPC::ResponseBuilder rb{ctx, 4};
100 rb.Push(ResultSuccess);
101 rb.Push<u64>(process_id);
102}
103
104void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
105 const u64 process_id = 0;
106
107 LOG_WARNING(Service_AM, "(STUBBED) called");
108
109 IPC::ResponseBuilder rb{ctx, 4};
110 rb.Push(ResultSuccess);
111 rb.Push<u64>(process_id);
112}
113
114void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) {
115 LOG_WARNING(Service_AM, "(STUBBED) called");
116 IPC::ResponseBuilder rb{ctx, 2};
117 rb.Push(ResultSuccess);
118}
119
120IAudioController::IAudioController(Core::System& system_)
121 : ServiceFramework{system_, "IAudioController"} {
122 // clang-format off
123 static const FunctionInfo functions[] = {
124 {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
125 {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"},
126 {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"},
127 {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"},
128 {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"},
129 };
130 // clang-format on
131
132 RegisterHandlers(functions);
133}
134
135IAudioController::~IAudioController() = default;
136
137void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) {
138 IPC::RequestParser rp{ctx};
139 const float main_applet_volume_tmp = rp.Pop<float>();
140 const float library_applet_volume_tmp = rp.Pop<float>();
141
142 LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
143 main_applet_volume_tmp, library_applet_volume_tmp);
144
145 // Ensure the volume values remain within the 0-100% range
146 main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
147 library_applet_volume =
148 std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
149
150 IPC::ResponseBuilder rb{ctx, 2};
151 rb.Push(ResultSuccess);
152}
153
154void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) {
155 LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume);
156 IPC::ResponseBuilder rb{ctx, 3};
157 rb.Push(ResultSuccess);
158 rb.Push(main_applet_volume);
159}
160
161void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) {
162 LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume);
163 IPC::ResponseBuilder rb{ctx, 3};
164 rb.Push(ResultSuccess);
165 rb.Push(library_applet_volume);
166}
167
168void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) {
169 struct Parameters {
170 float volume;
171 s64 fade_time_ns;
172 };
173 static_assert(sizeof(Parameters) == 16);
174
175 IPC::RequestParser rp{ctx};
176 const auto parameters = rp.PopRaw<Parameters>();
177
178 LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume,
179 parameters.fade_time_ns);
180
181 main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume);
182 fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns};
183
184 IPC::ResponseBuilder rb{ctx, 2};
185 rb.Push(ResultSuccess);
186}
187
188void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) {
189 IPC::RequestParser rp{ctx};
190 const float transparent_volume_rate_tmp = rp.Pop<float>();
191
192 LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp);
193
194 // Clamp volume range to 0-100%.
195 transparent_volume_rate =
196 std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume);
197
198 IPC::ResponseBuilder rb{ctx, 2};
199 rb.Push(ResultSuccess);
200}
201
202IDisplayController::IDisplayController(Core::System& system_)
203 : ServiceFramework{system_, "IDisplayController"} {
204 // clang-format off
205 static const FunctionInfo functions[] = {
206 {0, nullptr, "GetLastForegroundCaptureImage"},
207 {1, nullptr, "UpdateLastForegroundCaptureImage"},
208 {2, nullptr, "GetLastApplicationCaptureImage"},
209 {3, nullptr, "GetCallerAppletCaptureImage"},
210 {4, nullptr, "UpdateCallerAppletCaptureImage"},
211 {5, nullptr, "GetLastForegroundCaptureImageEx"},
212 {6, nullptr, "GetLastApplicationCaptureImageEx"},
213 {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"},
214 {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
215 {9, nullptr, "CopyBetweenCaptureBuffers"},
216 {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
217 {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
218 {12, nullptr, "AcquireLastForegroundCaptureBuffer"},
219 {13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
220 {14, nullptr, "AcquireCallerAppletCaptureBuffer"},
221 {15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
222 {16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
223 {17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
224 {18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
225 {20, nullptr, "ClearCaptureBuffer"},
226 {21, nullptr, "ClearAppletTransitionBuffer"},
227 {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"},
228 {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
229 {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"},
230 {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"},
231 {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"},
232 {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"},
233 {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
234 };
235 // clang-format on
236
237 RegisterHandlers(functions);
238}
239
240IDisplayController::~IDisplayController() = default;
241
242void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) {
243 LOG_WARNING(Service_AM, "(STUBBED) called");
244
245 IPC::ResponseBuilder rb{ctx, 4};
246 rb.Push(ResultSuccess);
247 rb.Push(1u);
248 rb.Push(0);
249}
250
251void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
252 LOG_WARNING(Service_AM, "(STUBBED) called");
253
254 IPC::ResponseBuilder rb{ctx, 2};
255 rb.Push(ResultSuccess);
256}
257
258void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
259 LOG_WARNING(Service_AM, "(STUBBED) called");
260
261 IPC::ResponseBuilder rb{ctx, 4};
262 rb.Push(ResultSuccess);
263 rb.Push(1U);
264 rb.Push(0);
265}
266
267void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
268 LOG_WARNING(Service_AM, "(STUBBED) called");
269
270 IPC::ResponseBuilder rb{ctx, 2};
271 rb.Push(ResultSuccess);
272}
273
274void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
275 LOG_WARNING(Service_AM, "(STUBBED) called");
276
277 IPC::ResponseBuilder rb{ctx, 4};
278 rb.Push(ResultSuccess);
279 rb.Push(1U);
280 rb.Push(0);
281}
282
283void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
284 LOG_WARNING(Service_AM, "(STUBBED) called");
285
286 IPC::ResponseBuilder rb{ctx, 2};
287 rb.Push(ResultSuccess);
288}
289
290IDebugFunctions::IDebugFunctions(Core::System& system_)
291 : ServiceFramework{system_, "IDebugFunctions"} {
292 // clang-format off
293 static const FunctionInfo functions[] = {
294 {0, nullptr, "NotifyMessageToHomeMenuForDebug"},
295 {1, nullptr, "OpenMainApplication"},
296 {10, nullptr, "PerformSystemButtonPressing"},
297 {20, nullptr, "InvalidateTransitionLayer"},
298 {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
299 {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
300 {40, nullptr, "GetAppletResourceUsageInfo"},
301 {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
302 {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
303 {100, nullptr, "SetCpuBoostModeForApplet"},
304 {101, nullptr, "CancelCpuBoostModeForApplet"},
305 {110, nullptr, "PushToAppletBoundChannelForDebug"},
306 {111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
307 {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
308 {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
309 {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
310 {130, nullptr, "FriendInvitationSetApplicationParameter"},
311 {131, nullptr, "FriendInvitationClearApplicationParameter"},
312 {132, nullptr, "FriendInvitationPushApplicationParameter"},
313 {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
314 {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
315 {300, nullptr, "TerminateAllRunningApplicationsForDebug"},
316 {900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
317 };
318 // clang-format on
319
320 RegisterHandlers(functions);
321}
322
323IDebugFunctions::~IDebugFunctions() = default;
324
325ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
326 : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_},
327 service_context{system, "ISelfController"} {
328 // clang-format off
329 static const FunctionInfo functions[] = {
330 {0, &ISelfController::Exit, "Exit"},
331 {1, &ISelfController::LockExit, "LockExit"},
332 {2, &ISelfController::UnlockExit, "UnlockExit"},
333 {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
334 {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
335 {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
336 {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
337 {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
338 {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"},
339 {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
340 {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
341 {15, nullptr, "SetScreenShotAppletIdentityInfo"},
342 {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
343 {17, nullptr, "SetControllerFirmwareUpdateSection"},
344 {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
345 {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
346 {20, nullptr, "SetDesirableKeyboardLayout"},
347 {21, nullptr, "GetScreenShotProgramId"},
348 {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
349 {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"},
350 {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"},
351 {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"},
352 {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
353 {45, nullptr, "SetManagedDisplayLayerSeparationMode"},
354 {46, nullptr, "SetRecordingLayerCompositionEnabled"},
355 {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
356 {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
357 {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
358 {61, nullptr, "SetMediaPlaybackState"},
359 {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
360 {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
361 {64, nullptr, "SetInputDetectionSourceSet"},
362 {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"},
363 {66, nullptr, "GetCurrentIlluminance"},
364 {67, nullptr, "IsIlluminanceAvailable"},
365 {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"},
366 {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"},
367 {70, nullptr, "ReportMultimediaError"},
368 {71, nullptr, "GetCurrentIlluminanceEx"},
369 {72, nullptr, "SetInputDetectionPolicy"},
370 {80, nullptr, "SetWirelessPriorityMode"},
371 {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
372 {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
373 {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
374 {110, nullptr, "SetApplicationAlbumUserData"},
375 {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"},
376 {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"},
377 {1000, nullptr, "GetDebugStorageChannel"},
378 };
379 // clang-format on
380
381 RegisterHandlers(functions);
382
383 launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent");
384
385 // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
386 // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
387 // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
388 // suspended if the event has previously been created by a call to
389 // GetAccumulatedSuspendedTickChangedEvent.
390
391 accumulated_suspended_tick_changed_event =
392 service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent");
393 accumulated_suspended_tick_changed_event->Signal();
394}
395
396ISelfController::~ISelfController() {
397 service_context.CloseEvent(launchable_event);
398 service_context.CloseEvent(accumulated_suspended_tick_changed_event);
399}
400
401void ISelfController::Exit(HLERequestContext& ctx) {
402 LOG_DEBUG(Service_AM, "called");
403
404 IPC::ResponseBuilder rb{ctx, 2};
405 rb.Push(ResultSuccess);
406
407 system.Exit();
408}
409
410void ISelfController::LockExit(HLERequestContext& ctx) {
411 LOG_DEBUG(Service_AM, "called");
412
413 system.SetExitLocked(true);
414
415 IPC::ResponseBuilder rb{ctx, 2};
416 rb.Push(ResultSuccess);
417}
418
419void ISelfController::UnlockExit(HLERequestContext& ctx) {
420 LOG_DEBUG(Service_AM, "called");
421
422 system.SetExitLocked(false);
423
424 IPC::ResponseBuilder rb{ctx, 2};
425 rb.Push(ResultSuccess);
426
427 if (system.GetExitRequested()) {
428 system.Exit();
429 }
430}
431
432void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
433 ++num_fatal_sections_entered;
434 LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
435
436 IPC::ResponseBuilder rb{ctx, 2};
437 rb.Push(ResultSuccess);
438}
439
440void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
441 LOG_DEBUG(Service_AM, "called.");
442
443 // Entry and exit of fatal sections must be balanced.
444 if (num_fatal_sections_entered == 0) {
445 IPC::ResponseBuilder rb{ctx, 2};
446 rb.Push(Result{ErrorModule::AM, 512});
447 return;
448 }
449
450 --num_fatal_sections_entered;
451
452 IPC::ResponseBuilder rb{ctx, 2};
453 rb.Push(ResultSuccess);
454}
455
456void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
457 LOG_WARNING(Service_AM, "(STUBBED) called");
458
459 launchable_event->Signal();
460
461 IPC::ResponseBuilder rb{ctx, 2, 1};
462 rb.Push(ResultSuccess);
463 rb.PushCopyObjects(launchable_event->GetReadableEvent());
464}
465
466void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
467 IPC::RequestParser rp{ctx};
468 const auto permission = rp.PopEnum<ScreenshotPermission>();
469 LOG_DEBUG(Service_AM, "called, permission={}", permission);
470
471 screenshot_permission = permission;
472
473 IPC::ResponseBuilder rb{ctx, 2};
474 rb.Push(ResultSuccess);
475}
476
477void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
478 IPC::RequestParser rp{ctx};
479
480 bool flag = rp.Pop<bool>();
481 LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
482
483 IPC::ResponseBuilder rb{ctx, 2};
484 rb.Push(ResultSuccess);
485}
486
487void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
488 IPC::RequestParser rp{ctx};
489
490 bool flag = rp.Pop<bool>();
491 LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
492
493 IPC::ResponseBuilder rb{ctx, 2};
494 rb.Push(ResultSuccess);
495}
496
497void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
498 // Takes 3 input u8s with each field located immediately after the previous
499 // u8, these are bool flags. No output.
500 IPC::RequestParser rp{ctx};
501
502 struct FocusHandlingModeParams {
503 u8 unknown0;
504 u8 unknown1;
505 u8 unknown2;
506 };
507 const auto flags = rp.PopRaw<FocusHandlingModeParams>();
508
509 LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
510 flags.unknown0, flags.unknown1, flags.unknown2);
511
512 IPC::ResponseBuilder rb{ctx, 2};
513 rb.Push(ResultSuccess);
514}
515
516void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
517 LOG_WARNING(Service_AM, "(STUBBED) called");
518
519 IPC::ResponseBuilder rb{ctx, 2};
520 rb.Push(ResultSuccess);
521}
522
523void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) {
524 // Takes 3 input u8s with each field located immediately after the previous
525 // u8, these are bool flags. No output.
526 IPC::RequestParser rp{ctx};
527
528 bool enabled = rp.Pop<bool>();
529 LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
530
531 IPC::ResponseBuilder rb{ctx, 2};
532 rb.Push(ResultSuccess);
533}
534
535void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
536 LOG_WARNING(Service_AM, "(STUBBED) called");
537
538 IPC::ResponseBuilder rb{ctx, 2};
539 rb.Push(ResultSuccess);
540}
541
542void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
543 LOG_WARNING(Service_AM, "(STUBBED) called");
544
545 // TODO(Subv): Find out how AM determines the display to use, for now just
546 // create the layer in the Default display.
547 const auto display_id = nvnflinger.OpenDisplay("Default");
548 const auto layer_id = nvnflinger.CreateLayer(*display_id);
549
550 IPC::ResponseBuilder rb{ctx, 4};
551 rb.Push(ResultSuccess);
552 rb.Push(*layer_id);
553}
554
555void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
556 LOG_WARNING(Service_AM, "(STUBBED) called");
557
558 IPC::ResponseBuilder rb{ctx, 2};
559 rb.Push(this->EnsureBufferSharingEnabled());
560}
561
562void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
563 LOG_WARNING(Service_AM, "(STUBBED) called");
564
565 IPC::ResponseBuilder rb{ctx, 6};
566 rb.Push(this->EnsureBufferSharingEnabled());
567 rb.Push<s64>(system_shared_buffer_id);
568 rb.Push<s64>(system_shared_layer_id);
569}
570
571void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
572 LOG_WARNING(Service_AM, "(STUBBED) called");
573
574 IPC::ResponseBuilder rb{ctx, 4};
575 rb.Push(this->EnsureBufferSharingEnabled());
576 rb.Push<s64>(system_shared_buffer_id);
577}
578
579Result ISelfController::EnsureBufferSharingEnabled() {
580 if (buffer_sharing_enabled) {
581 return ResultSuccess;
582 }
583
584 if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) {
585 return VI::ResultOperationFailed;
586 }
587
588 const auto display_id = nvnflinger.OpenDisplay("Default");
589 const auto result = nvnflinger.GetSystemBufferManager().Initialize(
590 &system_shared_buffer_id, &system_shared_layer_id, *display_id);
591
592 if (result.IsSuccess()) {
593 buffer_sharing_enabled = true;
594 }
595
596 return result;
597}
598
599void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
600 LOG_WARNING(Service_AM, "(STUBBED) called");
601
602 // TODO(Subv): Find out how AM determines the display to use, for now just
603 // create the layer in the Default display.
604 // This calls nn::vi::CreateRecordingLayer() which creates another layer.
605 // Currently we do not support more than 1 layer per display, output 1 layer id for now.
606 // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
607 // side effects.
608 // TODO: Support multiple layers
609 const auto display_id = nvnflinger.OpenDisplay("Default");
610 const auto layer_id = nvnflinger.CreateLayer(*display_id);
611
612 IPC::ResponseBuilder rb{ctx, 4};
613 rb.Push(ResultSuccess);
614 rb.Push(*layer_id);
615}
616
617void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
618 LOG_WARNING(Service_AM, "(STUBBED) called");
619
620 IPC::ResponseBuilder rb{ctx, 2};
621 rb.Push(ResultSuccess);
622}
623
624void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
625 LOG_WARNING(Service_AM, "(STUBBED) called");
626
627 IPC::ResponseBuilder rb{ctx, 2};
628 rb.Push(ResultSuccess);
629}
630
631void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
632 IPC::RequestParser rp{ctx};
633 idle_time_detection_extension = rp.Pop<u32>();
634 LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
635 idle_time_detection_extension);
636
637 IPC::ResponseBuilder rb{ctx, 2};
638 rb.Push(ResultSuccess);
639}
640
641void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
642 LOG_WARNING(Service_AM, "(STUBBED) called");
643
644 IPC::ResponseBuilder rb{ctx, 3};
645 rb.Push(ResultSuccess);
646 rb.Push<u32>(idle_time_detection_extension);
647}
648
649void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
650 LOG_WARNING(Service_AM, "(STUBBED) called");
651
652 IPC::ResponseBuilder rb{ctx, 2};
653 rb.Push(ResultSuccess);
654}
655
656void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
657 IPC::RequestParser rp{ctx};
658 is_auto_sleep_disabled = rp.Pop<bool>();
659
660 // On the system itself, if the previous state of is_auto_sleep_disabled
661 // differed from the current value passed in, it'd signify the internal
662 // window manager to update (and also increment some statistics like update counts)
663 //
664 // It'd also indicate this change to an idle handling context.
665 //
666 // However, given we're emulating this behavior, most of this can be ignored
667 // and it's sufficient to simply set the member variable for querying via
668 // IsAutoSleepDisabled().
669
670 LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled);
671
672 IPC::ResponseBuilder rb{ctx, 2};
673 rb.Push(ResultSuccess);
674}
675
676void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
677 LOG_DEBUG(Service_AM, "called.");
678
679 IPC::ResponseBuilder rb{ctx, 3};
680 rb.Push(ResultSuccess);
681 rb.Push(is_auto_sleep_disabled);
682}
683
684void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
685 LOG_DEBUG(Service_AM, "called.");
686
687 // This command returns the total number of system ticks since ISelfController creation
688 // where the game was suspended. Since Yuzu doesn't implement game suspension, this command
689 // can just always return 0 ticks.
690 IPC::ResponseBuilder rb{ctx, 4};
691 rb.Push(ResultSuccess);
692 rb.Push<u64>(0);
693}
694
695void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
696 LOG_DEBUG(Service_AM, "called.");
697
698 IPC::ResponseBuilder rb{ctx, 2, 1};
699 rb.Push(ResultSuccess);
700 rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
701}
702
703void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) {
704 IPC::RequestParser rp{ctx};
705
706 // This service call sets an internal flag whether a notification is shown when an image is
707 // captured. Currently we do not support capturing images via the capture button, so this can be
708 // stubbed for now.
709 const bool album_image_taken_notification_enabled = rp.Pop<bool>();
710
711 LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}",
712 album_image_taken_notification_enabled);
713
714 IPC::ResponseBuilder rb{ctx, 2};
715 rb.Push(ResultSuccess);
716}
717
718void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
719 IPC::RequestParser rp{ctx};
720
721 const auto report_option = rp.PopEnum<Capture::AlbumReportOption>();
722
723 LOG_INFO(Service_AM, "called, report_option={}", report_option);
724
725 const auto screenshot_service =
726 system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
727 "caps:su");
728
729 if (screenshot_service) {
730 screenshot_service->CaptureAndSaveScreenshot(report_option);
731 }
732
733 IPC::ResponseBuilder rb{ctx, 2};
734 rb.Push(ResultSuccess);
735}
736
737void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) {
738 IPC::RequestParser rp{ctx};
739
740 const auto is_record_volume_muted = rp.Pop<bool>();
741
742 LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted);
743
744 IPC::ResponseBuilder rb{ctx, 2};
745 rb.Push(ResultSuccess);
746}
747
748AppletMessageQueue::AppletMessageQueue(Core::System& system)
749 : service_context{system, "AppletMessageQueue"} {
750 on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived");
751 on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged");
752}
753
754AppletMessageQueue::~AppletMessageQueue() {
755 service_context.CloseEvent(on_new_message);
756 service_context.CloseEvent(on_operation_mode_changed);
757}
758
759Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() {
760 return on_new_message->GetReadableEvent();
761}
762
763Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() {
764 return on_operation_mode_changed->GetReadableEvent();
765}
766
767void AppletMessageQueue::PushMessage(AppletMessage msg) {
768 messages.push(msg);
769 on_new_message->Signal();
770}
771
772AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
773 if (messages.empty()) {
774 on_new_message->Clear();
775 return AppletMessage::None;
776 }
777 auto msg = messages.front();
778 messages.pop();
779 if (messages.empty()) {
780 on_new_message->Clear();
781 }
782 return msg;
783}
784
785std::size_t AppletMessageQueue::GetMessageCount() const {
786 return messages.size();
787}
788
789void AppletMessageQueue::RequestExit() {
790 PushMessage(AppletMessage::Exit);
791}
792
793void AppletMessageQueue::RequestResume() {
794 PushMessage(AppletMessage::Resume);
795}
796
797void AppletMessageQueue::FocusStateChanged() {
798 PushMessage(AppletMessage::FocusStateChanged);
799}
800
801void AppletMessageQueue::OperationModeChanged() {
802 PushMessage(AppletMessage::OperationModeChanged);
803 PushMessage(AppletMessage::PerformanceModeChanged);
804 on_operation_mode_changed->Signal();
805}
806
807ILockAccessor::ILockAccessor(Core::System& system_)
808 : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} {
809 // clang-format off
810 static const FunctionInfo functions[] = {
811 {1, &ILockAccessor::TryLock, "TryLock"},
812 {2, &ILockAccessor::Unlock, "Unlock"},
813 {3, &ILockAccessor::GetEvent, "GetEvent"},
814 {4,&ILockAccessor::IsLocked, "IsLocked"},
815 };
816 // clang-format on
817
818 RegisterHandlers(functions);
819
820 lock_event = service_context.CreateEvent("ILockAccessor::LockEvent");
821}
822
823ILockAccessor::~ILockAccessor() {
824 service_context.CloseEvent(lock_event);
825};
826
827void ILockAccessor::TryLock(HLERequestContext& ctx) {
828 IPC::RequestParser rp{ctx};
829 const auto return_handle = rp.Pop<bool>();
830
831 LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle);
832
833 // TODO: When return_handle is true this function should return the lock handle
834
835 is_locked = true;
836
837 IPC::ResponseBuilder rb{ctx, 3};
838 rb.Push(ResultSuccess);
839 rb.Push<u8>(is_locked);
840}
841
842void ILockAccessor::Unlock(HLERequestContext& ctx) {
843 LOG_INFO(Service_AM, "called");
844
845 is_locked = false;
846
847 IPC::ResponseBuilder rb{ctx, 2};
848 rb.Push(ResultSuccess);
849}
850
851void ILockAccessor::GetEvent(HLERequestContext& ctx) {
852 LOG_INFO(Service_AM, "called");
853
854 lock_event->Signal();
855
856 IPC::ResponseBuilder rb{ctx, 2, 1};
857 rb.Push(ResultSuccess);
858 rb.PushCopyObjects(lock_event->GetReadableEvent());
859}
860
861void ILockAccessor::IsLocked(HLERequestContext& ctx) {
862 LOG_INFO(Service_AM, "called");
863
864 IPC::ResponseBuilder rb{ctx, 2};
865 rb.Push(ResultSuccess);
866 rb.Push<u8>(is_locked);
867}
868
869ICommonStateGetter::ICommonStateGetter(Core::System& system_,
870 std::shared_ptr<AppletMessageQueue> msg_queue_)
871 : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)},
872 service_context{system_, "ICommonStateGetter"} {
873 // clang-format off
874 static const FunctionInfo functions[] = {
875 {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
876 {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
877 {2, nullptr, "GetThisAppletKind"},
878 {3, nullptr, "AllowToEnterSleep"},
879 {4, nullptr, "DisallowToEnterSleep"},
880 {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
881 {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
882 {7, nullptr, "GetCradleStatus"},
883 {8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
884 {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
885 {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"},
886 {11, nullptr, "ReleaseSleepLock"},
887 {12, nullptr, "ReleaseSleepLockTransiently"},
888 {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"},
889 {14, nullptr, "GetWakeupCount"},
890 {20, nullptr, "PushToGeneralChannel"},
891 {30, nullptr, "GetHomeButtonReaderLockAccessor"},
892 {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"},
893 {32, nullptr, "GetWriterLockAccessorEx"},
894 {40, nullptr, "GetCradleFwVersion"},
895 {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
896 {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
897 {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
898 {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
899 {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
900 {55, nullptr, "IsInControllerFirmwareUpdateSection"},
901 {59, nullptr, "SetVrPositionForDebug"},
902 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
903 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
904 {62, nullptr, "GetHdcpAuthenticationState"},
905 {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
906 {64, nullptr, "SetTvPowerStateMatchingMode"},
907 {65, nullptr, "GetApplicationIdByContentActionName"},
908 {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
909 {67, nullptr, "CancelCpuBoostMode"},
910 {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"},
911 {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"},
912 {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
913 {91, nullptr, "GetCurrentPerformanceConfiguration"},
914 {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
915 {110, nullptr, "OpenMyGpuErrorHandler"},
916 {120, nullptr, "GetAppletLaunchedHistory"},
917 {200, nullptr, "GetOperationModeSystemInfo"},
918 {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
919 {400, nullptr, "ActivateMigrationService"},
920 {401, nullptr, "DeactivateMigrationService"},
921 {500, nullptr, "DisableSleepTillShutdown"},
922 {501, nullptr, "SuppressDisablingSleepTemporarily"},
923 {502, nullptr, "IsSleepEnabled"},
924 {503, nullptr, "IsDisablingSleepSuppressed"},
925 {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
926 };
927 // clang-format on
928
929 RegisterHandlers(functions);
930
931 sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent");
932
933 // Configure applets to be in foreground state
934 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
935 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
936}
937
938ICommonStateGetter::~ICommonStateGetter() {
939 service_context.CloseEvent(sleep_lock_event);
940};
941
942void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
943 LOG_DEBUG(Service_AM, "called");
944
945 IPC::ResponseBuilder rb{ctx, 3};
946 rb.Push(ResultSuccess);
947 rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
948}
949
950void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) {
951 LOG_DEBUG(Service_AM, "called");
952
953 IPC::ResponseBuilder rb{ctx, 2, 1};
954 rb.Push(ResultSuccess);
955 rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent());
956}
957
958void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
959 LOG_DEBUG(Service_AM, "called");
960
961 const auto message = msg_queue->PopMessage();
962 IPC::ResponseBuilder rb{ctx, 3};
963
964 if (message == AppletMessageQueue::AppletMessage::None) {
965 LOG_ERROR(Service_AM, "Message queue is empty");
966 rb.Push(AM::ResultNoMessages);
967 rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
968 return;
969 }
970
971 rb.Push(ResultSuccess);
972 rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
973}
974
975void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
976 LOG_DEBUG(Service_AM, "(STUBBED) called");
977
978 IPC::ResponseBuilder rb{ctx, 3};
979 rb.Push(ResultSuccess);
980 rb.Push(static_cast<u8>(FocusState::InFocus));
981}
982
983void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
984 LOG_WARNING(Service_AM, "(STUBBED) called");
985
986 // Sleep lock is acquired immediately.
987 sleep_lock_event->Signal();
988
989 IPC::ResponseBuilder rb{ctx, 2};
990 rb.Push(ResultSuccess);
991}
992
993void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) {
994 IPC::RequestParser rp{ctx};
995 const auto unknown = rp.Pop<u32>();
996
997 LOG_INFO(Service_AM, "called, unknown={}", unknown);
998
999 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1000
1001 rb.Push(ResultSuccess);
1002 rb.PushIpcInterface<ILockAccessor>(system);
1003}
1004
1005void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
1006 LOG_WARNING(Service_AM, "called");
1007
1008 IPC::ResponseBuilder rb{ctx, 2, 1};
1009 rb.Push(ResultSuccess);
1010 rb.PushCopyObjects(sleep_lock_event->GetReadableEvent());
1011}
1012
1013void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
1014 LOG_DEBUG(Service_AM, "called");
1015
1016 IPC::ResponseBuilder rb{ctx, 3};
1017 rb.Push(ResultSuccess);
1018 rb.Push(vr_mode_state);
1019}
1020
1021void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
1022 IPC::RequestParser rp{ctx};
1023 vr_mode_state = rp.Pop<bool>();
1024
1025 LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off");
1026
1027 IPC::ResponseBuilder rb{ctx, 2};
1028 rb.Push(ResultSuccess);
1029}
1030
1031void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) {
1032 IPC::RequestParser rp{ctx};
1033 const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
1034
1035 LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
1036 is_lcd_backlight_off_enabled);
1037
1038 IPC::ResponseBuilder rb{ctx, 2};
1039 rb.Push(ResultSuccess);
1040}
1041
1042void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
1043 LOG_WARNING(Service_AM, "(STUBBED) called");
1044
1045 IPC::ResponseBuilder rb{ctx, 2};
1046 rb.Push(ResultSuccess);
1047}
1048
1049void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
1050 LOG_WARNING(Service_AM, "(STUBBED) called");
1051
1052 IPC::ResponseBuilder rb{ctx, 2};
1053 rb.Push(ResultSuccess);
1054}
1055
1056void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) {
1057 LOG_DEBUG(Service_AM, "called");
1058
1059 IPC::ResponseBuilder rb{ctx, 2, 1};
1060 rb.Push(ResultSuccess);
1061 rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent());
1062}
1063
1064void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
1065 LOG_DEBUG(Service_AM, "called");
1066
1067 IPC::ResponseBuilder rb{ctx, 4};
1068 rb.Push(ResultSuccess);
1069
1070 if (Settings::IsDockedMode()) {
1071 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
1072 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
1073 } else {
1074 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
1075 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
1076 }
1077}
1078
1079void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) {
1080 LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
1081
1082 const auto& sm = system.ServiceManager();
1083 const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
1084 ASSERT(apm_sys != nullptr);
1085
1086 apm_sys->SetCpuBoostMode(ctx);
1087}
1088
1089void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) {
1090 LOG_WARNING(Service_AM, "(STUBBED) called");
1091
1092 IPC::ResponseBuilder rb{ctx, 3};
1093 rb.Push(ResultSuccess);
1094 rb.Push(0);
1095}
1096
1097void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) {
1098 IPC::RequestParser rp{ctx};
1099 const auto system_button{rp.PopEnum<SystemButtonType>()};
1100
1101 LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button);
1102
1103 IPC::ResponseBuilder rb{ctx, 2};
1104 rb.Push(ResultSuccess);
1105}
1106
1107void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) {
1108 LOG_WARNING(Service_AM, "(STUBBED) called");
1109
1110 IPC::ResponseBuilder rb{ctx, 3};
1111 rb.Push(ResultSuccess);
1112 rb.PushEnum(SysPlatformRegion::Global);
1113}
1114
1115void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
1116 HLERequestContext& ctx) {
1117 LOG_WARNING(Service_AM, "(STUBBED) called");
1118
1119 IPC::ResponseBuilder rb{ctx, 2};
1120 rb.Push(ResultSuccess);
1121}
1122
1123IStorageImpl::~IStorageImpl() = default;
1124
1125class StorageDataImpl final : public IStorageImpl {
1126public:
1127 explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {}
1128
1129 std::vector<u8>& GetData() override {
1130 return buffer;
1131 }
1132
1133 const std::vector<u8>& GetData() const override {
1134 return buffer;
1135 }
1136
1137 std::size_t GetSize() const override {
1138 return buffer.size();
1139 }
1140
1141private:
1142 std::vector<u8> buffer;
1143};
1144
1145IStorage::IStorage(Core::System& system_, std::vector<u8>&& buffer)
1146 : ServiceFramework{system_, "IStorage"}, impl{std::make_shared<StorageDataImpl>(
1147 std::move(buffer))} {
1148 Register();
1149}
1150
1151void IStorage::Register() {
1152 // clang-format off
1153 static const FunctionInfo functions[] = {
1154 {0, &IStorage::Open, "Open"},
1155 {1, nullptr, "OpenTransferStorage"},
1156 };
1157 // clang-format on
1158
1159 RegisterHandlers(functions);
1160}
1161
1162IStorage::~IStorage() = default;
1163
1164void IStorage::Open(HLERequestContext& ctx) {
1165 LOG_DEBUG(Service_AM, "called");
1166
1167 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1168
1169 rb.Push(ResultSuccess);
1170 rb.PushIpcInterface<IStorageAccessor>(system, *this);
1171}
1172
1173void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
1174 const bool use_docked_mode{Settings::IsDockedMode()};
1175 LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
1176
1177 IPC::ResponseBuilder rb{ctx, 3};
1178 rb.Push(ResultSuccess);
1179 rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
1180}
1181
1182void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) {
1183 LOG_DEBUG(Service_AM, "called");
1184
1185 IPC::ResponseBuilder rb{ctx, 3};
1186 rb.Push(ResultSuccess);
1187 rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode());
1188}
1189
1190class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
1191public:
1192 explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<Applets::Applet> applet_)
1193 : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} {
1194 // clang-format off
1195 static const FunctionInfo functions[] = {
1196 {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
1197 {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
1198 {10, &ILibraryAppletAccessor::Start, "Start"},
1199 {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"},
1200 {25, nullptr, "Terminate"},
1201 {30, &ILibraryAppletAccessor::GetResult, "GetResult"},
1202 {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
1203 {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"},
1204 {100, &ILibraryAppletAccessor::PushInData, "PushInData"},
1205 {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
1206 {102, nullptr, "PushExtraStorage"},
1207 {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
1208 {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
1209 {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
1210 {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
1211 {110, nullptr, "NeedsToExitProcess"},
1212 {120, nullptr, "GetLibraryAppletInfo"},
1213 {150, nullptr, "RequestForAppletToGetForeground"},
1214 {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"},
1215 };
1216 // clang-format on
1217
1218 RegisterHandlers(functions);
1219 }
1220
1221private:
1222 void GetAppletStateChangedEvent(HLERequestContext& ctx) {
1223 LOG_DEBUG(Service_AM, "called");
1224
1225 IPC::ResponseBuilder rb{ctx, 2, 1};
1226 rb.Push(ResultSuccess);
1227 rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent());
1228 }
1229
1230 void IsCompleted(HLERequestContext& ctx) {
1231 LOG_DEBUG(Service_AM, "called");
1232
1233 IPC::ResponseBuilder rb{ctx, 3};
1234 rb.Push(ResultSuccess);
1235 rb.Push<u32>(applet->TransactionComplete());
1236 }
1237
1238 void GetResult(HLERequestContext& ctx) {
1239 LOG_DEBUG(Service_AM, "called");
1240
1241 IPC::ResponseBuilder rb{ctx, 2};
1242 rb.Push(applet->GetStatus());
1243 }
1244
1245 void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
1246 LOG_WARNING(Service_AM, "(STUBBED) called");
1247
1248 IPC::ResponseBuilder rb{ctx, 2};
1249 rb.Push(ResultSuccess);
1250 }
1251
1252 void Start(HLERequestContext& ctx) {
1253 LOG_DEBUG(Service_AM, "called");
1254
1255 ASSERT(applet != nullptr);
1256
1257 applet->Initialize();
1258 applet->Execute();
1259
1260 IPC::ResponseBuilder rb{ctx, 2};
1261 rb.Push(ResultSuccess);
1262 }
1263
1264 void RequestExit(HLERequestContext& ctx) {
1265 LOG_DEBUG(Service_AM, "called");
1266
1267 ASSERT(applet != nullptr);
1268
1269 IPC::ResponseBuilder rb{ctx, 2};
1270 rb.Push(applet->RequestExit());
1271 }
1272
1273 void PushInData(HLERequestContext& ctx) {
1274 LOG_DEBUG(Service_AM, "called");
1275
1276 IPC::RequestParser rp{ctx};
1277 applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>().lock());
1278
1279 IPC::ResponseBuilder rb{ctx, 2};
1280 rb.Push(ResultSuccess);
1281 }
1282
1283 void PopOutData(HLERequestContext& ctx) {
1284 LOG_DEBUG(Service_AM, "called");
1285
1286 auto storage = applet->GetBroker().PopNormalDataToGame();
1287 if (storage == nullptr) {
1288 LOG_DEBUG(Service_AM,
1289 "storage is a nullptr. There is no data in the current normal channel");
1290 IPC::ResponseBuilder rb{ctx, 2};
1291 rb.Push(AM::ResultNoDataInChannel);
1292 return;
1293 }
1294
1295 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1296 rb.Push(ResultSuccess);
1297 rb.PushIpcInterface<IStorage>(std::move(storage));
1298 }
1299
1300 void PushInteractiveInData(HLERequestContext& ctx) {
1301 LOG_DEBUG(Service_AM, "called");
1302
1303 IPC::RequestParser rp{ctx};
1304 applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>().lock());
1305
1306 ASSERT(applet->IsInitialized());
1307 applet->ExecuteInteractive();
1308 applet->Execute();
1309
1310 IPC::ResponseBuilder rb{ctx, 2};
1311 rb.Push(ResultSuccess);
1312 }
1313
1314 void PopInteractiveOutData(HLERequestContext& ctx) {
1315 LOG_DEBUG(Service_AM, "called");
1316
1317 auto storage = applet->GetBroker().PopInteractiveDataToGame();
1318 if (storage == nullptr) {
1319 LOG_DEBUG(Service_AM,
1320 "storage is a nullptr. There is no data in the current interactive channel");
1321 IPC::ResponseBuilder rb{ctx, 2};
1322 rb.Push(AM::ResultNoDataInChannel);
1323 return;
1324 }
1325
1326 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1327 rb.Push(ResultSuccess);
1328 rb.PushIpcInterface<IStorage>(std::move(storage));
1329 }
1330
1331 void GetPopOutDataEvent(HLERequestContext& ctx) {
1332 LOG_DEBUG(Service_AM, "called");
1333
1334 IPC::ResponseBuilder rb{ctx, 2, 1};
1335 rb.Push(ResultSuccess);
1336 rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
1337 }
1338
1339 void GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
1340 LOG_DEBUG(Service_AM, "called");
1341
1342 IPC::ResponseBuilder rb{ctx, 2, 1};
1343 rb.Push(ResultSuccess);
1344 rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
1345 }
1346
1347 void GetIndirectLayerConsumerHandle(HLERequestContext& ctx) {
1348 LOG_WARNING(Service_AM, "(STUBBED) called");
1349
1350 // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
1351 // actually used anywhere
1352 constexpr u64 handle = 0xdeadbeef;
1353
1354 IPC::ResponseBuilder rb{ctx, 4};
1355 rb.Push(ResultSuccess);
1356 rb.Push(handle);
1357 }
1358
1359 std::shared_ptr<Applets::Applet> applet;
1360};
1361
1362IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_)
1363 : ServiceFramework{system_, "IStorageAccessor"}, backing{backing_} {
1364 // clang-format off
1365 static const FunctionInfo functions[] = {
1366 {0, &IStorageAccessor::GetSize, "GetSize"},
1367 {10, &IStorageAccessor::Write, "Write"},
1368 {11, &IStorageAccessor::Read, "Read"},
1369 };
1370 // clang-format on
1371
1372 RegisterHandlers(functions);
1373}
1374
1375IStorageAccessor::~IStorageAccessor() = default;
1376
1377void IStorageAccessor::GetSize(HLERequestContext& ctx) {
1378 LOG_DEBUG(Service_AM, "called");
1379
1380 IPC::ResponseBuilder rb{ctx, 4};
1381
1382 rb.Push(ResultSuccess);
1383 rb.Push(static_cast<u64>(backing.GetSize()));
1384}
1385
1386void IStorageAccessor::Write(HLERequestContext& ctx) {
1387 IPC::RequestParser rp{ctx};
1388
1389 const u64 offset{rp.Pop<u64>()};
1390 const auto data{ctx.ReadBuffer()};
1391 const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)};
1392
1393 LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
1394
1395 if (offset > backing.GetSize()) {
1396 LOG_ERROR(Service_AM,
1397 "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}",
1398 backing.GetSize(), size, offset);
1399
1400 IPC::ResponseBuilder rb{ctx, 2};
1401 rb.Push(AM::ResultInvalidOffset);
1402 return;
1403 }
1404
1405 std::memcpy(backing.GetData().data() + offset, data.data(), size);
1406
1407 IPC::ResponseBuilder rb{ctx, 2};
1408 rb.Push(ResultSuccess);
1409}
1410
1411void IStorageAccessor::Read(HLERequestContext& ctx) {
1412 IPC::RequestParser rp{ctx};
1413
1414 const u64 offset{rp.Pop<u64>()};
1415 const std::size_t size{std::min<u64>(ctx.GetWriteBufferSize(), backing.GetSize() - offset)};
1416
1417 LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
1418
1419 if (offset > backing.GetSize()) {
1420 LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}",
1421 backing.GetSize(), size, offset);
1422
1423 IPC::ResponseBuilder rb{ctx, 2};
1424 rb.Push(AM::ResultInvalidOffset);
1425 return;
1426 }
1427
1428 ctx.WriteBuffer(backing.GetData().data() + offset, size);
1429
1430 IPC::ResponseBuilder rb{ctx, 2};
1431 rb.Push(ResultSuccess);
1432}
1433
1434ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
1435 : ServiceFramework{system_, "ILibraryAppletCreator"} {
1436 static const FunctionInfo functions[] = {
1437 {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
1438 {1, nullptr, "TerminateAllLibraryApplets"},
1439 {2, nullptr, "AreAnyLibraryAppletsLeft"},
1440 {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
1441 {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
1442 {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
1443 };
1444 RegisterHandlers(functions);
1445}
1446
1447ILibraryAppletCreator::~ILibraryAppletCreator() = default;
1448
1449void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
1450 IPC::RequestParser rp{ctx};
1451
1452 const auto applet_id = rp.PopRaw<Applets::AppletId>();
1453 const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>();
1454
1455 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
1456 applet_mode);
1457
1458 const auto& applet_manager{system.GetAppletManager()};
1459 const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
1460
1461 if (applet == nullptr) {
1462 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
1463
1464 IPC::ResponseBuilder rb{ctx, 2};
1465 rb.Push(ResultUnknown);
1466 return;
1467 }
1468
1469 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1470
1471 rb.Push(ResultSuccess);
1472 rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
1473}
1474
1475void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) {
1476 IPC::RequestParser rp{ctx};
1477
1478 const s64 size{rp.Pop<s64>()};
1479
1480 LOG_DEBUG(Service_AM, "called, size={}", size);
1481
1482 if (size <= 0) {
1483 LOG_ERROR(Service_AM, "size is less than or equal to 0");
1484 IPC::ResponseBuilder rb{ctx, 2};
1485 rb.Push(ResultUnknown);
1486 return;
1487 }
1488
1489 std::vector<u8> buffer(size);
1490
1491 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1492 rb.Push(ResultSuccess);
1493 rb.PushIpcInterface<IStorage>(system, std::move(buffer));
1494}
1495
1496void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) {
1497 IPC::RequestParser rp{ctx};
1498
1499 struct Parameters {
1500 u8 permissions;
1501 s64 size;
1502 };
1503
1504 const auto parameters{rp.PopRaw<Parameters>()};
1505 const auto handle{ctx.GetCopyHandle(0)};
1506
1507 LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions,
1508 parameters.size, handle);
1509
1510 if (parameters.size <= 0) {
1511 LOG_ERROR(Service_AM, "size is less than or equal to 0");
1512 IPC::ResponseBuilder rb{ctx, 2};
1513 rb.Push(ResultUnknown);
1514 return;
1515 }
1516
1517 auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
1518
1519 if (transfer_mem.IsNull()) {
1520 LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
1521 IPC::ResponseBuilder rb{ctx, 2};
1522 rb.Push(ResultUnknown);
1523 return;
1524 }
1525
1526 std::vector<u8> memory(transfer_mem->GetSize());
1527 ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
1528
1529 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1530 rb.Push(ResultSuccess);
1531 rb.PushIpcInterface<IStorage>(system, std::move(memory));
1532}
1533
1534void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
1535 IPC::RequestParser rp{ctx};
1536
1537 const s64 size{rp.Pop<s64>()};
1538 const auto handle{ctx.GetCopyHandle(0)};
1539
1540 LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
1541
1542 if (size <= 0) {
1543 LOG_ERROR(Service_AM, "size is less than or equal to 0");
1544 IPC::ResponseBuilder rb{ctx, 2};
1545 rb.Push(ResultUnknown);
1546 return;
1547 }
1548
1549 auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
1550
1551 if (transfer_mem.IsNull()) {
1552 LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
1553 IPC::ResponseBuilder rb{ctx, 2};
1554 rb.Push(ResultUnknown);
1555 return;
1556 }
1557
1558 std::vector<u8> memory(transfer_mem->GetSize());
1559 ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
1560
1561 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1562 rb.Push(ResultSuccess);
1563 rb.PushIpcInterface<IStorage>(system, std::move(memory));
1564}
1565
1566ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
1567 : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
1568 // clang-format off
1569 static const FunctionInfo functions[] = {
1570 {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
1571 {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
1572 {2, nullptr, "PopInteractiveInData"},
1573 {3, nullptr, "PushInteractiveOutData"},
1574 {5, nullptr, "GetPopInDataEvent"},
1575 {6, nullptr, "GetPopInteractiveInDataEvent"},
1576 {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
1577 {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
1578 {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
1579 {13, nullptr, "CanUseApplicationCore"},
1580 {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
1581 {15, nullptr, "GetMainAppletApplicationControlProperty"},
1582 {16, nullptr, "GetMainAppletStorageId"},
1583 {17, nullptr, "GetCallerAppletIdentityInfoStack"},
1584 {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
1585 {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"},
1586 {20, nullptr, "PopExtraStorage"},
1587 {25, nullptr, "GetPopExtraStorageEvent"},
1588 {30, nullptr, "UnpopInData"},
1589 {31, nullptr, "UnpopExtraStorage"},
1590 {40, nullptr, "GetIndirectLayerProducerHandle"},
1591 {50, nullptr, "ReportVisibleError"},
1592 {51, nullptr, "ReportVisibleErrorWithErrorContext"},
1593 {60, nullptr, "GetMainAppletApplicationDesiredLanguage"},
1594 {70, nullptr, "GetCurrentApplicationId"},
1595 {80, nullptr, "RequestExitToSelf"},
1596 {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
1597 {100, nullptr, "CreateGameMovieTrimmer"},
1598 {101, nullptr, "ReserveResourceForMovieOperation"},
1599 {102, nullptr, "UnreserveResourceForMovieOperation"},
1600 {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"},
1601 {120, nullptr, "GetLaunchStorageInfoForDebug"},
1602 {130, nullptr, "GetGpuErrorDetectedSystemEvent"},
1603 {140, nullptr, "SetApplicationMemoryReservation"},
1604 {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
1605 };
1606 // clang-format on
1607 RegisterHandlers(functions);
1608
1609 switch (system.GetAppletManager().GetCurrentAppletId()) {
1610 case Applets::AppletId::Cabinet:
1611 PushInShowCabinetData();
1612 break;
1613 case Applets::AppletId::MiiEdit:
1614 PushInShowMiiEditData();
1615 break;
1616 case Applets::AppletId::PhotoViewer:
1617 PushInShowAlbum();
1618 break;
1619 case Applets::AppletId::SoftwareKeyboard:
1620 PushInShowSoftwareKeyboard();
1621 break;
1622 case Applets::AppletId::Controller:
1623 PushInShowController();
1624 break;
1625 default:
1626 break;
1627 }
1628}
1629
1630ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
1631void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
1632 LOG_INFO(Service_AM, "called");
1633
1634 if (queue_data.empty()) {
1635 IPC::ResponseBuilder rb{ctx, 2};
1636 rb.Push(ResultNoDataInChannel);
1637 return;
1638 }
1639
1640 auto data = queue_data.front();
1641 queue_data.pop_front();
1642
1643 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1644 rb.Push(ResultSuccess);
1645 rb.PushIpcInterface<IStorage>(system, std::move(data));
1646}
1647
1648void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
1649 LOG_WARNING(Service_AM, "(STUBBED) called");
1650
1651 IPC::ResponseBuilder rb{ctx, 2};
1652 rb.Push(ResultSuccess);
1653}
1654
1655void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
1656 LOG_WARNING(Service_AM, "(STUBBED) called");
1657
1658 system.Exit();
1659
1660 IPC::ResponseBuilder rb{ctx, 2};
1661 rb.Push(ResultSuccess);
1662}
1663
1664void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
1665 struct LibraryAppletInfo {
1666 Applets::AppletId applet_id;
1667 Applets::LibraryAppletMode library_applet_mode;
1668 };
1669
1670 LOG_WARNING(Service_AM, "(STUBBED) called");
1671
1672 const LibraryAppletInfo applet_info{
1673 .applet_id = system.GetAppletManager().GetCurrentAppletId(),
1674 .library_applet_mode = Applets::LibraryAppletMode::AllForeground,
1675 };
1676
1677 IPC::ResponseBuilder rb{ctx, 4};
1678 rb.Push(ResultSuccess);
1679 rb.PushRaw(applet_info);
1680}
1681
1682void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
1683 struct AppletIdentityInfo {
1684 Applets::AppletId applet_id;
1685 INSERT_PADDING_BYTES(0x4);
1686 u64 application_id;
1687 };
1688 static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
1689
1690 LOG_WARNING(Service_AM, "(STUBBED) called");
1691
1692 const AppletIdentityInfo applet_info{
1693 .applet_id = Applets::AppletId::QLaunch,
1694 .application_id = 0x0100000000001000ull,
1695 };
1696
1697 IPC::ResponseBuilder rb{ctx, 6};
1698 rb.Push(ResultSuccess);
1699 rb.PushRaw(applet_info);
1700}
1701
1702void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
1703 struct AppletIdentityInfo {
1704 Applets::AppletId applet_id;
1705 INSERT_PADDING_BYTES(0x4);
1706 u64 application_id;
1707 };
1708 static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
1709 LOG_WARNING(Service_AM, "(STUBBED) called");
1710
1711 const AppletIdentityInfo applet_info{
1712 .applet_id = Applets::AppletId::QLaunch,
1713 .application_id = 0x0100000000001000ull,
1714 };
1715
1716 IPC::ResponseBuilder rb{ctx, 6};
1717 rb.Push(ResultSuccess);
1718 rb.PushRaw(applet_info);
1719}
1720
1721void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
1722 LOG_WARNING(Service_AM, "(STUBBED) called");
1723
1724 IPC::ResponseBuilder rb{ctx, 3};
1725 rb.Push(ResultSuccess);
1726 rb.Push<u32>(0);
1727}
1728
1729void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) {
1730 const Service::Account::ProfileManager manager{};
1731 bool is_empty{true};
1732 s32 user_count{-1};
1733
1734 LOG_INFO(Service_AM, "called");
1735
1736 if (manager.GetUserCount() > 0) {
1737 is_empty = false;
1738 user_count = static_cast<s32>(manager.GetUserCount());
1739 ctx.WriteBuffer(manager.GetAllUsers());
1740 }
1741
1742 IPC::ResponseBuilder rb{ctx, 4};
1743 rb.Push(ResultSuccess);
1744 rb.Push<u8>(is_empty);
1745 rb.Push(user_count);
1746}
1747
1748void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) {
1749 LOG_WARNING(Service_AM, "(STUBBED) called");
1750
1751 IPC::ResponseBuilder rb{ctx, 2};
1752 rb.Push(ResultSuccess);
1753 rb.Push<u8>(0);
1754}
1755
1756void ILibraryAppletSelfAccessor::PushInShowAlbum() {
1757 const Applets::CommonArguments arguments{
1758 .arguments_version = Applets::CommonArgumentVersion::Version3,
1759 .size = Applets::CommonArgumentSize::Version3,
1760 .library_version = 1,
1761 .theme_color = Applets::ThemeColor::BasicBlack,
1762 .play_startup_sound = true,
1763 .system_tick = system.CoreTiming().GetClockTicks(),
1764 };
1765
1766 std::vector<u8> argument_data(sizeof(arguments));
1767 std::vector<u8> settings_data{2};
1768 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
1769 queue_data.emplace_back(std::move(argument_data));
1770 queue_data.emplace_back(std::move(settings_data));
1771}
1772
1773void ILibraryAppletSelfAccessor::PushInShowController() {
1774 const Applets::CommonArguments common_args = {
1775 .arguments_version = Applets::CommonArgumentVersion::Version3,
1776 .size = Applets::CommonArgumentSize::Version3,
1777 .library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8),
1778 .theme_color = Applets::ThemeColor::BasicBlack,
1779 .play_startup_sound = true,
1780 .system_tick = system.CoreTiming().GetClockTicks(),
1781 };
1782
1783 Applets::ControllerSupportArgNew user_args = {
1784 .header = {.player_count_min = 1,
1785 .player_count_max = 4,
1786 .enable_take_over_connection = true,
1787 .enable_left_justify = false,
1788 .enable_permit_joy_dual = true,
1789 .enable_single_mode = false,
1790 .enable_identification_color = false},
1791 .identification_colors = {},
1792 .enable_explain_text = false,
1793 .explain_text = {},
1794 };
1795
1796 Applets::ControllerSupportArgPrivate private_args = {
1797 .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate),
1798 .arg_size = sizeof(Applets::ControllerSupportArgNew),
1799 .is_home_menu = true,
1800 .flag_1 = true,
1801 .mode = Applets::ControllerSupportMode::ShowControllerSupport,
1802 .caller = Applets::ControllerSupportCaller::
1803 Application, // switchbrew: Always zero except with
1804 // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem,
1805 // which sets this to the input param
1806 .style_set = Core::HID::NpadStyleSet::None,
1807 .joy_hold_type = 0,
1808 };
1809 std::vector<u8> common_args_data(sizeof(common_args));
1810 std::vector<u8> private_args_data(sizeof(private_args));
1811 std::vector<u8> user_args_data(sizeof(user_args));
1812
1813 std::memcpy(common_args_data.data(), &common_args, sizeof(common_args));
1814 std::memcpy(private_args_data.data(), &private_args, sizeof(private_args));
1815 std::memcpy(user_args_data.data(), &user_args, sizeof(user_args));
1816
1817 queue_data.emplace_back(std::move(common_args_data));
1818 queue_data.emplace_back(std::move(private_args_data));
1819 queue_data.emplace_back(std::move(user_args_data));
1820}
1821
1822void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
1823 const Applets::CommonArguments arguments{
1824 .arguments_version = Applets::CommonArgumentVersion::Version3,
1825 .size = Applets::CommonArgumentSize::Version3,
1826 .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1),
1827 .theme_color = Applets::ThemeColor::BasicBlack,
1828 .play_startup_sound = true,
1829 .system_tick = system.CoreTiming().GetClockTicks(),
1830 };
1831
1832 const Applets::StartParamForAmiiboSettings amiibo_settings{
1833 .param_1 = 0,
1834 .applet_mode = system.GetAppletManager().GetCabinetMode(),
1835 .flags = Applets::CabinetFlags::None,
1836 .amiibo_settings_1 = 0,
1837 .device_handle = 0,
1838 .tag_info{},
1839 .register_info{},
1840 .amiibo_settings_3{},
1841 };
1842
1843 std::vector<u8> argument_data(sizeof(arguments));
1844 std::vector<u8> settings_data(sizeof(amiibo_settings));
1845 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
1846 std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
1847 queue_data.emplace_back(std::move(argument_data));
1848 queue_data.emplace_back(std::move(settings_data));
1849}
1850
1851void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
1852 struct MiiEditV3 {
1853 Applets::MiiEditAppletInputCommon common;
1854 Applets::MiiEditAppletInputV3 input;
1855 };
1856 static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
1857
1858 MiiEditV3 mii_arguments{
1859 .common =
1860 {
1861 .version = Applets::MiiEditAppletVersion::Version3,
1862 .applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit,
1863 },
1864 .input{},
1865 };
1866
1867 std::vector<u8> argument_data(sizeof(mii_arguments));
1868 std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));
1869
1870 queue_data.emplace_back(std::move(argument_data));
1871}
1872
1873void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() {
1874 const Applets::CommonArguments arguments{
1875 .arguments_version = Applets::CommonArgumentVersion::Version3,
1876 .size = Applets::CommonArgumentSize::Version3,
1877 .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301),
1878 .theme_color = Applets::ThemeColor::BasicBlack,
1879 .play_startup_sound = true,
1880 .system_tick = system.CoreTiming().GetClockTicks(),
1881 };
1882
1883 std::vector<char16_t> initial_string(0);
1884
1885 const Applets::SwkbdConfigCommon swkbd_config{
1886 .type = Applets::SwkbdType::Qwerty,
1887 .ok_text{},
1888 .left_optional_symbol_key{},
1889 .right_optional_symbol_key{},
1890 .use_prediction = false,
1891 .key_disable_flags{},
1892 .initial_cursor_position = Applets::SwkbdInitialCursorPosition::Start,
1893 .header_text{},
1894 .sub_text{},
1895 .guide_text{},
1896 .max_text_length = 500,
1897 .min_text_length = 0,
1898 .password_mode = Applets::SwkbdPasswordMode::Disabled,
1899 .text_draw_type = Applets::SwkbdTextDrawType::Box,
1900 .enable_return_button = true,
1901 .use_utf8 = false,
1902 .use_blur_background = true,
1903 .initial_string_offset{},
1904 .initial_string_length = static_cast<u32>(initial_string.size()),
1905 .user_dictionary_offset{},
1906 .user_dictionary_entries{},
1907 .use_text_check = false,
1908 };
1909
1910 Applets::SwkbdConfigNew swkbd_config_new{};
1911
1912 std::vector<u8> argument_data(sizeof(arguments));
1913 std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new));
1914 std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t));
1915
1916 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
1917 std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config));
1918 std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new,
1919 sizeof(Applets::SwkbdConfigNew));
1920 std::memcpy(work_buffer.data(), initial_string.data(),
1921 swkbd_config.initial_string_length * sizeof(char16_t));
1922
1923 queue_data.emplace_back(std::move(argument_data));
1924 queue_data.emplace_back(std::move(swkbd_data));
1925 queue_data.emplace_back(std::move(work_buffer));
1926}
1927
1928IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
1929 : ServiceFramework{system_, "IAppletCommonFunctions"} {
1930 // clang-format off
1931 static const FunctionInfo functions[] = {
1932 {0, nullptr, "SetTerminateResult"},
1933 {10, nullptr, "ReadThemeStorage"},
1934 {11, nullptr, "WriteThemeStorage"},
1935 {20, nullptr, "PushToAppletBoundChannel"},
1936 {21, nullptr, "TryPopFromAppletBoundChannel"},
1937 {40, nullptr, "GetDisplayLogicalResolution"},
1938 {42, nullptr, "SetDisplayMagnification"},
1939 {50, nullptr, "SetHomeButtonDoubleClickEnabled"},
1940 {51, nullptr, "GetHomeButtonDoubleClickEnabled"},
1941 {52, nullptr, "IsHomeButtonShortPressedBlocked"},
1942 {60, nullptr, "IsVrModeCurtainRequired"},
1943 {61, nullptr, "IsSleepRequiredByHighTemperature"},
1944 {62, nullptr, "IsSleepRequiredByLowBattery"},
1945 {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"},
1946 {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
1947 {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
1948 {90, nullptr, "OpenNamedChannelAsParent"},
1949 {91, nullptr, "OpenNamedChannelAsChild"},
1950 {100, nullptr, "SetApplicationCoreUsageMode"},
1951 };
1952 // clang-format on
1953
1954 RegisterHandlers(functions);
1955}
1956
1957IAppletCommonFunctions::~IAppletCommonFunctions() = default;
1958
1959void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
1960 LOG_WARNING(Service_AM, "(STUBBED) called");
1961
1962 IPC::ResponseBuilder rb{ctx, 2};
1963 rb.Push(ResultSuccess);
1964}
1965
1966IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1967 : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
1968 "IApplicationFunctions"} {
1969 // clang-format off
1970 static const FunctionInfo functions[] = {
1971 {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
1972 {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
1973 {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
1974 {12, nullptr, "CreateApplicationAndRequestToStart"},
1975 {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
1976 {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
1977 {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
1978 {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
1979 {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
1980 {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
1981 {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
1982 {24, nullptr, "GetLaunchStorageInfoForDebug"},
1983 {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
1984 {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
1985 {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"},
1986 {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"},
1987 {29, nullptr, "GetCacheStorageMax"},
1988 {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
1989 {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
1990 {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
1991 {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
1992 {34, nullptr, "SelectApplicationLicense"},
1993 {35, nullptr, "GetDeviceSaveDataSizeMax"},
1994 {36, nullptr, "GetLimitedApplicationLicense"},
1995 {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
1996 {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
1997 {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
1998 {60, nullptr, "SetMediaPlaybackStateForApplication"},
1999 {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"},
2000 {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
2001 {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
2002 {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
2003 {70, nullptr, "RequestToShutdown"},
2004 {71, nullptr, "RequestToReboot"},
2005 {72, nullptr, "RequestToSleep"},
2006 {80, nullptr, "ExitAndRequestToShowThanksMessage"},
2007 {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
2008 {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
2009 {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
2010 {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
2011 {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"},
2012 {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"},
2013 {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"},
2014 {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"},
2015 {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"},
2016 {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
2017 {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
2018 {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
2019 {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
2020 {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
2021 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
2022 {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
2023 {151, nullptr, "TryPopFromNotificationStorageChannel"},
2024 {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
2025 {170, nullptr, "SetHdcpAuthenticationActivated"},
2026 {180, nullptr, "GetLaunchRequiredVersion"},
2027 {181, nullptr, "UpgradeLaunchRequiredVersion"},
2028 {190, nullptr, "SendServerMaintenanceOverlayNotification"},
2029 {200, nullptr, "GetLastApplicationExitReason"},
2030 {500, nullptr, "StartContinuousRecordingFlushForDebug"},
2031 {1000, nullptr, "CreateMovieMaker"},
2032 {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"},
2033 };
2034 // clang-format on
2035
2036 RegisterHandlers(functions);
2037
2038 gpu_error_detected_event =
2039 service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent");
2040 friend_invitation_storage_channel_event =
2041 service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent");
2042 notification_storage_channel_event =
2043 service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent");
2044 health_warning_disappeared_system_event =
2045 service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent");
2046}
2047
2048IApplicationFunctions::~IApplicationFunctions() {
2049 service_context.CloseEvent(gpu_error_detected_event);
2050 service_context.CloseEvent(friend_invitation_storage_channel_event);
2051 service_context.CloseEvent(notification_storage_channel_event);
2052 service_context.CloseEvent(health_warning_disappeared_system_event);
2053}
2054
2055void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
2056 LOG_WARNING(Service_AM, "(STUBBED) called");
2057
2058 IPC::ResponseBuilder rb{ctx, 2};
2059 rb.Push(ResultSuccess);
2060}
2061
2062void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) {
2063 LOG_WARNING(Service_AM, "(STUBBED) called");
2064
2065 IPC::ResponseBuilder rb{ctx, 2};
2066 rb.Push(ResultSuccess);
2067}
2068
2069void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) {
2070 LOG_WARNING(Service_AM, "(STUBBED) called");
2071
2072 IPC::ResponseBuilder rb{ctx, 2};
2073 rb.Push(ResultSuccess);
2074}
2075
2076void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) {
2077 IPC::RequestParser rp{ctx};
2078 const auto is_visible = rp.Pop<bool>();
2079
2080 LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
2081
2082 IPC::ResponseBuilder rb{ctx, 2};
2083 rb.Push(ResultSuccess);
2084}
2085
2086void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
2087 LOG_WARNING(Service_AM, "(STUBBED) called");
2088
2089 IPC::ResponseBuilder rb{ctx, 2};
2090 rb.Push(ResultSuccess);
2091}
2092
2093void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
2094 LOG_WARNING(Service_AM, "(STUBBED) called");
2095
2096 IPC::ResponseBuilder rb{ctx, 2};
2097 rb.Push(ResultSuccess);
2098}
2099
2100void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
2101 LOG_WARNING(Service_AM, "(STUBBED) called");
2102
2103 IPC::ResponseBuilder rb{ctx, 2};
2104 rb.Push(ResultSuccess);
2105}
2106
2107void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
2108 LOG_WARNING(Service_AM, "(STUBBED) called");
2109
2110 IPC::ResponseBuilder rb{ctx, 2};
2111 rb.Push(ResultSuccess);
2112}
2113
2114void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
2115 IPC::RequestParser rp{ctx};
2116 const auto kind = rp.PopEnum<LaunchParameterKind>();
2117
2118 LOG_INFO(Service_AM, "called, kind={:08X}", kind);
2119
2120 if (kind == LaunchParameterKind::UserChannel) {
2121 auto channel = system.GetUserChannel();
2122 if (channel.empty()) {
2123 LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
2124 IPC::ResponseBuilder rb{ctx, 2};
2125 rb.Push(AM::ResultNoDataInChannel);
2126 return;
2127 }
2128
2129 auto data = channel.back();
2130 channel.pop_back();
2131
2132 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
2133 rb.Push(ResultSuccess);
2134 rb.PushIpcInterface<IStorage>(system, std::move(data));
2135 } else if (kind == LaunchParameterKind::AccountPreselectedUser &&
2136 !launch_popped_account_preselect) {
2137 // TODO: Verify this is hw-accurate
2138 LaunchParameterAccountPreselectedUser params{};
2139
2140 params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
2141 params.is_account_selected = 1;
2142
2143 Account::ProfileManager profile_manager{};
2144 const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user));
2145 ASSERT(uuid.has_value() && uuid->IsValid());
2146 params.current_user = *uuid;
2147
2148 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
2149 rb.Push(ResultSuccess);
2150
2151 std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
2152 std::memcpy(buffer.data(), &params, buffer.size());
2153
2154 rb.PushIpcInterface<IStorage>(system, std::move(buffer));
2155 launch_popped_account_preselect = true;
2156 } else {
2157 LOG_ERROR(Service_AM, "Unknown launch parameter kind.");
2158 IPC::ResponseBuilder rb{ctx, 2};
2159 rb.Push(AM::ResultNoDataInChannel);
2160 }
2161}
2162
2163void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
2164 LOG_WARNING(Service_AM, "(STUBBED) called");
2165
2166 IPC::ResponseBuilder rb{ctx, 2};
2167 rb.Push(ResultSuccess);
2168}
2169
2170void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
2171 IPC::RequestParser rp{ctx};
2172 u128 user_id = rp.PopRaw<u128>();
2173
2174 LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
2175
2176 FileSys::SaveDataAttribute attribute{};
2177 attribute.title_id = system.GetApplicationProcessProgramID();
2178 attribute.user_id = user_id;
2179 attribute.type = FileSys::SaveDataType::SaveData;
2180
2181 FileSys::VirtualDir save_data{};
2182 const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
2183 &save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
2184
2185 IPC::ResponseBuilder rb{ctx, 4};
2186 rb.Push(res);
2187 rb.Push<u64>(0);
2188}
2189
2190void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) {
2191 // Takes an input u32 Result, no output.
2192 // For example, in some cases official apps use this with error 0x2A2 then
2193 // uses svcBreak.
2194
2195 IPC::RequestParser rp{ctx};
2196 u32 result = rp.Pop<u32>();
2197 LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
2198
2199 IPC::ResponseBuilder rb{ctx, 2};
2200 rb.Push(ResultSuccess);
2201}
2202
2203void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) {
2204 LOG_DEBUG(Service_AM, "called");
2205
2206 std::array<u8, 0x10> version_string{};
2207
2208 const auto res = [this] {
2209 const auto title_id = system.GetApplicationProcessProgramID();
2210
2211 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
2212 system.GetContentProvider()};
2213 auto metadata = pm.GetControlMetadata();
2214 if (metadata.first != nullptr) {
2215 return metadata;
2216 }
2217
2218 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
2219 system.GetFileSystemController(),
2220 system.GetContentProvider()};
2221 return pm_update.GetControlMetadata();
2222 }();
2223
2224 if (res.first != nullptr) {
2225 const auto& version = res.first->GetVersionString();
2226 std::copy(version.begin(), version.end(), version_string.begin());
2227 } else {
2228 static constexpr char default_version[]{"1.0.0"};
2229 std::memcpy(version_string.data(), default_version, sizeof(default_version));
2230 }
2231
2232 IPC::ResponseBuilder rb{ctx, 6};
2233 rb.Push(ResultSuccess);
2234 rb.PushRaw(version_string);
2235}
2236
2237void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
2238 // TODO(bunnei): This should be configurable
2239 LOG_DEBUG(Service_AM, "called");
2240
2241 // Get supported languages from NACP, if possible
2242 // Default to 0 (all languages supported)
2243 u32 supported_languages = 0;
2244
2245 const auto res = [this] {
2246 const auto title_id = system.GetApplicationProcessProgramID();
2247
2248 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
2249 system.GetContentProvider()};
2250 auto metadata = pm.GetControlMetadata();
2251 if (metadata.first != nullptr) {
2252 return metadata;
2253 }
2254
2255 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
2256 system.GetFileSystemController(),
2257 system.GetContentProvider()};
2258 return pm_update.GetControlMetadata();
2259 }();
2260
2261 if (res.first != nullptr) {
2262 supported_languages = res.first->GetSupportedLanguages();
2263 }
2264
2265 // Call IApplicationManagerInterface implementation.
2266 auto& service_manager = system.ServiceManager();
2267 auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
2268 auto app_man = ns_am2->GetApplicationManagerInterface();
2269
2270 // Get desired application language
2271 u8 desired_language{};
2272 const auto res_lang =
2273 app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
2274 if (res_lang != ResultSuccess) {
2275 IPC::ResponseBuilder rb{ctx, 2};
2276 rb.Push(res_lang);
2277 return;
2278 }
2279
2280 // Convert to settings language code.
2281 u64 language_code{};
2282 const auto res_code =
2283 app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
2284 if (res_code != ResultSuccess) {
2285 IPC::ResponseBuilder rb{ctx, 2};
2286 rb.Push(res_code);
2287 return;
2288 }
2289
2290 LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
2291
2292 IPC::ResponseBuilder rb{ctx, 4};
2293 rb.Push(ResultSuccess);
2294 rb.Push(language_code);
2295}
2296
2297void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
2298 LOG_WARNING(Service_AM, "(STUBBED) called");
2299
2300 constexpr bool gameplay_recording_supported = false;
2301
2302 IPC::ResponseBuilder rb{ctx, 3};
2303 rb.Push(ResultSuccess);
2304 rb.Push(gameplay_recording_supported);
2305}
2306
2307void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
2308 LOG_WARNING(Service_AM, "(STUBBED) called");
2309
2310 IPC::ResponseBuilder rb{ctx, 2};
2311 rb.Push(ResultSuccess);
2312}
2313
2314void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
2315 LOG_WARNING(Service_AM, "(STUBBED) called");
2316
2317 IPC::ResponseBuilder rb{ctx, 2};
2318 rb.Push(ResultSuccess);
2319}
2320
2321void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
2322 LOG_WARNING(Service_AM, "(STUBBED) called");
2323
2324 IPC::ResponseBuilder rb{ctx, 3};
2325 rb.Push(ResultSuccess);
2326 rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
2327}
2328
2329void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) {
2330 LOG_WARNING(Service_AM, "(STUBBED) called");
2331
2332 IPC::ResponseBuilder rb{ctx, 6};
2333 rb.Push(ResultSuccess);
2334
2335 // Returns a 128-bit UUID
2336 rb.Push<u64>(0);
2337 rb.Push<u64>(0);
2338}
2339
2340void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
2341 struct Parameters {
2342 FileSys::SaveDataType type;
2343 u128 user_id;
2344 u64 new_normal_size;
2345 u64 new_journal_size;
2346 };
2347 static_assert(sizeof(Parameters) == 40);
2348
2349 IPC::RequestParser rp{ctx};
2350 const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>();
2351
2352 LOG_DEBUG(Service_AM,
2353 "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
2354 "new_journal={:016X}",
2355 static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
2356
2357 system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
2358 type, system.GetApplicationProcessProgramID(), user_id,
2359 {new_normal_size, new_journal_size});
2360
2361 IPC::ResponseBuilder rb{ctx, 4};
2362 rb.Push(ResultSuccess);
2363
2364 // The following value is used upon failure to help the system recover.
2365 // Since we always succeed, this should be 0.
2366 rb.Push<u64>(0);
2367}
2368
2369void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
2370 struct Parameters {
2371 FileSys::SaveDataType type;
2372 u128 user_id;
2373 };
2374 static_assert(sizeof(Parameters) == 24);
2375
2376 IPC::RequestParser rp{ctx};
2377 const auto [type, user_id] = rp.PopRaw<Parameters>();
2378
2379 LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1],
2380 user_id[0]);
2381
2382 const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
2383 type, system.GetApplicationProcessProgramID(), user_id);
2384
2385 IPC::ResponseBuilder rb{ctx, 6};
2386 rb.Push(ResultSuccess);
2387 rb.Push(size.normal);
2388 rb.Push(size.journal);
2389}
2390
2391void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) {
2392 struct InputParameters {
2393 u16 index;
2394 s64 size;
2395 s64 journal_size;
2396 };
2397 static_assert(sizeof(InputParameters) == 24);
2398
2399 struct OutputParameters {
2400 u32 storage_target;
2401 u64 required_size;
2402 };
2403 static_assert(sizeof(OutputParameters) == 16);
2404
2405 IPC::RequestParser rp{ctx};
2406 const auto params = rp.PopRaw<InputParameters>();
2407
2408 LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}",
2409 params.index, params.size, params.journal_size);
2410
2411 const OutputParameters resp{
2412 .storage_target = 1,
2413 .required_size = 0,
2414 };
2415
2416 IPC::ResponseBuilder rb{ctx, 6};
2417 rb.Push(ResultSuccess);
2418 rb.PushRaw(resp);
2419}
2420
2421void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) {
2422 LOG_WARNING(Service_AM, "(STUBBED) called");
2423
2424 constexpr u64 size_max_normal = 0xFFFFFFF;
2425 constexpr u64 size_max_journal = 0xFFFFFFF;
2426
2427 IPC::ResponseBuilder rb{ctx, 6};
2428 rb.Push(ResultSuccess);
2429 rb.Push(size_max_normal);
2430 rb.Push(size_max_journal);
2431}
2432
2433void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) {
2434 LOG_WARNING(Service_AM, "(STUBBED) called");
2435
2436 IPC::ResponseBuilder rb{ctx, 3};
2437 rb.Push(ResultSuccess);
2438 rb.Push<u32>(0);
2439}
2440
2441void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) {
2442 LOG_WARNING(Service_AM, "(STUBBED) called");
2443
2444 IPC::ResponseBuilder rb{ctx, 3};
2445 rb.Push(ResultSuccess);
2446 rb.Push<u32>(0);
2447}
2448
2449void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
2450 LOG_WARNING(Service_AM, "(STUBBED) called");
2451
2452 IPC::RequestParser rp{ctx};
2453 [[maybe_unused]] const auto unk_1 = rp.Pop<u32>();
2454 [[maybe_unused]] const auto unk_2 = rp.Pop<u32>();
2455 const auto program_index = rp.Pop<u64>();
2456
2457 IPC::ResponseBuilder rb{ctx, 2};
2458 rb.Push(ResultSuccess);
2459
2460 system.ExecuteProgram(program_index);
2461}
2462
2463void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
2464 LOG_DEBUG(Service_AM, "called");
2465
2466 system.GetUserChannel().clear();
2467
2468 IPC::ResponseBuilder rb{ctx, 2};
2469 rb.Push(ResultSuccess);
2470}
2471
2472void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
2473 LOG_DEBUG(Service_AM, "called");
2474
2475 IPC::RequestParser rp{ctx};
2476 const auto storage = rp.PopIpcInterface<IStorage>().lock();
2477 if (storage) {
2478 system.GetUserChannel().push_back(storage->GetData());
2479 }
2480
2481 IPC::ResponseBuilder rb{ctx, 2};
2482 rb.Push(ResultSuccess);
2483}
2484
2485void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) {
2486 LOG_WARNING(Service_AM, "(STUBBED) called");
2487
2488 IPC::ResponseBuilder rb{ctx, 3};
2489 rb.Push(ResultSuccess);
2490 rb.Push<s32>(previous_program_index);
2491}
2492
2493void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
2494 LOG_WARNING(Service_AM, "(STUBBED) called");
2495
2496 IPC::ResponseBuilder rb{ctx, 2, 1};
2497 rb.Push(ResultSuccess);
2498 rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
2499}
2500
2501void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
2502 LOG_DEBUG(Service_AM, "called");
2503
2504 IPC::ResponseBuilder rb{ctx, 2, 1};
2505 rb.Push(ResultSuccess);
2506 rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
2507}
2508
2509void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
2510 LOG_DEBUG(Service_AM, "(STUBBED) called");
2511
2512 IPC::ResponseBuilder rb{ctx, 2};
2513 rb.Push(AM::ResultNoDataInChannel);
2514}
2515
2516void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) {
2517 LOG_DEBUG(Service_AM, "called");
2518
2519 IPC::ResponseBuilder rb{ctx, 2, 1};
2520 rb.Push(ResultSuccess);
2521 rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent());
2522}
2523
2524void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
2525 LOG_DEBUG(Service_AM, "called");
2526
2527 IPC::ResponseBuilder rb{ctx, 2, 1};
2528 rb.Push(ResultSuccess);
2529 rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
2530}
2531
2532void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
2533 LOG_WARNING(Service_AM, "(STUBBED) called");
2534
2535 IPC::ResponseBuilder rb{ctx, 2};
2536 rb.Push(ResultSuccess);
2537}
2538
2539void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { 15void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
2540 auto message_queue = std::make_shared<AppletMessageQueue>(system); 16 auto message_queue = std::make_shared<AppletMessageQueue>(system);
2541 auto server_manager = std::make_unique<ServerManager>(system); 17 auto server_manager = std::make_unique<ServerManager>(system);
@@ -2550,155 +26,4 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
2550 ServerManager::RunServer(std::move(server_manager)); 26 ServerManager::RunServer(std::move(server_manager));
2551} 27}
2552 28
2553IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
2554 : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system,
2555 "IHomeMenuFunctions"} {
2556 // clang-format off
2557 static const FunctionInfo functions[] = {
2558 {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
2559 {11, nullptr, "LockForeground"},
2560 {12, nullptr, "UnlockForeground"},
2561 {20, nullptr, "PopFromGeneralChannel"},
2562 {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
2563 {30, nullptr, "GetHomeButtonWriterLockAccessor"},
2564 {31, nullptr, "GetWriterLockAccessorEx"},
2565 {40, nullptr, "IsSleepEnabled"},
2566 {41, nullptr, "IsRebootEnabled"},
2567 {50, nullptr, "LaunchSystemApplet"},
2568 {51, nullptr, "LaunchStarter"},
2569 {100, nullptr, "PopRequestLaunchApplicationForDebug"},
2570 {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
2571 {200, nullptr, "LaunchDevMenu"},
2572 {1000, nullptr, "SetLastApplicationExitReason"},
2573 };
2574 // clang-format on
2575
2576 RegisterHandlers(functions);
2577
2578 pop_from_general_channel_event =
2579 service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent");
2580}
2581
2582IHomeMenuFunctions::~IHomeMenuFunctions() {
2583 service_context.CloseEvent(pop_from_general_channel_event);
2584}
2585
2586void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) {
2587 LOG_WARNING(Service_AM, "(STUBBED) called");
2588
2589 IPC::ResponseBuilder rb{ctx, 2};
2590 rb.Push(ResultSuccess);
2591}
2592
2593void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) {
2594 LOG_WARNING(Service_AM, "(STUBBED) called");
2595
2596 IPC::ResponseBuilder rb{ctx, 2, 1};
2597 rb.Push(ResultSuccess);
2598 rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
2599}
2600
2601IGlobalStateController::IGlobalStateController(Core::System& system_)
2602 : ServiceFramework{system_, "IGlobalStateController"} {
2603 // clang-format off
2604 static const FunctionInfo functions[] = {
2605 {0, nullptr, "RequestToEnterSleep"},
2606 {1, nullptr, "EnterSleep"},
2607 {2, nullptr, "StartSleepSequence"},
2608 {3, nullptr, "StartShutdownSequence"},
2609 {4, nullptr, "StartRebootSequence"},
2610 {9, nullptr, "IsAutoPowerDownRequested"},
2611 {10, nullptr, "LoadAndApplyIdlePolicySettings"},
2612 {11, nullptr, "NotifyCecSettingsChanged"},
2613 {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
2614 {13, nullptr, "UpdateDefaultDisplayResolution"},
2615 {14, nullptr, "ShouldSleepOnBoot"},
2616 {15, nullptr, "GetHdcpAuthenticationFailedEvent"},
2617 {30, nullptr, "OpenCradleFirmwareUpdater"},
2618 };
2619 // clang-format on
2620
2621 RegisterHandlers(functions);
2622}
2623
2624IGlobalStateController::~IGlobalStateController() = default;
2625
2626IApplicationCreator::IApplicationCreator(Core::System& system_)
2627 : ServiceFramework{system_, "IApplicationCreator"} {
2628 // clang-format off
2629 static const FunctionInfo functions[] = {
2630 {0, nullptr, "CreateApplication"},
2631 {1, nullptr, "PopLaunchRequestedApplication"},
2632 {10, nullptr, "CreateSystemApplication"},
2633 {100, nullptr, "PopFloatingApplicationForDevelopment"},
2634 };
2635 // clang-format on
2636
2637 RegisterHandlers(functions);
2638}
2639
2640IApplicationCreator::~IApplicationCreator() = default;
2641
2642IProcessWindingController::IProcessWindingController(Core::System& system_)
2643 : ServiceFramework{system_, "IProcessWindingController"} {
2644 // clang-format off
2645 static const FunctionInfo functions[] = {
2646 {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
2647 {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"},
2648 {21, nullptr, "PushContext"},
2649 {22, nullptr, "PopContext"},
2650 {23, nullptr, "CancelWindingReservation"},
2651 {30, nullptr, "WindAndDoReserved"},
2652 {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
2653 {41, nullptr, "ReserveToStartAndWait"},
2654 };
2655 // clang-format on
2656
2657 RegisterHandlers(functions);
2658}
2659
2660IProcessWindingController::~IProcessWindingController() = default;
2661
2662void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
2663 LOG_WARNING(Service_AM, "(STUBBED) called");
2664
2665 struct AppletProcessLaunchReason {
2666 u8 flag;
2667 INSERT_PADDING_BYTES(3);
2668 };
2669 static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
2670 "AppletProcessLaunchReason is an invalid size");
2671
2672 AppletProcessLaunchReason reason{
2673 .flag = 0,
2674 };
2675
2676 IPC::ResponseBuilder rb{ctx, 3};
2677 rb.Push(ResultSuccess);
2678 rb.PushRaw(reason);
2679}
2680
2681void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
2682 const auto applet_id = system.GetAppletManager().GetCurrentAppletId();
2683 const auto applet_mode = Applets::LibraryAppletMode::AllForeground;
2684
2685 LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
2686 applet_mode);
2687
2688 const auto& applet_manager{system.GetAppletManager()};
2689 const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
2690
2691 if (applet == nullptr) {
2692 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
2693
2694 IPC::ResponseBuilder rb{ctx, 2};
2695 rb.Push(ResultUnknown);
2696 return;
2697 }
2698
2699 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
2700 rb.Push(ResultSuccess);
2701 rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
2702}
2703
2704} // namespace Service::AM 29} // namespace Service::AM
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 905a71b9f..4a2d797bd 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -1,20 +1,11 @@
1// SPDX-FileCopyrightText: Copyright 2018 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#pragma once 4#pragma once
5 5
6#include <chrono> 6namespace Core {
7#include <memory> 7class System;
8#include <queue> 8}
9
10#include "core/hle/service/kernel_helpers.h"
11#include "core/hle/service/service.h"
12
13namespace Kernel {
14class KernelCore;
15class KReadableEvent;
16class KTransferMemory;
17} // namespace Kernel
18 9
19namespace Service::Nvnflinger { 10namespace Service::Nvnflinger {
20class Nvnflinger; 11class Nvnflinger;
@@ -22,443 +13,6 @@ class Nvnflinger;
22 13
23namespace Service::AM { 14namespace Service::AM {
24 15
25class AppletMessageQueue {
26public:
27 // This is nn::am::AppletMessage
28 enum class AppletMessage : u32 {
29 None = 0,
30 ChangeIntoForeground = 1,
31 ChangeIntoBackground = 2,
32 Exit = 4,
33 ApplicationExited = 6,
34 FocusStateChanged = 15,
35 Resume = 16,
36 DetectShortPressingHomeButton = 20,
37 DetectLongPressingHomeButton = 21,
38 DetectShortPressingPowerButton = 22,
39 DetectMiddlePressingPowerButton = 23,
40 DetectLongPressingPowerButton = 24,
41 RequestToPrepareSleep = 25,
42 FinishedSleepSequence = 26,
43 SleepRequiredByHighTemperature = 27,
44 SleepRequiredByLowBattery = 28,
45 AutoPowerDown = 29,
46 OperationModeChanged = 30,
47 PerformanceModeChanged = 31,
48 DetectReceivingCecSystemStandby = 32,
49 SdCardRemoved = 33,
50 LaunchApplicationRequested = 50,
51 RequestToDisplay = 51,
52 ShowApplicationLogo = 55,
53 HideApplicationLogo = 56,
54 ForceHideApplicationLogo = 57,
55 FloatingApplicationDetected = 60,
56 DetectShortPressingCaptureButton = 90,
57 AlbumScreenShotTaken = 92,
58 AlbumRecordingSaved = 93,
59 };
60
61 explicit AppletMessageQueue(Core::System& system);
62 ~AppletMessageQueue();
63
64 Kernel::KReadableEvent& GetMessageReceiveEvent();
65 Kernel::KReadableEvent& GetOperationModeChangedEvent();
66 void PushMessage(AppletMessage msg);
67 AppletMessage PopMessage();
68 std::size_t GetMessageCount() const;
69 void RequestExit();
70 void RequestResume();
71 void FocusStateChanged();
72 void OperationModeChanged();
73
74private:
75 KernelHelpers::ServiceContext service_context;
76
77 Kernel::KEvent* on_new_message;
78 Kernel::KEvent* on_operation_mode_changed;
79
80 std::queue<AppletMessage> messages;
81};
82
83class IWindowController final : public ServiceFramework<IWindowController> {
84public:
85 explicit IWindowController(Core::System& system_);
86 ~IWindowController() override;
87
88private:
89 void GetAppletResourceUserId(HLERequestContext& ctx);
90 void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
91 void AcquireForegroundRights(HLERequestContext& ctx);
92};
93
94class IAudioController final : public ServiceFramework<IAudioController> {
95public:
96 explicit IAudioController(Core::System& system_);
97 ~IAudioController() override;
98
99private:
100 void SetExpectedMasterVolume(HLERequestContext& ctx);
101 void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx);
102 void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx);
103 void ChangeMainAppletMasterVolume(HLERequestContext& ctx);
104 void SetTransparentAudioRate(HLERequestContext& ctx);
105
106 static constexpr float min_allowed_volume = 0.0f;
107 static constexpr float max_allowed_volume = 1.0f;
108
109 float main_applet_volume{0.25f};
110 float library_applet_volume{max_allowed_volume};
111 float transparent_volume_rate{min_allowed_volume};
112
113 // Volume transition fade time in nanoseconds.
114 // e.g. If the main applet volume was 0% and was changed to 50%
115 // with a fade of 50ns, then over the course of 50ns,
116 // the volume will gradually fade up to 50%
117 std::chrono::nanoseconds fade_time_ns{0};
118};
119
120class IDisplayController final : public ServiceFramework<IDisplayController> {
121public:
122 explicit IDisplayController(Core::System& system_);
123 ~IDisplayController() override;
124
125private:
126 void GetCallerAppletCaptureImageEx(HLERequestContext& ctx);
127 void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
128 void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
129 void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
130 void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
131 void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
132};
133
134class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
135public:
136 explicit IDebugFunctions(Core::System& system_);
137 ~IDebugFunctions() override;
138};
139
140class ISelfController final : public ServiceFramework<ISelfController> {
141public:
142 explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_);
143 ~ISelfController() override;
144
145private:
146 void Exit(HLERequestContext& ctx);
147 void LockExit(HLERequestContext& ctx);
148 void UnlockExit(HLERequestContext& ctx);
149 void EnterFatalSection(HLERequestContext& ctx);
150 void LeaveFatalSection(HLERequestContext& ctx);
151 void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx);
152 void SetScreenShotPermission(HLERequestContext& ctx);
153 void SetOperationModeChangedNotification(HLERequestContext& ctx);
154 void SetPerformanceModeChangedNotification(HLERequestContext& ctx);
155 void SetFocusHandlingMode(HLERequestContext& ctx);
156 void SetRestartMessageEnabled(HLERequestContext& ctx);
157 void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx);
158 void SetAlbumImageOrientation(HLERequestContext& ctx);
159 void IsSystemBufferSharingEnabled(HLERequestContext& ctx);
160 void GetSystemSharedBufferHandle(HLERequestContext& ctx);
161 void GetSystemSharedLayerHandle(HLERequestContext& ctx);
162 void CreateManagedDisplayLayer(HLERequestContext& ctx);
163 void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
164 void SetHandlesRequestToDisplay(HLERequestContext& ctx);
165 void ApproveToDisplay(HLERequestContext& ctx);
166 void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
167 void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
168 void ReportUserIsActive(HLERequestContext& ctx);
169 void SetAutoSleepDisabled(HLERequestContext& ctx);
170 void IsAutoSleepDisabled(HLERequestContext& ctx);
171 void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx);
172 void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx);
173 void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx);
174 void SaveCurrentScreenshot(HLERequestContext& ctx);
175 void SetRecordVolumeMuted(HLERequestContext& ctx);
176
177 Result EnsureBufferSharingEnabled();
178
179 enum class ScreenshotPermission : u32 {
180 Inherit = 0,
181 Enable = 1,
182 Disable = 2,
183 };
184
185 Nvnflinger::Nvnflinger& nvnflinger;
186
187 KernelHelpers::ServiceContext service_context;
188
189 Kernel::KEvent* launchable_event;
190 Kernel::KEvent* accumulated_suspended_tick_changed_event;
191
192 u32 idle_time_detection_extension = 0;
193 u64 num_fatal_sections_entered = 0;
194 u64 system_shared_buffer_id = 0;
195 u64 system_shared_layer_id = 0;
196 bool is_auto_sleep_disabled = false;
197 bool buffer_sharing_enabled = false;
198 ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
199};
200
201class ILockAccessor final : public ServiceFramework<ILockAccessor> {
202public:
203 explicit ILockAccessor(Core::System& system_);
204 ~ILockAccessor() override;
205
206private:
207 void TryLock(HLERequestContext& ctx);
208 void Unlock(HLERequestContext& ctx);
209 void GetEvent(HLERequestContext& ctx);
210 void IsLocked(HLERequestContext& ctx);
211
212 bool is_locked{};
213
214 Kernel::KEvent* lock_event;
215 KernelHelpers::ServiceContext service_context;
216};
217
218class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
219public:
220 explicit ICommonStateGetter(Core::System& system_,
221 std::shared_ptr<AppletMessageQueue> msg_queue_);
222 ~ICommonStateGetter() override;
223
224private:
225 // This is nn::oe::FocusState
226 enum class FocusState : u8 {
227 InFocus = 1,
228 NotInFocus = 2,
229 Background = 3,
230 };
231
232 // This is nn::oe::OperationMode
233 enum class OperationMode : u8 {
234 Handheld = 0,
235 Docked = 1,
236 };
237
238 // This is nn::am::service::SystemButtonType
239 enum class SystemButtonType {
240 None,
241 HomeButtonShortPressing,
242 HomeButtonLongPressing,
243 PowerButtonShortPressing,
244 PowerButtonLongPressing,
245 ShutdownSystem,
246 CaptureButtonShortPressing,
247 CaptureButtonLongPressing,
248 };
249
250 enum class SysPlatformRegion : s32 {
251 Global = 1,
252 Terra = 2,
253 };
254
255 void GetEventHandle(HLERequestContext& ctx);
256 void ReceiveMessage(HLERequestContext& ctx);
257 void GetCurrentFocusState(HLERequestContext& ctx);
258 void RequestToAcquireSleepLock(HLERequestContext& ctx);
259 void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
260 void GetReaderLockAccessorEx(HLERequestContext& ctx);
261 void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
262 void GetOperationMode(HLERequestContext& ctx);
263 void GetPerformanceMode(HLERequestContext& ctx);
264 void GetBootMode(HLERequestContext& ctx);
265 void IsVrModeEnabled(HLERequestContext& ctx);
266 void SetVrModeEnabled(HLERequestContext& ctx);
267 void SetLcdBacklighOffEnabled(HLERequestContext& ctx);
268 void BeginVrModeEx(HLERequestContext& ctx);
269 void EndVrModeEx(HLERequestContext& ctx);
270 void GetDefaultDisplayResolution(HLERequestContext& ctx);
271 void SetCpuBoostMode(HLERequestContext& ctx);
272 void GetBuiltInDisplayType(HLERequestContext& ctx);
273 void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
274 void GetSettingsPlatformRegion(HLERequestContext& ctx);
275 void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
276
277 std::shared_ptr<AppletMessageQueue> msg_queue;
278 bool vr_mode_state{};
279 Kernel::KEvent* sleep_lock_event;
280 KernelHelpers::ServiceContext service_context;
281};
282
283class IStorageImpl {
284public:
285 virtual ~IStorageImpl();
286 virtual std::vector<u8>& GetData() = 0;
287 virtual const std::vector<u8>& GetData() const = 0;
288 virtual std::size_t GetSize() const = 0;
289};
290
291class IStorage final : public ServiceFramework<IStorage> {
292public:
293 explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
294 ~IStorage() override;
295
296 std::vector<u8>& GetData() {
297 return impl->GetData();
298 }
299
300 const std::vector<u8>& GetData() const {
301 return impl->GetData();
302 }
303
304 std::size_t GetSize() const {
305 return impl->GetSize();
306 }
307
308private:
309 void Register();
310 void Open(HLERequestContext& ctx);
311
312 std::shared_ptr<IStorageImpl> impl;
313};
314
315class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
316public:
317 explicit IStorageAccessor(Core::System& system_, IStorage& backing_);
318 ~IStorageAccessor() override;
319
320private:
321 void GetSize(HLERequestContext& ctx);
322 void Write(HLERequestContext& ctx);
323 void Read(HLERequestContext& ctx);
324
325 IStorage& backing;
326};
327
328class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
329public:
330 explicit ILibraryAppletCreator(Core::System& system_);
331 ~ILibraryAppletCreator() override;
332
333private:
334 void CreateLibraryApplet(HLERequestContext& ctx);
335 void CreateStorage(HLERequestContext& ctx);
336 void CreateTransferMemoryStorage(HLERequestContext& ctx);
337 void CreateHandleStorage(HLERequestContext& ctx);
338};
339
340class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
341public:
342 explicit ILibraryAppletSelfAccessor(Core::System& system_);
343 ~ILibraryAppletSelfAccessor() override;
344
345private:
346 void PopInData(HLERequestContext& ctx);
347 void PushOutData(HLERequestContext& ctx);
348 void GetLibraryAppletInfo(HLERequestContext& ctx);
349 void GetMainAppletIdentityInfo(HLERequestContext& ctx);
350 void ExitProcessAndReturn(HLERequestContext& ctx);
351 void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
352 void GetDesirableKeyboardLayout(HLERequestContext& ctx);
353 void GetMainAppletAvailableUsers(HLERequestContext& ctx);
354 void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
355
356 void PushInShowAlbum();
357 void PushInShowCabinetData();
358 void PushInShowMiiEditData();
359 void PushInShowSoftwareKeyboard();
360 void PushInShowController();
361
362 std::deque<std::vector<u8>> queue_data;
363};
364
365class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
366public:
367 explicit IAppletCommonFunctions(Core::System& system_);
368 ~IAppletCommonFunctions() override;
369
370private:
371 void SetCpuBoostRequestPriority(HLERequestContext& ctx);
372};
373
374class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
375public:
376 explicit IApplicationFunctions(Core::System& system_);
377 ~IApplicationFunctions() override;
378
379private:
380 void PopLaunchParameter(HLERequestContext& ctx);
381 void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx);
382 void EnsureSaveData(HLERequestContext& ctx);
383 void SetTerminateResult(HLERequestContext& ctx);
384 void GetDisplayVersion(HLERequestContext& ctx);
385 void GetDesiredLanguage(HLERequestContext& ctx);
386 void IsGamePlayRecordingSupported(HLERequestContext& ctx);
387 void InitializeGamePlayRecording(HLERequestContext& ctx);
388 void SetGamePlayRecordingState(HLERequestContext& ctx);
389 void NotifyRunning(HLERequestContext& ctx);
390 void GetPseudoDeviceId(HLERequestContext& ctx);
391 void ExtendSaveData(HLERequestContext& ctx);
392 void GetSaveDataSize(HLERequestContext& ctx);
393 void CreateCacheStorage(HLERequestContext& ctx);
394 void GetSaveDataSizeMax(HLERequestContext& ctx);
395 void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
396 void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
397 void BeginBlockingHomeButton(HLERequestContext& ctx);
398 void EndBlockingHomeButton(HLERequestContext& ctx);
399 void EnableApplicationCrashReport(HLERequestContext& ctx);
400 void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx);
401 void SetApplicationCopyrightImage(HLERequestContext& ctx);
402 void SetApplicationCopyrightVisibility(HLERequestContext& ctx);
403 void QueryApplicationPlayStatistics(HLERequestContext& ctx);
404 void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx);
405 void ExecuteProgram(HLERequestContext& ctx);
406 void ClearUserChannel(HLERequestContext& ctx);
407 void UnpopToUserChannel(HLERequestContext& ctx);
408 void GetPreviousProgramIndex(HLERequestContext& ctx);
409 void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx);
410 void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx);
411 void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx);
412 void GetNotificationStorageChannelEvent(HLERequestContext& ctx);
413 void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
414 void PrepareForJit(HLERequestContext& ctx);
415
416 KernelHelpers::ServiceContext service_context;
417
418 bool launch_popped_account_preselect = false;
419 s32 previous_program_index{-1};
420 Kernel::KEvent* gpu_error_detected_event;
421 Kernel::KEvent* friend_invitation_storage_channel_event;
422 Kernel::KEvent* notification_storage_channel_event;
423 Kernel::KEvent* health_warning_disappeared_system_event;
424};
425
426class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
427public:
428 explicit IHomeMenuFunctions(Core::System& system_);
429 ~IHomeMenuFunctions() override;
430
431private:
432 void RequestToGetForeground(HLERequestContext& ctx);
433 void GetPopFromGeneralChannelEvent(HLERequestContext& ctx);
434
435 KernelHelpers::ServiceContext service_context;
436
437 Kernel::KEvent* pop_from_general_channel_event;
438};
439
440class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
441public:
442 explicit IGlobalStateController(Core::System& system_);
443 ~IGlobalStateController() override;
444};
445
446class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
447public:
448 explicit IApplicationCreator(Core::System& system_);
449 ~IApplicationCreator() override;
450};
451
452class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
453public:
454 explicit IProcessWindingController(Core::System& system_);
455 ~IProcessWindingController() override;
456
457private:
458 void GetLaunchReason(HLERequestContext& ctx);
459 void OpenCallingLibraryApplet(HLERequestContext& ctx);
460};
461
462void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); 16void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
463 17
464} // namespace Service::AM 18} // namespace Service::AM
diff --git a/src/core/hle/service/am/am_results.h b/src/core/hle/service/am/am_results.h
new file mode 100644
index 000000000..528b334ad
--- /dev/null
+++ b/src/core/hle/service/am/am_results.h
@@ -0,0 +1,14 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/result.h"
7
8namespace Service::AM {
9
10constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
11constexpr Result ResultNoMessages{ErrorModule::AM, 3};
12constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
13
14} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index e30e6478a..bd9e5f505 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -1,263 +1,13 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 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/logging/log.h"
5#include "core/core.h"
6#include "core/hle/service/am/am.h"
7#include "core/hle/service/am/applet_ae.h" 4#include "core/hle/service/am/applet_ae.h"
5#include "core/hle/service/am/library_applet_proxy.h"
6#include "core/hle/service/am/system_applet_proxy.h"
8#include "core/hle/service/ipc_helpers.h" 7#include "core/hle/service/ipc_helpers.h"
9#include "core/hle/service/nvnflinger/nvnflinger.h"
10 8
11namespace Service::AM { 9namespace Service::AM {
12 10
13class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
14public:
15 explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
16 std::shared_ptr<AppletMessageQueue> msg_queue_,
17 Core::System& system_)
18 : ServiceFramework{system_, "ILibraryAppletProxy"},
19 nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} {
20 // clang-format off
21 static const FunctionInfo functions[] = {
22 {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
23 {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
24 {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
25 {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
26 {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
27 {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
28 {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
29 {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
30 {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
31 {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
32 {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
33 {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
34 };
35 // clang-format on
36
37 RegisterHandlers(functions);
38 }
39
40private:
41 void GetCommonStateGetter(HLERequestContext& ctx) {
42 LOG_DEBUG(Service_AM, "called");
43
44 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
45 rb.Push(ResultSuccess);
46 rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
47 }
48
49 void GetSelfController(HLERequestContext& ctx) {
50 LOG_DEBUG(Service_AM, "called");
51
52 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
53 rb.Push(ResultSuccess);
54 rb.PushIpcInterface<ISelfController>(system, nvnflinger);
55 }
56
57 void GetWindowController(HLERequestContext& ctx) {
58 LOG_DEBUG(Service_AM, "called");
59
60 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
61 rb.Push(ResultSuccess);
62 rb.PushIpcInterface<IWindowController>(system);
63 }
64
65 void GetAudioController(HLERequestContext& ctx) {
66 LOG_DEBUG(Service_AM, "called");
67
68 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
69 rb.Push(ResultSuccess);
70 rb.PushIpcInterface<IAudioController>(system);
71 }
72
73 void GetDisplayController(HLERequestContext& ctx) {
74 LOG_DEBUG(Service_AM, "called");
75
76 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
77 rb.Push(ResultSuccess);
78 rb.PushIpcInterface<IDisplayController>(system);
79 }
80
81 void GetProcessWindingController(HLERequestContext& ctx) {
82 LOG_DEBUG(Service_AM, "called");
83
84 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
85 rb.Push(ResultSuccess);
86 rb.PushIpcInterface<IProcessWindingController>(system);
87 }
88
89 void GetLibraryAppletCreator(HLERequestContext& ctx) {
90 LOG_DEBUG(Service_AM, "called");
91
92 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
93 rb.Push(ResultSuccess);
94 rb.PushIpcInterface<ILibraryAppletCreator>(system);
95 }
96
97 void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
98 LOG_DEBUG(Service_AM, "called");
99
100 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
101 rb.Push(ResultSuccess);
102 rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
103 }
104
105 void GetAppletCommonFunctions(HLERequestContext& ctx) {
106 LOG_DEBUG(Service_AM, "called");
107
108 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
109 rb.Push(ResultSuccess);
110 rb.PushIpcInterface<IAppletCommonFunctions>(system);
111 }
112
113 void GetHomeMenuFunctions(HLERequestContext& ctx) {
114 LOG_DEBUG(Service_AM, "called");
115
116 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
117 rb.Push(ResultSuccess);
118 rb.PushIpcInterface<IHomeMenuFunctions>(system);
119 }
120
121 void GetGlobalStateController(HLERequestContext& ctx) {
122 LOG_DEBUG(Service_AM, "called");
123
124 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
125 rb.Push(ResultSuccess);
126 rb.PushIpcInterface<IGlobalStateController>(system);
127 }
128
129 void GetDebugFunctions(HLERequestContext& ctx) {
130 LOG_DEBUG(Service_AM, "called");
131
132 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
133 rb.Push(ResultSuccess);
134 rb.PushIpcInterface<IDebugFunctions>(system);
135 }
136
137 Nvnflinger::Nvnflinger& nvnflinger;
138 std::shared_ptr<AppletMessageQueue> msg_queue;
139};
140
141class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
142public:
143 explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
144 std::shared_ptr<AppletMessageQueue> msg_queue_,
145 Core::System& system_)
146 : ServiceFramework{system_, "ISystemAppletProxy"},
147 nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} {
148 // clang-format off
149 static const FunctionInfo functions[] = {
150 {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
151 {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"},
152 {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"},
153 {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"},
154 {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"},
155 {10, nullptr, "GetProcessWindingController"},
156 {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
157 {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
158 {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
159 {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
160 {23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
161 {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
162 };
163 // clang-format on
164
165 RegisterHandlers(functions);
166 }
167
168private:
169 void GetCommonStateGetter(HLERequestContext& ctx) {
170 LOG_DEBUG(Service_AM, "called");
171
172 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
173 rb.Push(ResultSuccess);
174 rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
175 }
176
177 void GetSelfController(HLERequestContext& ctx) {
178 LOG_DEBUG(Service_AM, "called");
179
180 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
181 rb.Push(ResultSuccess);
182 rb.PushIpcInterface<ISelfController>(system, nvnflinger);
183 }
184
185 void GetWindowController(HLERequestContext& ctx) {
186 LOG_DEBUG(Service_AM, "called");
187
188 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
189 rb.Push(ResultSuccess);
190 rb.PushIpcInterface<IWindowController>(system);
191 }
192
193 void GetAudioController(HLERequestContext& ctx) {
194 LOG_DEBUG(Service_AM, "called");
195
196 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
197 rb.Push(ResultSuccess);
198 rb.PushIpcInterface<IAudioController>(system);
199 }
200
201 void GetDisplayController(HLERequestContext& ctx) {
202 LOG_DEBUG(Service_AM, "called");
203
204 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
205 rb.Push(ResultSuccess);
206 rb.PushIpcInterface<IDisplayController>(system);
207 }
208
209 void GetLibraryAppletCreator(HLERequestContext& ctx) {
210 LOG_DEBUG(Service_AM, "called");
211
212 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
213 rb.Push(ResultSuccess);
214 rb.PushIpcInterface<ILibraryAppletCreator>(system);
215 }
216
217 void GetHomeMenuFunctions(HLERequestContext& ctx) {
218 LOG_DEBUG(Service_AM, "called");
219
220 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
221 rb.Push(ResultSuccess);
222 rb.PushIpcInterface<IHomeMenuFunctions>(system);
223 }
224
225 void GetGlobalStateController(HLERequestContext& ctx) {
226 LOG_DEBUG(Service_AM, "called");
227
228 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
229 rb.Push(ResultSuccess);
230 rb.PushIpcInterface<IGlobalStateController>(system);
231 }
232
233 void GetApplicationCreator(HLERequestContext& ctx) {
234 LOG_DEBUG(Service_AM, "called");
235
236 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
237 rb.Push(ResultSuccess);
238 rb.PushIpcInterface<IApplicationCreator>(system);
239 }
240
241 void GetAppletCommonFunctions(HLERequestContext& ctx) {
242 LOG_DEBUG(Service_AM, "called");
243
244 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
245 rb.Push(ResultSuccess);
246 rb.PushIpcInterface<IAppletCommonFunctions>(system);
247 }
248
249 void GetDebugFunctions(HLERequestContext& ctx) {
250 LOG_DEBUG(Service_AM, "called");
251
252 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
253 rb.Push(ResultSuccess);
254 rb.PushIpcInterface<IDebugFunctions>(system);
255 }
256
257 Nvnflinger::Nvnflinger& nvnflinger;
258 std::shared_ptr<AppletMessageQueue> msg_queue;
259};
260
261void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { 11void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) {
262 LOG_DEBUG(Service_AM, "called"); 12 LOG_DEBUG(Service_AM, "called");
263 13
@@ -284,8 +34,8 @@ void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) {
284 34
285AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, 35AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_,
286 std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) 36 std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_)
287 : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_}, msg_queue{ 37 : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_},
288 std::move(msg_queue_)} { 38 msg_queue{std::move(msg_queue_)} {
289 // clang-format off 39 // clang-format off
290 static const FunctionInfo functions[] = { 40 static const FunctionInfo functions[] = {
291 {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, 41 {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
diff --git a/src/core/hle/service/am/applet_common_functions.cpp b/src/core/hle/service/am/applet_common_functions.cpp
new file mode 100644
index 000000000..81c01a48b
--- /dev/null
+++ b/src/core/hle/service/am/applet_common_functions.cpp
@@ -0,0 +1,47 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applet_common_functions.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
10 : ServiceFramework{system_, "IAppletCommonFunctions"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, nullptr, "SetTerminateResult"},
14 {10, nullptr, "ReadThemeStorage"},
15 {11, nullptr, "WriteThemeStorage"},
16 {20, nullptr, "PushToAppletBoundChannel"},
17 {21, nullptr, "TryPopFromAppletBoundChannel"},
18 {40, nullptr, "GetDisplayLogicalResolution"},
19 {42, nullptr, "SetDisplayMagnification"},
20 {50, nullptr, "SetHomeButtonDoubleClickEnabled"},
21 {51, nullptr, "GetHomeButtonDoubleClickEnabled"},
22 {52, nullptr, "IsHomeButtonShortPressedBlocked"},
23 {60, nullptr, "IsVrModeCurtainRequired"},
24 {61, nullptr, "IsSleepRequiredByHighTemperature"},
25 {62, nullptr, "IsSleepRequiredByLowBattery"},
26 {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"},
27 {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
28 {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
29 {90, nullptr, "OpenNamedChannelAsParent"},
30 {91, nullptr, "OpenNamedChannelAsChild"},
31 {100, nullptr, "SetApplicationCoreUsageMode"},
32 };
33 // clang-format on
34
35 RegisterHandlers(functions);
36}
37
38IAppletCommonFunctions::~IAppletCommonFunctions() = default;
39
40void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
41 LOG_WARNING(Service_AM, "(STUBBED) called");
42
43 IPC::ResponseBuilder rb{ctx, 2};
44 rb.Push(ResultSuccess);
45}
46
47} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_common_functions.h b/src/core/hle/service/am/applet_common_functions.h
new file mode 100644
index 000000000..be87b3820
--- /dev/null
+++ b/src/core/hle/service/am/applet_common_functions.h
@@ -0,0 +1,19 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
11public:
12 explicit IAppletCommonFunctions(Core::System& system_);
13 ~IAppletCommonFunctions() override;
14
15private:
16 void SetCpuBoostRequestPriority(HLERequestContext& ctx);
17};
18
19} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_message_queue.cpp b/src/core/hle/service/am/applet_message_queue.cpp
new file mode 100644
index 000000000..e4931031d
--- /dev/null
+++ b/src/core/hle/service/am/applet_message_queue.cpp
@@ -0,0 +1,68 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applet_message_queue.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9AppletMessageQueue::AppletMessageQueue(Core::System& system)
10 : service_context{system, "AppletMessageQueue"} {
11 on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived");
12 on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged");
13}
14
15AppletMessageQueue::~AppletMessageQueue() {
16 service_context.CloseEvent(on_new_message);
17 service_context.CloseEvent(on_operation_mode_changed);
18}
19
20Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() {
21 return on_new_message->GetReadableEvent();
22}
23
24Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() {
25 return on_operation_mode_changed->GetReadableEvent();
26}
27
28void AppletMessageQueue::PushMessage(AppletMessage msg) {
29 messages.push(msg);
30 on_new_message->Signal();
31}
32
33AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
34 if (messages.empty()) {
35 on_new_message->Clear();
36 return AppletMessage::None;
37 }
38 auto msg = messages.front();
39 messages.pop();
40 if (messages.empty()) {
41 on_new_message->Clear();
42 }
43 return msg;
44}
45
46std::size_t AppletMessageQueue::GetMessageCount() const {
47 return messages.size();
48}
49
50void AppletMessageQueue::RequestExit() {
51 PushMessage(AppletMessage::Exit);
52}
53
54void AppletMessageQueue::RequestResume() {
55 PushMessage(AppletMessage::Resume);
56}
57
58void AppletMessageQueue::FocusStateChanged() {
59 PushMessage(AppletMessage::FocusStateChanged);
60}
61
62void AppletMessageQueue::OperationModeChanged() {
63 PushMessage(AppletMessage::OperationModeChanged);
64 PushMessage(AppletMessage::PerformanceModeChanged);
65 on_operation_mode_changed->Signal();
66}
67
68} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_message_queue.h b/src/core/hle/service/am/applet_message_queue.h
new file mode 100644
index 000000000..60145aae9
--- /dev/null
+++ b/src/core/hle/service/am/applet_message_queue.h
@@ -0,0 +1,75 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <queue>
7
8#include "core/hle/service/kernel_helpers.h"
9#include "core/hle/service/service.h"
10
11namespace Kernel {
12class KReadableEvent;
13} // namespace Kernel
14
15namespace Service::AM {
16
17class AppletMessageQueue {
18public:
19 // This is nn::am::AppletMessage
20 enum class AppletMessage : u32 {
21 None = 0,
22 ChangeIntoForeground = 1,
23 ChangeIntoBackground = 2,
24 Exit = 4,
25 ApplicationExited = 6,
26 FocusStateChanged = 15,
27 Resume = 16,
28 DetectShortPressingHomeButton = 20,
29 DetectLongPressingHomeButton = 21,
30 DetectShortPressingPowerButton = 22,
31 DetectMiddlePressingPowerButton = 23,
32 DetectLongPressingPowerButton = 24,
33 RequestToPrepareSleep = 25,
34 FinishedSleepSequence = 26,
35 SleepRequiredByHighTemperature = 27,
36 SleepRequiredByLowBattery = 28,
37 AutoPowerDown = 29,
38 OperationModeChanged = 30,
39 PerformanceModeChanged = 31,
40 DetectReceivingCecSystemStandby = 32,
41 SdCardRemoved = 33,
42 LaunchApplicationRequested = 50,
43 RequestToDisplay = 51,
44 ShowApplicationLogo = 55,
45 HideApplicationLogo = 56,
46 ForceHideApplicationLogo = 57,
47 FloatingApplicationDetected = 60,
48 DetectShortPressingCaptureButton = 90,
49 AlbumScreenShotTaken = 92,
50 AlbumRecordingSaved = 93,
51 };
52
53 explicit AppletMessageQueue(Core::System& system);
54 ~AppletMessageQueue();
55
56 Kernel::KReadableEvent& GetMessageReceiveEvent();
57 Kernel::KReadableEvent& GetOperationModeChangedEvent();
58 void PushMessage(AppletMessage msg);
59 AppletMessage PopMessage();
60 std::size_t GetMessageCount() const;
61 void RequestExit();
62 void RequestResume();
63 void FocusStateChanged();
64 void OperationModeChanged();
65
66private:
67 KernelHelpers::ServiceContext service_context;
68
69 Kernel::KEvent* on_new_message;
70 Kernel::KEvent* on_operation_mode_changed;
71
72 std::queue<AppletMessage> messages;
73};
74
75} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index d6c565d85..f373d1136 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -1,107 +1,13 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 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/logging/log.h"
5#include "core/hle/service/am/am.h" 4#include "core/hle/service/am/am.h"
6#include "core/hle/service/am/applet_oe.h" 5#include "core/hle/service/am/applet_oe.h"
6#include "core/hle/service/am/application_proxy.h"
7#include "core/hle/service/ipc_helpers.h" 7#include "core/hle/service/ipc_helpers.h"
8#include "core/hle/service/nvnflinger/nvnflinger.h"
9 8
10namespace Service::AM { 9namespace Service::AM {
11 10
12class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
13public:
14 explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
15 std::shared_ptr<AppletMessageQueue> msg_queue_,
16 Core::System& system_)
17 : ServiceFramework{system_, "IApplicationProxy"},
18 nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} {
19 // clang-format off
20 static const FunctionInfo functions[] = {
21 {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
22 {1, &IApplicationProxy::GetSelfController, "GetSelfController"},
23 {2, &IApplicationProxy::GetWindowController, "GetWindowController"},
24 {3, &IApplicationProxy::GetAudioController, "GetAudioController"},
25 {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"},
26 {10, nullptr, "GetProcessWindingController"},
27 {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
28 {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"},
29 {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"},
30 };
31 // clang-format on
32
33 RegisterHandlers(functions);
34 }
35
36private:
37 void GetAudioController(HLERequestContext& ctx) {
38 LOG_DEBUG(Service_AM, "called");
39
40 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
41 rb.Push(ResultSuccess);
42 rb.PushIpcInterface<IAudioController>(system);
43 }
44
45 void GetDisplayController(HLERequestContext& ctx) {
46 LOG_DEBUG(Service_AM, "called");
47
48 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
49 rb.Push(ResultSuccess);
50 rb.PushIpcInterface<IDisplayController>(system);
51 }
52
53 void GetDebugFunctions(HLERequestContext& ctx) {
54 LOG_DEBUG(Service_AM, "called");
55
56 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
57 rb.Push(ResultSuccess);
58 rb.PushIpcInterface<IDebugFunctions>(system);
59 }
60
61 void GetWindowController(HLERequestContext& ctx) {
62 LOG_DEBUG(Service_AM, "called");
63
64 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
65 rb.Push(ResultSuccess);
66 rb.PushIpcInterface<IWindowController>(system);
67 }
68
69 void GetSelfController(HLERequestContext& ctx) {
70 LOG_DEBUG(Service_AM, "called");
71
72 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
73 rb.Push(ResultSuccess);
74 rb.PushIpcInterface<ISelfController>(system, nvnflinger);
75 }
76
77 void GetCommonStateGetter(HLERequestContext& ctx) {
78 LOG_DEBUG(Service_AM, "called");
79
80 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
81 rb.Push(ResultSuccess);
82 rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
83 }
84
85 void GetLibraryAppletCreator(HLERequestContext& ctx) {
86 LOG_DEBUG(Service_AM, "called");
87
88 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
89 rb.Push(ResultSuccess);
90 rb.PushIpcInterface<ILibraryAppletCreator>(system);
91 }
92
93 void GetApplicationFunctions(HLERequestContext& ctx) {
94 LOG_DEBUG(Service_AM, "called");
95
96 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
97 rb.Push(ResultSuccess);
98 rb.PushIpcInterface<IApplicationFunctions>(system);
99 }
100
101 Nvnflinger::Nvnflinger& nvnflinger;
102 std::shared_ptr<AppletMessageQueue> msg_queue;
103};
104
105void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { 11void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
106 LOG_DEBUG(Service_AM, "called"); 12 LOG_DEBUG(Service_AM, "called");
107 13
@@ -112,8 +18,8 @@ void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
112 18
113AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, 19AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_,
114 std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) 20 std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_)
115 : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_}, msg_queue{ 21 : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_},
116 std::move(msg_queue_)} { 22 msg_queue{std::move(msg_queue_)} {
117 static const FunctionInfo functions[] = { 23 static const FunctionInfo functions[] = {
118 {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, 24 {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
119 }; 25 };
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp
index c2ff444a6..1b756fbd7 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.cpp
+++ b/src/core/hle/service/am/applets/applet_cabinet.cpp
@@ -9,6 +9,7 @@
9#include "core/hle/kernel/k_readable_event.h" 9#include "core/hle/kernel/k_readable_event.h"
10#include "core/hle/service/am/am.h" 10#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/applets/applet_cabinet.h" 11#include "core/hle/service/am/applets/applet_cabinet.h"
12#include "core/hle/service/am/storage.h"
12#include "core/hle/service/mii/mii_manager.h" 13#include "core/hle/service/mii/mii_manager.h"
13#include "core/hle/service/nfc/common/device.h" 14#include "core/hle/service/nfc/common/device.h"
14#include "hid_core/hid_core.h" 15#include "hid_core/hid_core.h"
@@ -17,9 +18,8 @@ namespace Service::AM::Applets {
17 18
18Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_, 19Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_,
19 const Core::Frontend::CabinetApplet& frontend_) 20 const Core::Frontend::CabinetApplet& frontend_)
20 : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_}, service_context{ 21 : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_},
21 system_, 22 service_context{system_, "CabinetApplet"} {
22 "CabinetApplet"} {
23 23
24 availability_change_event = 24 availability_change_event =
25 service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent"); 25 service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent");
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 0e4d9cc39..bc8de6b60 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -12,6 +12,7 @@
12#include "core/hle/result.h" 12#include "core/hle/result.h"
13#include "core/hle/service/am/am.h" 13#include "core/hle/service/am/am.h"
14#include "core/hle/service/am/applets/applet_controller.h" 14#include "core/hle/service/am/applets/applet_controller.h"
15#include "core/hle/service/am/storage.h"
15#include "hid_core/frontend/emulated_controller.h" 16#include "hid_core/frontend/emulated_controller.h"
16#include "hid_core/hid_core.h" 17#include "hid_core/hid_core.h"
17#include "hid_core/hid_types.h" 18#include "hid_core/hid_types.h"
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp
index 084bc138c..96126832c 100644
--- a/src/core/hle/service/am/applets/applet_error.cpp
+++ b/src/core/hle/service/am/applets/applet_error.cpp
@@ -10,6 +10,7 @@
10#include "core/frontend/applets/error.h" 10#include "core/frontend/applets/error.h"
11#include "core/hle/service/am/am.h" 11#include "core/hle/service/am/am.h"
12#include "core/hle/service/am/applets/applet_error.h" 12#include "core/hle/service/am/applets/applet_error.h"
13#include "core/hle/service/am/storage.h"
13#include "core/reporter.h" 14#include "core/reporter.h"
14 15
15namespace Service::AM::Applets { 16namespace Service::AM::Applets {
diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp
index c0032f652..c010c78e2 100644
--- a/src/core/hle/service/am/applets/applet_general_backend.cpp
+++ b/src/core/hle/service/am/applets/applet_general_backend.cpp
@@ -9,6 +9,7 @@
9#include "core/hle/result.h" 9#include "core/hle/result.h"
10#include "core/hle/service/am/am.h" 10#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/applets/applet_general_backend.h" 11#include "core/hle/service/am/applets/applet_general_backend.h"
12#include "core/hle/service/am/storage.h"
12#include "core/reporter.h" 13#include "core/reporter.h"
13 14
14namespace Service::AM::Applets { 15namespace Service::AM::Applets {
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp
index e83e931c5..1576b45c4 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit.cpp
+++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp
@@ -7,6 +7,7 @@
7#include "core/frontend/applets/mii_edit.h" 7#include "core/frontend/applets/mii_edit.h"
8#include "core/hle/service/am/am.h" 8#include "core/hle/service/am/am.h"
9#include "core/hle/service/am/applets/applet_mii_edit.h" 9#include "core/hle/service/am/applets/applet_mii_edit.h"
10#include "core/hle/service/am/storage.h"
10#include "core/hle/service/mii/mii.h" 11#include "core/hle/service/mii/mii.h"
11#include "core/hle/service/mii/mii_manager.h" 12#include "core/hle/service/mii/mii_manager.h"
12#include "core/hle/service/sm/sm.h" 13#include "core/hle/service/sm/sm.h"
diff --git a/src/core/hle/service/am/applets/applet_profile_select.cpp b/src/core/hle/service/am/applets/applet_profile_select.cpp
index 89cb323e9..f32db6842 100644
--- a/src/core/hle/service/am/applets/applet_profile_select.cpp
+++ b/src/core/hle/service/am/applets/applet_profile_select.cpp
@@ -10,6 +10,7 @@
10#include "core/hle/service/acc/errors.h" 10#include "core/hle/service/acc/errors.h"
11#include "core/hle/service/am/am.h" 11#include "core/hle/service/am/am.h"
12#include "core/hle/service/am/applets/applet_profile_select.h" 12#include "core/hle/service/am/applets/applet_profile_select.h"
13#include "core/hle/service/am/storage.h"
13 14
14namespace Service::AM::Applets { 15namespace Service::AM::Applets {
15 16
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
index 4145bb84f..a6a07cef3 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
@@ -6,6 +6,7 @@
6#include "core/frontend/applets/software_keyboard.h" 6#include "core/frontend/applets/software_keyboard.h"
7#include "core/hle/service/am/am.h" 7#include "core/hle/service/am/am.h"
8#include "core/hle/service/am/applets/applet_software_keyboard.h" 8#include "core/hle/service/am/applets/applet_software_keyboard.h"
9#include "core/hle/service/am/storage.h"
9 10
10namespace Service::AM::Applets { 11namespace Service::AM::Applets {
11 12
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp
index 19057ad7b..871737b3e 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.cpp
+++ b/src/core/hle/service/am/applets/applet_web_browser.cpp
@@ -20,6 +20,7 @@
20#include "core/hle/result.h" 20#include "core/hle/result.h"
21#include "core/hle/service/am/am.h" 21#include "core/hle/service/am/am.h"
22#include "core/hle/service/am/applets/applet_web_browser.h" 22#include "core/hle/service/am/applets/applet_web_browser.h"
23#include "core/hle/service/am/storage.h"
23#include "core/hle/service/filesystem/filesystem.h" 24#include "core/hle/service/filesystem/filesystem.h"
24#include "core/hle/service/ns/iplatform_service_manager.h" 25#include "core/hle/service/ns/iplatform_service_manager.h"
25#include "core/loader/loader.h" 26#include "core/loader/loader.h"
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 89d5434af..6a47f4b7a 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/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_message_queue.h"
19#include "core/hle/service/am/applet_oe.h" 20#include "core/hle/service/am/applet_oe.h"
20#include "core/hle/service/am/applets/applet_cabinet.h" 21#include "core/hle/service/am/applets/applet_cabinet.h"
21#include "core/hle/service/am/applets/applet_controller.h" 22#include "core/hle/service/am/applets/applet_controller.h"
@@ -26,13 +27,14 @@
26#include "core/hle/service/am/applets/applet_software_keyboard.h" 27#include "core/hle/service/am/applets/applet_software_keyboard.h"
27#include "core/hle/service/am/applets/applet_web_browser.h" 28#include "core/hle/service/am/applets/applet_web_browser.h"
28#include "core/hle/service/am/applets/applets.h" 29#include "core/hle/service/am/applets/applets.h"
30#include "core/hle/service/am/storage.h"
29#include "core/hle/service/sm/sm.h" 31#include "core/hle/service/sm/sm.h"
30 32
31namespace Service::AM::Applets { 33namespace Service::AM::Applets {
32 34
33AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_) 35AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_)
34 : system{system_}, applet_mode{applet_mode_}, service_context{system, 36 : system{system_}, applet_mode{applet_mode_},
35 "ILibraryAppletAccessor"} { 37 service_context{system, "ILibraryAppletAccessor"} {
36 state_changed_event = service_context.CreateEvent("ILibraryAppletAccessor:StateChangedEvent"); 38 state_changed_event = service_context.CreateEvent("ILibraryAppletAccessor:StateChangedEvent");
37 pop_out_data_event = service_context.CreateEvent("ILibraryAppletAccessor:PopDataOutEvent"); 39 pop_out_data_event = service_context.CreateEvent("ILibraryAppletAccessor:PopDataOutEvent");
38 pop_interactive_out_data_event = 40 pop_interactive_out_data_event =
diff --git a/src/core/hle/service/am/application_creator.cpp b/src/core/hle/service/am/application_creator.cpp
new file mode 100644
index 000000000..79ea045a3
--- /dev/null
+++ b/src/core/hle/service/am/application_creator.cpp
@@ -0,0 +1,25 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/application_creator.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9IApplicationCreator::IApplicationCreator(Core::System& system_)
10 : ServiceFramework{system_, "IApplicationCreator"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, nullptr, "CreateApplication"},
14 {1, nullptr, "PopLaunchRequestedApplication"},
15 {10, nullptr, "CreateSystemApplication"},
16 {100, nullptr, "PopFloatingApplicationForDevelopment"},
17 };
18 // clang-format on
19
20 RegisterHandlers(functions);
21}
22
23IApplicationCreator::~IApplicationCreator() = default;
24
25} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_creator.h b/src/core/hle/service/am/application_creator.h
new file mode 100644
index 000000000..375a3c476
--- /dev/null
+++ b/src/core/hle/service/am/application_creator.h
@@ -0,0 +1,16 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
11public:
12 explicit IApplicationCreator(Core::System& system_);
13 ~IApplicationCreator() override;
14};
15
16} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_functions.cpp b/src/core/hle/service/am/application_functions.cpp
new file mode 100644
index 000000000..fef45c732
--- /dev/null
+++ b/src/core/hle/service/am/application_functions.cpp
@@ -0,0 +1,610 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/settings.h"
5#include "common/uuid.h"
6#include "core/file_sys/control_metadata.h"
7#include "core/file_sys/patch_manager.h"
8#include "core/file_sys/registered_cache.h"
9#include "core/file_sys/savedata_factory.h"
10#include "core/hle/service/acc/profile_manager.h"
11#include "core/hle/service/am/am_results.h"
12#include "core/hle/service/am/application_functions.h"
13#include "core/hle/service/am/storage.h"
14#include "core/hle/service/filesystem/filesystem.h"
15#include "core/hle/service/filesystem/save_data_controller.h"
16#include "core/hle/service/ipc_helpers.h"
17#include "core/hle/service/ns/ns.h"
18#include "core/hle/service/sm/sm.h"
19
20namespace Service::AM {
21
22enum class LaunchParameterKind : u32 {
23 UserChannel = 1,
24 AccountPreselectedUser = 2,
25};
26
27constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
28
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
41 static const FunctionInfo functions[] = {
42 {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
43 {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
44 {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
45 {12, nullptr, "CreateApplicationAndRequestToStart"},
46 {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
47 {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
48 {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
49 {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
50 {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
51 {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
52 {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
53 {24, nullptr, "GetLaunchStorageInfoForDebug"},
54 {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
55 {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
56 {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"},
57 {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"},
58 {29, nullptr, "GetCacheStorageMax"},
59 {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
60 {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
61 {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
62 {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
63 {34, nullptr, "SelectApplicationLicense"},
64 {35, nullptr, "GetDeviceSaveDataSizeMax"},
65 {36, nullptr, "GetLimitedApplicationLicense"},
66 {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
67 {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
68 {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
69 {60, nullptr, "SetMediaPlaybackStateForApplication"},
70 {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"},
71 {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
72 {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
73 {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
74 {70, nullptr, "RequestToShutdown"},
75 {71, nullptr, "RequestToReboot"},
76 {72, nullptr, "RequestToSleep"},
77 {80, nullptr, "ExitAndRequestToShowThanksMessage"},
78 {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
79 {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
80 {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
81 {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
82 {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"},
83 {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"},
84 {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"},
85 {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"},
86 {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"},
87 {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
88 {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
89 {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
90 {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
91 {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
92 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
93 {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
94 {151, nullptr, "TryPopFromNotificationStorageChannel"},
95 {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
96 {170, nullptr, "SetHdcpAuthenticationActivated"},
97 {180, nullptr, "GetLaunchRequiredVersion"},
98 {181, nullptr, "UpgradeLaunchRequiredVersion"},
99 {190, nullptr, "SendServerMaintenanceOverlayNotification"},
100 {200, nullptr, "GetLastApplicationExitReason"},
101 {500, nullptr, "StartContinuousRecordingFlushForDebug"},
102 {1000, nullptr, "CreateMovieMaker"},
103 {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"},
104 };
105 // clang-format on
106
107 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}
118
119IApplicationFunctions::~IApplicationFunctions() {
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
126void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
127 LOG_WARNING(Service_AM, "(STUBBED) called");
128
129 IPC::ResponseBuilder rb{ctx, 2};
130 rb.Push(ResultSuccess);
131}
132
133void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) {
134 LOG_WARNING(Service_AM, "(STUBBED) called");
135
136 IPC::ResponseBuilder rb{ctx, 2};
137 rb.Push(ResultSuccess);
138}
139
140void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) {
141 LOG_WARNING(Service_AM, "(STUBBED) called");
142
143 IPC::ResponseBuilder rb{ctx, 2};
144 rb.Push(ResultSuccess);
145}
146
147void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) {
148 IPC::RequestParser rp{ctx};
149 const auto is_visible = rp.Pop<bool>();
150
151 LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
152
153 IPC::ResponseBuilder rb{ctx, 2};
154 rb.Push(ResultSuccess);
155}
156
157void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
158 LOG_WARNING(Service_AM, "(STUBBED) called");
159
160 IPC::ResponseBuilder rb{ctx, 2};
161 rb.Push(ResultSuccess);
162}
163
164void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
165 LOG_WARNING(Service_AM, "(STUBBED) called");
166
167 IPC::ResponseBuilder rb{ctx, 2};
168 rb.Push(ResultSuccess);
169}
170
171void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
172 LOG_WARNING(Service_AM, "(STUBBED) called");
173
174 IPC::ResponseBuilder rb{ctx, 2};
175 rb.Push(ResultSuccess);
176}
177
178void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
179 LOG_WARNING(Service_AM, "(STUBBED) called");
180
181 IPC::ResponseBuilder rb{ctx, 2};
182 rb.Push(ResultSuccess);
183}
184
185void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
186 IPC::RequestParser rp{ctx};
187 const auto kind = rp.PopEnum<LaunchParameterKind>();
188
189 LOG_INFO(Service_AM, "called, kind={:08X}", kind);
190
191 if (kind == LaunchParameterKind::UserChannel) {
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
219 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
220 rb.Push(ResultSuccess);
221
222 std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
223 std::memcpy(buffer.data(), &params, buffer.size());
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};
230 rb.Push(AM::ResultNoDataInChannel);
231 }
232}
233
234void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
235 LOG_WARNING(Service_AM, "(STUBBED) called");
236
237 IPC::ResponseBuilder rb{ctx, 2};
238 rb.Push(ResultSuccess);
239}
240
241void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
242 IPC::RequestParser rp{ctx};
243 u128 user_id = rp.PopRaw<u128>();
244
245 LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
246
247 FileSys::SaveDataAttribute attribute{};
248 attribute.title_id = system.GetApplicationProcessProgramID();
249 attribute.user_id = user_id;
250 attribute.type = FileSys::SaveDataType::SaveData;
251
252 FileSys::VirtualDir save_data{};
253 const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
254 &save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
255
256 IPC::ResponseBuilder rb{ctx, 4};
257 rb.Push(res);
258 rb.Push<u64>(0);
259}
260
261void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) {
262 // Takes an input u32 Result, no output.
263 // For example, in some cases official apps use this with error 0x2A2 then
264 // uses svcBreak.
265
266 IPC::RequestParser rp{ctx};
267 u32 result = rp.Pop<u32>();
268 LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
269
270 IPC::ResponseBuilder rb{ctx, 2};
271 rb.Push(ResultSuccess);
272}
273
274void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) {
275 LOG_DEBUG(Service_AM, "called");
276
277 std::array<u8, 0x10> version_string{};
278
279 const auto res = [this] {
280 const auto title_id = system.GetApplicationProcessProgramID();
281
282 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
283 system.GetContentProvider()};
284 auto metadata = pm.GetControlMetadata();
285 if (metadata.first != nullptr) {
286 return metadata;
287 }
288
289 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
290 system.GetFileSystemController(),
291 system.GetContentProvider()};
292 return pm_update.GetControlMetadata();
293 }();
294
295 if (res.first != nullptr) {
296 const auto& version = res.first->GetVersionString();
297 std::copy(version.begin(), version.end(), version_string.begin());
298 } else {
299 static constexpr char default_version[]{"1.0.0"};
300 std::memcpy(version_string.data(), default_version, sizeof(default_version));
301 }
302
303 IPC::ResponseBuilder rb{ctx, 6};
304 rb.Push(ResultSuccess);
305 rb.PushRaw(version_string);
306}
307
308void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
309 // TODO(bunnei): This should be configurable
310 LOG_DEBUG(Service_AM, "called");
311
312 // Get supported languages from NACP, if possible
313 // Default to 0 (all languages supported)
314 u32 supported_languages = 0;
315
316 const auto res = [this] {
317 const auto title_id = system.GetApplicationProcessProgramID();
318
319 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
320 system.GetContentProvider()};
321 auto metadata = pm.GetControlMetadata();
322 if (metadata.first != nullptr) {
323 return metadata;
324 }
325
326 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
327 system.GetFileSystemController(),
328 system.GetContentProvider()};
329 return pm_update.GetControlMetadata();
330 }();
331
332 if (res.first != nullptr) {
333 supported_languages = res.first->GetSupportedLanguages();
334 }
335
336 // Call IApplicationManagerInterface implementation.
337 auto& service_manager = system.ServiceManager();
338 auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
339 auto app_man = ns_am2->GetApplicationManagerInterface();
340
341 // Get desired application language
342 u8 desired_language{};
343 const auto res_lang =
344 app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
345 if (res_lang != ResultSuccess) {
346 IPC::ResponseBuilder rb{ctx, 2};
347 rb.Push(res_lang);
348 return;
349 }
350
351 // Convert to settings language code.
352 u64 language_code{};
353 const auto res_code =
354 app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
355 if (res_code != ResultSuccess) {
356 IPC::ResponseBuilder rb{ctx, 2};
357 rb.Push(res_code);
358 return;
359 }
360
361 LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
362
363 IPC::ResponseBuilder rb{ctx, 4};
364 rb.Push(ResultSuccess);
365 rb.Push(language_code);
366}
367
368void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
369 LOG_WARNING(Service_AM, "(STUBBED) called");
370
371 constexpr bool gameplay_recording_supported = false;
372
373 IPC::ResponseBuilder rb{ctx, 3};
374 rb.Push(ResultSuccess);
375 rb.Push(gameplay_recording_supported);
376}
377
378void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
379 LOG_WARNING(Service_AM, "(STUBBED) called");
380
381 IPC::ResponseBuilder rb{ctx, 2};
382 rb.Push(ResultSuccess);
383}
384
385void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
386 LOG_WARNING(Service_AM, "(STUBBED) called");
387
388 IPC::ResponseBuilder rb{ctx, 2};
389 rb.Push(ResultSuccess);
390}
391
392void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
393 LOG_WARNING(Service_AM, "(STUBBED) called");
394
395 IPC::ResponseBuilder rb{ctx, 3};
396 rb.Push(ResultSuccess);
397 rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
398}
399
400void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) {
401 LOG_WARNING(Service_AM, "(STUBBED) called");
402
403 IPC::ResponseBuilder rb{ctx, 6};
404 rb.Push(ResultSuccess);
405
406 // Returns a 128-bit UUID
407 rb.Push<u64>(0);
408 rb.Push<u64>(0);
409}
410
411void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
412 struct Parameters {
413 FileSys::SaveDataType type;
414 u128 user_id;
415 u64 new_normal_size;
416 u64 new_journal_size;
417 };
418 static_assert(sizeof(Parameters) == 40);
419
420 IPC::RequestParser rp{ctx};
421 const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>();
422
423 LOG_DEBUG(Service_AM,
424 "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
425 "new_journal={:016X}",
426 static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
427
428 system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
429 type, system.GetApplicationProcessProgramID(), user_id,
430 {new_normal_size, new_journal_size});
431
432 IPC::ResponseBuilder rb{ctx, 4};
433 rb.Push(ResultSuccess);
434
435 // The following value is used upon failure to help the system recover.
436 // Since we always succeed, this should be 0.
437 rb.Push<u64>(0);
438}
439
440void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
441 struct Parameters {
442 FileSys::SaveDataType type;
443 u128 user_id;
444 };
445 static_assert(sizeof(Parameters) == 24);
446
447 IPC::RequestParser rp{ctx};
448 const auto [type, user_id] = rp.PopRaw<Parameters>();
449
450 LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1],
451 user_id[0]);
452
453 const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
454 type, system.GetApplicationProcessProgramID(), user_id);
455
456 IPC::ResponseBuilder rb{ctx, 6};
457 rb.Push(ResultSuccess);
458 rb.Push(size.normal);
459 rb.Push(size.journal);
460}
461
462void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) {
463 struct InputParameters {
464 u16 index;
465 s64 size;
466 s64 journal_size;
467 };
468 static_assert(sizeof(InputParameters) == 24);
469
470 struct OutputParameters {
471 u32 storage_target;
472 u64 required_size;
473 };
474 static_assert(sizeof(OutputParameters) == 16);
475
476 IPC::RequestParser rp{ctx};
477 const auto params = rp.PopRaw<InputParameters>();
478
479 LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}",
480 params.index, params.size, params.journal_size);
481
482 const OutputParameters resp{
483 .storage_target = 1,
484 .required_size = 0,
485 };
486
487 IPC::ResponseBuilder rb{ctx, 6};
488 rb.Push(ResultSuccess);
489 rb.PushRaw(resp);
490}
491
492void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) {
493 LOG_WARNING(Service_AM, "(STUBBED) called");
494
495 constexpr u64 size_max_normal = 0xFFFFFFF;
496 constexpr u64 size_max_journal = 0xFFFFFFF;
497
498 IPC::ResponseBuilder rb{ctx, 6};
499 rb.Push(ResultSuccess);
500 rb.Push(size_max_normal);
501 rb.Push(size_max_journal);
502}
503
504void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) {
505 LOG_WARNING(Service_AM, "(STUBBED) called");
506
507 IPC::ResponseBuilder rb{ctx, 3};
508 rb.Push(ResultSuccess);
509 rb.Push<u32>(0);
510}
511
512void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) {
513 LOG_WARNING(Service_AM, "(STUBBED) called");
514
515 IPC::ResponseBuilder rb{ctx, 3};
516 rb.Push(ResultSuccess);
517 rb.Push<u32>(0);
518}
519
520void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
521 LOG_WARNING(Service_AM, "(STUBBED) called");
522
523 IPC::RequestParser rp{ctx};
524 [[maybe_unused]] const auto unk_1 = rp.Pop<u32>();
525 [[maybe_unused]] const auto unk_2 = rp.Pop<u32>();
526 const auto program_index = rp.Pop<u64>();
527
528 IPC::ResponseBuilder rb{ctx, 2};
529 rb.Push(ResultSuccess);
530
531 system.ExecuteProgram(program_index);
532}
533
534void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
535 LOG_DEBUG(Service_AM, "called");
536
537 system.GetUserChannel().clear();
538
539 IPC::ResponseBuilder rb{ctx, 2};
540 rb.Push(ResultSuccess);
541}
542
543void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
544 LOG_DEBUG(Service_AM, "called");
545
546 IPC::RequestParser rp{ctx};
547 const auto storage = rp.PopIpcInterface<IStorage>().lock();
548 if (storage) {
549 system.GetUserChannel().push_back(storage->GetData());
550 }
551
552 IPC::ResponseBuilder rb{ctx, 2};
553 rb.Push(ResultSuccess);
554}
555
556void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) {
557 LOG_WARNING(Service_AM, "(STUBBED) called");
558
559 IPC::ResponseBuilder rb{ctx, 3};
560 rb.Push(ResultSuccess);
561 rb.Push<s32>(previous_program_index);
562}
563
564void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
565 LOG_WARNING(Service_AM, "(STUBBED) called");
566
567 IPC::ResponseBuilder rb{ctx, 2, 1};
568 rb.Push(ResultSuccess);
569 rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
570}
571
572void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
573 LOG_DEBUG(Service_AM, "called");
574
575 IPC::ResponseBuilder rb{ctx, 2, 1};
576 rb.Push(ResultSuccess);
577 rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
578}
579
580void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
581 LOG_DEBUG(Service_AM, "(STUBBED) called");
582
583 IPC::ResponseBuilder rb{ctx, 2};
584 rb.Push(AM::ResultNoDataInChannel);
585}
586
587void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) {
588 LOG_DEBUG(Service_AM, "called");
589
590 IPC::ResponseBuilder rb{ctx, 2, 1};
591 rb.Push(ResultSuccess);
592 rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent());
593}
594
595void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
596 LOG_DEBUG(Service_AM, "called");
597
598 IPC::ResponseBuilder rb{ctx, 2, 1};
599 rb.Push(ResultSuccess);
600 rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
601}
602
603void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
604 LOG_WARNING(Service_AM, "(STUBBED) called");
605
606 IPC::ResponseBuilder rb{ctx, 2};
607 rb.Push(ResultSuccess);
608}
609
610} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_functions.h b/src/core/hle/service/am/application_functions.h
new file mode 100644
index 000000000..22aab1c8f
--- /dev/null
+++ b/src/core/hle/service/am/application_functions.h
@@ -0,0 +1,63 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
12public:
13 explicit IApplicationFunctions(Core::System& system_);
14 ~IApplicationFunctions() override;
15
16private:
17 void PopLaunchParameter(HLERequestContext& ctx);
18 void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx);
19 void EnsureSaveData(HLERequestContext& ctx);
20 void SetTerminateResult(HLERequestContext& ctx);
21 void GetDisplayVersion(HLERequestContext& ctx);
22 void GetDesiredLanguage(HLERequestContext& ctx);
23 void IsGamePlayRecordingSupported(HLERequestContext& ctx);
24 void InitializeGamePlayRecording(HLERequestContext& ctx);
25 void SetGamePlayRecordingState(HLERequestContext& ctx);
26 void NotifyRunning(HLERequestContext& ctx);
27 void GetPseudoDeviceId(HLERequestContext& ctx);
28 void ExtendSaveData(HLERequestContext& ctx);
29 void GetSaveDataSize(HLERequestContext& ctx);
30 void CreateCacheStorage(HLERequestContext& ctx);
31 void GetSaveDataSizeMax(HLERequestContext& ctx);
32 void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
33 void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
34 void BeginBlockingHomeButton(HLERequestContext& ctx);
35 void EndBlockingHomeButton(HLERequestContext& ctx);
36 void EnableApplicationCrashReport(HLERequestContext& ctx);
37 void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx);
38 void SetApplicationCopyrightImage(HLERequestContext& ctx);
39 void SetApplicationCopyrightVisibility(HLERequestContext& ctx);
40 void QueryApplicationPlayStatistics(HLERequestContext& ctx);
41 void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx);
42 void ExecuteProgram(HLERequestContext& ctx);
43 void ClearUserChannel(HLERequestContext& ctx);
44 void UnpopToUserChannel(HLERequestContext& ctx);
45 void GetPreviousProgramIndex(HLERequestContext& ctx);
46 void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx);
47 void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx);
48 void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx);
49 void GetNotificationStorageChannelEvent(HLERequestContext& ctx);
50 void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
51 void PrepareForJit(HLERequestContext& ctx);
52
53 KernelHelpers::ServiceContext service_context;
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};
62
63} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_proxy.cpp b/src/core/hle/service/am/application_proxy.cpp
new file mode 100644
index 000000000..e9cd0aa71
--- /dev/null
+++ b/src/core/hle/service/am/application_proxy.cpp
@@ -0,0 +1,114 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applet_common_functions.h"
5#include "core/hle/service/am/application_functions.h"
6#include "core/hle/service/am/application_proxy.h"
7#include "core/hle/service/am/audio_controller.h"
8#include "core/hle/service/am/common_state_getter.h"
9#include "core/hle/service/am/debug_functions.h"
10#include "core/hle/service/am/display_controller.h"
11#include "core/hle/service/am/library_applet_creator.h"
12#include "core/hle/service/am/library_applet_self_accessor.h"
13#include "core/hle/service/am/process_winding_controller.h"
14#include "core/hle/service/am/self_controller.h"
15#include "core/hle/service/am/window_controller.h"
16#include "core/hle/service/ipc_helpers.h"
17
18namespace Service::AM {
19
20IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
21 std::shared_ptr<AppletMessageQueue> msg_queue_,
22 Core::System& system_)
23 : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_},
24 msg_queue{std::move(msg_queue_)} {
25 // clang-format off
26 static const FunctionInfo functions[] = {
27 {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
28 {1, &IApplicationProxy::GetSelfController, "GetSelfController"},
29 {2, &IApplicationProxy::GetWindowController, "GetWindowController"},
30 {3, &IApplicationProxy::GetAudioController, "GetAudioController"},
31 {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"},
32 {10, &IApplicationProxy::GetProcessWindingController, "GetProcessWindingController"},
33 {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
34 {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"},
35 {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"},
36 };
37 // clang-format on
38
39 RegisterHandlers(functions);
40}
41
42void IApplicationProxy::GetAudioController(HLERequestContext& ctx) {
43 LOG_DEBUG(Service_AM, "called");
44
45 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
46 rb.Push(ResultSuccess);
47 rb.PushIpcInterface<IAudioController>(system);
48}
49
50void IApplicationProxy::GetDisplayController(HLERequestContext& ctx) {
51 LOG_DEBUG(Service_AM, "called");
52
53 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
54 rb.Push(ResultSuccess);
55 rb.PushIpcInterface<IDisplayController>(system);
56}
57
58void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) {
59 LOG_DEBUG(Service_AM, "called");
60
61 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
62 rb.Push(ResultSuccess);
63 rb.PushIpcInterface<IProcessWindingController>(system);
64}
65
66void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) {
67 LOG_DEBUG(Service_AM, "called");
68
69 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
70 rb.Push(ResultSuccess);
71 rb.PushIpcInterface<IDebugFunctions>(system);
72}
73
74void IApplicationProxy::GetWindowController(HLERequestContext& ctx) {
75 LOG_DEBUG(Service_AM, "called");
76
77 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
78 rb.Push(ResultSuccess);
79 rb.PushIpcInterface<IWindowController>(system);
80}
81
82void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
83 LOG_DEBUG(Service_AM, "called");
84
85 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
86 rb.Push(ResultSuccess);
87 rb.PushIpcInterface<ISelfController>(system, nvnflinger);
88}
89
90void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) {
91 LOG_DEBUG(Service_AM, "called");
92
93 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
94 rb.Push(ResultSuccess);
95 rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
96}
97
98void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
99 LOG_DEBUG(Service_AM, "called");
100
101 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
102 rb.Push(ResultSuccess);
103 rb.PushIpcInterface<ILibraryAppletCreator>(system);
104}
105
106void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
107 LOG_DEBUG(Service_AM, "called");
108
109 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
110 rb.Push(ResultSuccess);
111 rb.PushIpcInterface<IApplicationFunctions>(system);
112}
113
114} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_proxy.h b/src/core/hle/service/am/application_proxy.h
new file mode 100644
index 000000000..4f620242b
--- /dev/null
+++ b/src/core/hle/service/am/application_proxy.h
@@ -0,0 +1,32 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/applet_message_queue.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
12public:
13 explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
14 std::shared_ptr<AppletMessageQueue> msg_queue_,
15 Core::System& system_);
16
17private:
18 void GetAudioController(HLERequestContext& ctx);
19 void GetDisplayController(HLERequestContext& ctx);
20 void GetProcessWindingController(HLERequestContext& ctx);
21 void GetDebugFunctions(HLERequestContext& ctx);
22 void GetWindowController(HLERequestContext& ctx);
23 void GetSelfController(HLERequestContext& ctx);
24 void GetCommonStateGetter(HLERequestContext& ctx);
25 void GetLibraryAppletCreator(HLERequestContext& ctx);
26 void GetApplicationFunctions(HLERequestContext& ctx);
27
28 Nvnflinger::Nvnflinger& nvnflinger;
29 std::shared_ptr<AppletMessageQueue> msg_queue;
30};
31
32} // namespace Service::AM
diff --git a/src/core/hle/service/am/audio_controller.cpp b/src/core/hle/service/am/audio_controller.cpp
new file mode 100644
index 000000000..ae75db174
--- /dev/null
+++ b/src/core/hle/service/am/audio_controller.cpp
@@ -0,0 +1,91 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/audio_controller.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9IAudioController::IAudioController(Core::System& system_)
10 : ServiceFramework{system_, "IAudioController"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
14 {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"},
15 {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"},
16 {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"},
17 {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"},
18 };
19 // clang-format on
20
21 RegisterHandlers(functions);
22}
23
24IAudioController::~IAudioController() = default;
25
26void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) {
27 IPC::RequestParser rp{ctx};
28 const float main_applet_volume_tmp = rp.Pop<float>();
29 const float library_applet_volume_tmp = rp.Pop<float>();
30
31 LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
32 main_applet_volume_tmp, library_applet_volume_tmp);
33
34 // Ensure the volume values remain within the 0-100% range
35 main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
36 library_applet_volume =
37 std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
38
39 IPC::ResponseBuilder rb{ctx, 2};
40 rb.Push(ResultSuccess);
41}
42
43void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) {
44 LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume);
45 IPC::ResponseBuilder rb{ctx, 3};
46 rb.Push(ResultSuccess);
47 rb.Push(main_applet_volume);
48}
49
50void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) {
51 LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume);
52 IPC::ResponseBuilder rb{ctx, 3};
53 rb.Push(ResultSuccess);
54 rb.Push(library_applet_volume);
55}
56
57void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) {
58 struct Parameters {
59 float volume;
60 s64 fade_time_ns;
61 };
62 static_assert(sizeof(Parameters) == 16);
63
64 IPC::RequestParser rp{ctx};
65 const auto parameters = rp.PopRaw<Parameters>();
66
67 LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume,
68 parameters.fade_time_ns);
69
70 main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume);
71 fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns};
72
73 IPC::ResponseBuilder rb{ctx, 2};
74 rb.Push(ResultSuccess);
75}
76
77void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) {
78 IPC::RequestParser rp{ctx};
79 const float transparent_volume_rate_tmp = rp.Pop<float>();
80
81 LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp);
82
83 // Clamp volume range to 0-100%.
84 transparent_volume_rate =
85 std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume);
86
87 IPC::ResponseBuilder rb{ctx, 2};
88 rb.Push(ResultSuccess);
89}
90
91} // namespace Service::AM
diff --git a/src/core/hle/service/am/audio_controller.h b/src/core/hle/service/am/audio_controller.h
new file mode 100644
index 000000000..a47e3bad8
--- /dev/null
+++ b/src/core/hle/service/am/audio_controller.h
@@ -0,0 +1,36 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IAudioController final : public ServiceFramework<IAudioController> {
11public:
12 explicit IAudioController(Core::System& system_);
13 ~IAudioController() override;
14
15private:
16 void SetExpectedMasterVolume(HLERequestContext& ctx);
17 void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx);
18 void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx);
19 void ChangeMainAppletMasterVolume(HLERequestContext& ctx);
20 void SetTransparentAudioRate(HLERequestContext& ctx);
21
22 static constexpr float min_allowed_volume = 0.0f;
23 static constexpr float max_allowed_volume = 1.0f;
24
25 float main_applet_volume{0.25f};
26 float library_applet_volume{max_allowed_volume};
27 float transparent_volume_rate{min_allowed_volume};
28
29 // Volume transition fade time in nanoseconds.
30 // e.g. If the main applet volume was 0% and was changed to 50%
31 // with a fade of 50ns, then over the course of 50ns,
32 // the volume will gradually fade up to 50%
33 std::chrono::nanoseconds fade_time_ns{0};
34};
35
36} // 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
new file mode 100644
index 000000000..0b54b769d
--- /dev/null
+++ b/src/core/hle/service/am/common_state_getter.cpp
@@ -0,0 +1,288 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/settings.h"
5#include "core/hle/service/am/am_results.h"
6#include "core/hle/service/am/common_state_getter.h"
7#include "core/hle/service/am/lock_accessor.h"
8#include "core/hle/service/apm/apm_controller.h"
9#include "core/hle/service/apm/apm_interface.h"
10#include "core/hle/service/ipc_helpers.h"
11#include "core/hle/service/pm/pm.h"
12#include "core/hle/service/sm/sm.h"
13#include "core/hle/service/vi/vi.h"
14
15namespace Service::AM {
16
17ICommonStateGetter::ICommonStateGetter(Core::System& system_,
18 std::shared_ptr<AppletMessageQueue> msg_queue_)
19 : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)},
20 service_context{system_, "ICommonStateGetter"} {
21 // clang-format off
22 static const FunctionInfo functions[] = {
23 {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
24 {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
25 {2, nullptr, "GetThisAppletKind"},
26 {3, nullptr, "AllowToEnterSleep"},
27 {4, nullptr, "DisallowToEnterSleep"},
28 {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
29 {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
30 {7, nullptr, "GetCradleStatus"},
31 {8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
32 {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
33 {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"},
34 {11, nullptr, "ReleaseSleepLock"},
35 {12, nullptr, "ReleaseSleepLockTransiently"},
36 {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"},
37 {14, nullptr, "GetWakeupCount"},
38 {20, nullptr, "PushToGeneralChannel"},
39 {30, nullptr, "GetHomeButtonReaderLockAccessor"},
40 {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"},
41 {32, nullptr, "GetWriterLockAccessorEx"},
42 {40, nullptr, "GetCradleFwVersion"},
43 {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
44 {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
45 {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
46 {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
47 {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
48 {55, nullptr, "IsInControllerFirmwareUpdateSection"},
49 {59, nullptr, "SetVrPositionForDebug"},
50 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
51 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
52 {62, nullptr, "GetHdcpAuthenticationState"},
53 {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
54 {64, nullptr, "SetTvPowerStateMatchingMode"},
55 {65, nullptr, "GetApplicationIdByContentActionName"},
56 {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
57 {67, nullptr, "CancelCpuBoostMode"},
58 {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"},
59 {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"},
60 {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
61 {91, nullptr, "GetCurrentPerformanceConfiguration"},
62 {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
63 {110, nullptr, "OpenMyGpuErrorHandler"},
64 {120, nullptr, "GetAppletLaunchedHistory"},
65 {200, nullptr, "GetOperationModeSystemInfo"},
66 {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
67 {400, nullptr, "ActivateMigrationService"},
68 {401, nullptr, "DeactivateMigrationService"},
69 {500, nullptr, "DisableSleepTillShutdown"},
70 {501, nullptr, "SuppressDisablingSleepTemporarily"},
71 {502, nullptr, "IsSleepEnabled"},
72 {503, nullptr, "IsDisablingSleepSuppressed"},
73 {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
74 };
75 // clang-format on
76
77 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}
85
86ICommonStateGetter::~ICommonStateGetter() {
87 service_context.CloseEvent(sleep_lock_event);
88};
89
90void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
91 LOG_DEBUG(Service_AM, "called");
92
93 IPC::ResponseBuilder rb{ctx, 3};
94 rb.Push(ResultSuccess);
95 rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
96}
97
98void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) {
99 LOG_DEBUG(Service_AM, "called");
100
101 IPC::ResponseBuilder rb{ctx, 2, 1};
102 rb.Push(ResultSuccess);
103 rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent());
104}
105
106void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
107 LOG_DEBUG(Service_AM, "called");
108
109 const auto message = msg_queue->PopMessage();
110 IPC::ResponseBuilder rb{ctx, 3};
111
112 if (message == AppletMessageQueue::AppletMessage::None) {
113 LOG_ERROR(Service_AM, "Message queue is empty");
114 rb.Push(AM::ResultNoMessages);
115 rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
116 return;
117 }
118
119 rb.Push(ResultSuccess);
120 rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
121}
122
123void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
124 LOG_DEBUG(Service_AM, "(STUBBED) called");
125
126 IPC::ResponseBuilder rb{ctx, 3};
127 rb.Push(ResultSuccess);
128 rb.Push(static_cast<u8>(FocusState::InFocus));
129}
130
131void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
132 const bool use_docked_mode{Settings::IsDockedMode()};
133 LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
134
135 IPC::ResponseBuilder rb{ctx, 3};
136 rb.Push(ResultSuccess);
137 rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
138}
139
140void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) {
141 LOG_DEBUG(Service_AM, "called");
142
143 IPC::ResponseBuilder rb{ctx, 3};
144 rb.Push(ResultSuccess);
145 rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode());
146}
147
148void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
149 LOG_WARNING(Service_AM, "(STUBBED) called");
150
151 // Sleep lock is acquired immediately.
152 sleep_lock_event->Signal();
153
154 IPC::ResponseBuilder rb{ctx, 2};
155 rb.Push(ResultSuccess);
156}
157
158void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) {
159 IPC::RequestParser rp{ctx};
160 const auto unknown = rp.Pop<u32>();
161
162 LOG_INFO(Service_AM, "called, unknown={}", unknown);
163
164 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
165
166 rb.Push(ResultSuccess);
167 rb.PushIpcInterface<ILockAccessor>(system);
168}
169
170void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
171 LOG_WARNING(Service_AM, "called");
172
173 IPC::ResponseBuilder rb{ctx, 2, 1};
174 rb.Push(ResultSuccess);
175 rb.PushCopyObjects(sleep_lock_event->GetReadableEvent());
176}
177
178void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
179 LOG_DEBUG(Service_AM, "called");
180
181 IPC::ResponseBuilder rb{ctx, 3};
182 rb.Push(ResultSuccess);
183 rb.Push(vr_mode_state);
184}
185
186void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
187 IPC::RequestParser rp{ctx};
188 vr_mode_state = rp.Pop<bool>();
189
190 LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off");
191
192 IPC::ResponseBuilder rb{ctx, 2};
193 rb.Push(ResultSuccess);
194}
195
196void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) {
197 IPC::RequestParser rp{ctx};
198 const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
199
200 LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
201 is_lcd_backlight_off_enabled);
202
203 IPC::ResponseBuilder rb{ctx, 2};
204 rb.Push(ResultSuccess);
205}
206
207void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
208 LOG_WARNING(Service_AM, "(STUBBED) called");
209
210 IPC::ResponseBuilder rb{ctx, 2};
211 rb.Push(ResultSuccess);
212}
213
214void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
215 LOG_WARNING(Service_AM, "(STUBBED) called");
216
217 IPC::ResponseBuilder rb{ctx, 2};
218 rb.Push(ResultSuccess);
219}
220
221void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) {
222 LOG_DEBUG(Service_AM, "called");
223
224 IPC::ResponseBuilder rb{ctx, 2, 1};
225 rb.Push(ResultSuccess);
226 rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent());
227}
228
229void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
230 LOG_DEBUG(Service_AM, "called");
231
232 IPC::ResponseBuilder rb{ctx, 4};
233 rb.Push(ResultSuccess);
234
235 if (Settings::IsDockedMode()) {
236 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
237 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
238 } else {
239 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
240 rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
241 }
242}
243
244void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) {
245 LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
246
247 const auto& sm = system.ServiceManager();
248 const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
249 ASSERT(apm_sys != nullptr);
250
251 apm_sys->SetCpuBoostMode(ctx);
252}
253
254void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) {
255 LOG_WARNING(Service_AM, "(STUBBED) called");
256
257 IPC::ResponseBuilder rb{ctx, 3};
258 rb.Push(ResultSuccess);
259 rb.Push(0);
260}
261
262void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) {
263 IPC::RequestParser rp{ctx};
264 const auto system_button{rp.PopEnum<SystemButtonType>()};
265
266 LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button);
267
268 IPC::ResponseBuilder rb{ctx, 2};
269 rb.Push(ResultSuccess);
270}
271
272void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) {
273 LOG_WARNING(Service_AM, "(STUBBED) called");
274
275 IPC::ResponseBuilder rb{ctx, 3};
276 rb.Push(ResultSuccess);
277 rb.PushEnum(SysPlatformRegion::Global);
278}
279
280void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
281 HLERequestContext& ctx) {
282 LOG_WARNING(Service_AM, "(STUBBED) called");
283
284 IPC::ResponseBuilder rb{ctx, 2};
285 rb.Push(ResultSuccess);
286}
287
288} // namespace Service::AM
diff --git a/src/core/hle/service/am/common_state_getter.h b/src/core/hle/service/am/common_state_getter.h
new file mode 100644
index 000000000..11d66f10a
--- /dev/null
+++ b/src/core/hle/service/am/common_state_getter.h
@@ -0,0 +1,78 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/service.h"
8
9#include "core/hle/service/am/applet_message_queue.h"
10
11namespace Service::AM {
12
13class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
14public:
15 explicit ICommonStateGetter(Core::System& system_,
16 std::shared_ptr<AppletMessageQueue> msg_queue_);
17 ~ICommonStateGetter() override;
18
19private:
20 // This is nn::oe::FocusState
21 enum class FocusState : u8 {
22 InFocus = 1,
23 NotInFocus = 2,
24 Background = 3,
25 };
26
27 // This is nn::oe::OperationMode
28 enum class OperationMode : u8 {
29 Handheld = 0,
30 Docked = 1,
31 };
32
33 // This is nn::am::service::SystemButtonType
34 enum class SystemButtonType {
35 None,
36 HomeButtonShortPressing,
37 HomeButtonLongPressing,
38 PowerButtonShortPressing,
39 PowerButtonLongPressing,
40 ShutdownSystem,
41 CaptureButtonShortPressing,
42 CaptureButtonLongPressing,
43 };
44
45 enum class SysPlatformRegion : s32 {
46 Global = 1,
47 Terra = 2,
48 };
49
50 void GetEventHandle(HLERequestContext& ctx);
51 void ReceiveMessage(HLERequestContext& ctx);
52 void GetCurrentFocusState(HLERequestContext& ctx);
53 void RequestToAcquireSleepLock(HLERequestContext& ctx);
54 void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
55 void GetReaderLockAccessorEx(HLERequestContext& ctx);
56 void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
57 void GetOperationMode(HLERequestContext& ctx);
58 void GetPerformanceMode(HLERequestContext& ctx);
59 void GetBootMode(HLERequestContext& ctx);
60 void IsVrModeEnabled(HLERequestContext& ctx);
61 void SetVrModeEnabled(HLERequestContext& ctx);
62 void SetLcdBacklighOffEnabled(HLERequestContext& ctx);
63 void BeginVrModeEx(HLERequestContext& ctx);
64 void EndVrModeEx(HLERequestContext& ctx);
65 void GetDefaultDisplayResolution(HLERequestContext& ctx);
66 void SetCpuBoostMode(HLERequestContext& ctx);
67 void GetBuiltInDisplayType(HLERequestContext& ctx);
68 void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
69 void GetSettingsPlatformRegion(HLERequestContext& ctx);
70 void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
71
72 std::shared_ptr<AppletMessageQueue> msg_queue;
73 bool vr_mode_state{};
74 Kernel::KEvent* sleep_lock_event;
75 KernelHelpers::ServiceContext service_context;
76};
77
78} // namespace Service::AM
diff --git a/src/core/hle/service/am/debug_functions.cpp b/src/core/hle/service/am/debug_functions.cpp
new file mode 100644
index 000000000..f80b970f2
--- /dev/null
+++ b/src/core/hle/service/am/debug_functions.cpp
@@ -0,0 +1,44 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/debug_functions.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9IDebugFunctions::IDebugFunctions(Core::System& system_)
10 : ServiceFramework{system_, "IDebugFunctions"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, nullptr, "NotifyMessageToHomeMenuForDebug"},
14 {1, nullptr, "OpenMainApplication"},
15 {10, nullptr, "PerformSystemButtonPressing"},
16 {20, nullptr, "InvalidateTransitionLayer"},
17 {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
18 {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
19 {40, nullptr, "GetAppletResourceUsageInfo"},
20 {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
21 {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
22 {100, nullptr, "SetCpuBoostModeForApplet"},
23 {101, nullptr, "CancelCpuBoostModeForApplet"},
24 {110, nullptr, "PushToAppletBoundChannelForDebug"},
25 {111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
26 {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
27 {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
28 {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
29 {130, nullptr, "FriendInvitationSetApplicationParameter"},
30 {131, nullptr, "FriendInvitationClearApplicationParameter"},
31 {132, nullptr, "FriendInvitationPushApplicationParameter"},
32 {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
33 {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
34 {300, nullptr, "TerminateAllRunningApplicationsForDebug"},
35 {900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
36 };
37 // clang-format on
38
39 RegisterHandlers(functions);
40}
41
42IDebugFunctions::~IDebugFunctions() = default;
43
44} // namespace Service::AM
diff --git a/src/core/hle/service/am/debug_functions.h b/src/core/hle/service/am/debug_functions.h
new file mode 100644
index 000000000..d55968743
--- /dev/null
+++ b/src/core/hle/service/am/debug_functions.h
@@ -0,0 +1,16 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
11public:
12 explicit IDebugFunctions(Core::System& system_);
13 ~IDebugFunctions() override;
14};
15
16} // namespace Service::AM
diff --git a/src/core/hle/service/am/display_controller.cpp b/src/core/hle/service/am/display_controller.cpp
new file mode 100644
index 000000000..d4d3d60e7
--- /dev/null
+++ b/src/core/hle/service/am/display_controller.cpp
@@ -0,0 +1,97 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/display_controller.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9IDisplayController::IDisplayController(Core::System& system_)
10 : ServiceFramework{system_, "IDisplayController"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, nullptr, "GetLastForegroundCaptureImage"},
14 {1, nullptr, "UpdateLastForegroundCaptureImage"},
15 {2, nullptr, "GetLastApplicationCaptureImage"},
16 {3, nullptr, "GetCallerAppletCaptureImage"},
17 {4, nullptr, "UpdateCallerAppletCaptureImage"},
18 {5, nullptr, "GetLastForegroundCaptureImageEx"},
19 {6, nullptr, "GetLastApplicationCaptureImageEx"},
20 {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"},
21 {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
22 {9, nullptr, "CopyBetweenCaptureBuffers"},
23 {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
24 {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
25 {12, nullptr, "AcquireLastForegroundCaptureBuffer"},
26 {13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
27 {14, nullptr, "AcquireCallerAppletCaptureBuffer"},
28 {15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
29 {16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
30 {17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
31 {18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
32 {20, nullptr, "ClearCaptureBuffer"},
33 {21, nullptr, "ClearAppletTransitionBuffer"},
34 {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"},
35 {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
36 {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"},
37 {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"},
38 {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"},
39 {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"},
40 {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
41 };
42 // clang-format on
43
44 RegisterHandlers(functions);
45}
46
47IDisplayController::~IDisplayController() = default;
48
49void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) {
50 LOG_WARNING(Service_AM, "(STUBBED) called");
51
52 IPC::ResponseBuilder rb{ctx, 4};
53 rb.Push(ResultSuccess);
54 rb.Push(1u);
55 rb.Push(1);
56}
57
58void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
59 LOG_WARNING(Service_AM, "(STUBBED) called");
60
61 IPC::ResponseBuilder rb{ctx, 2};
62 rb.Push(ResultSuccess);
63}
64
65void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
66 LOG_WARNING(Service_AM, "(STUBBED) called");
67
68 IPC::ResponseBuilder rb{ctx, 4};
69 rb.Push(ResultSuccess);
70 rb.Push(1U);
71 rb.Push(1);
72}
73
74void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
75 LOG_WARNING(Service_AM, "(STUBBED) called");
76
77 IPC::ResponseBuilder rb{ctx, 2};
78 rb.Push(ResultSuccess);
79}
80
81void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
82 LOG_WARNING(Service_AM, "(STUBBED) called");
83
84 IPC::ResponseBuilder rb{ctx, 4};
85 rb.Push(ResultSuccess);
86 rb.Push(1U);
87 rb.Push(1);
88}
89
90void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
91 LOG_WARNING(Service_AM, "(STUBBED) called");
92
93 IPC::ResponseBuilder rb{ctx, 2};
94 rb.Push(ResultSuccess);
95}
96
97} // namespace Service::AM
diff --git a/src/core/hle/service/am/display_controller.h b/src/core/hle/service/am/display_controller.h
new file mode 100644
index 000000000..32f819294
--- /dev/null
+++ b/src/core/hle/service/am/display_controller.h
@@ -0,0 +1,24 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IDisplayController final : public ServiceFramework<IDisplayController> {
11public:
12 explicit IDisplayController(Core::System& system_);
13 ~IDisplayController() override;
14
15private:
16 void GetCallerAppletCaptureImageEx(HLERequestContext& ctx);
17 void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
18 void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
19 void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
20 void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
21 void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
22};
23
24} // namespace Service::AM
diff --git a/src/core/hle/service/am/global_state_controller.cpp b/src/core/hle/service/am/global_state_controller.cpp
new file mode 100644
index 000000000..ed0eb7108
--- /dev/null
+++ b/src/core/hle/service/am/global_state_controller.cpp
@@ -0,0 +1,34 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/global_state_controller.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9IGlobalStateController::IGlobalStateController(Core::System& system_)
10 : ServiceFramework{system_, "IGlobalStateController"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, nullptr, "RequestToEnterSleep"},
14 {1, nullptr, "EnterSleep"},
15 {2, nullptr, "StartSleepSequence"},
16 {3, nullptr, "StartShutdownSequence"},
17 {4, nullptr, "StartRebootSequence"},
18 {9, nullptr, "IsAutoPowerDownRequested"},
19 {10, nullptr, "LoadAndApplyIdlePolicySettings"},
20 {11, nullptr, "NotifyCecSettingsChanged"},
21 {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
22 {13, nullptr, "UpdateDefaultDisplayResolution"},
23 {14, nullptr, "ShouldSleepOnBoot"},
24 {15, nullptr, "GetHdcpAuthenticationFailedEvent"},
25 {30, nullptr, "OpenCradleFirmwareUpdater"},
26 };
27 // clang-format on
28
29 RegisterHandlers(functions);
30}
31
32IGlobalStateController::~IGlobalStateController() = default;
33
34} // namespace Service::AM
diff --git a/src/core/hle/service/am/global_state_controller.h b/src/core/hle/service/am/global_state_controller.h
new file mode 100644
index 000000000..7125464a1
--- /dev/null
+++ b/src/core/hle/service/am/global_state_controller.h
@@ -0,0 +1,16 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
11public:
12 explicit IGlobalStateController(Core::System& system_);
13 ~IGlobalStateController() override;
14};
15
16} // namespace Service::AM
diff --git a/src/core/hle/service/am/home_menu_functions.cpp b/src/core/hle/service/am/home_menu_functions.cpp
new file mode 100644
index 000000000..640e9fbb7
--- /dev/null
+++ b/src/core/hle/service/am/home_menu_functions.cpp
@@ -0,0 +1,57 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/home_menu_functions.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
10 : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system,
11 "IHomeMenuFunctions"} {
12 // clang-format off
13 static const FunctionInfo functions[] = {
14 {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
15 {11, nullptr, "LockForeground"},
16 {12, nullptr, "UnlockForeground"},
17 {20, nullptr, "PopFromGeneralChannel"},
18 {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
19 {30, nullptr, "GetHomeButtonWriterLockAccessor"},
20 {31, nullptr, "GetWriterLockAccessorEx"},
21 {40, nullptr, "IsSleepEnabled"},
22 {41, nullptr, "IsRebootEnabled"},
23 {50, nullptr, "LaunchSystemApplet"},
24 {51, nullptr, "LaunchStarter"},
25 {100, nullptr, "PopRequestLaunchApplicationForDebug"},
26 {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
27 {200, nullptr, "LaunchDevMenu"},
28 {1000, nullptr, "SetLastApplicationExitReason"},
29 };
30 // clang-format on
31
32 RegisterHandlers(functions);
33
34 pop_from_general_channel_event =
35 service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent");
36}
37
38IHomeMenuFunctions::~IHomeMenuFunctions() {
39 service_context.CloseEvent(pop_from_general_channel_event);
40}
41
42void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) {
43 LOG_WARNING(Service_AM, "(STUBBED) called");
44
45 IPC::ResponseBuilder rb{ctx, 2};
46 rb.Push(ResultSuccess);
47}
48
49void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) {
50 LOG_WARNING(Service_AM, "(STUBBED) called");
51
52 IPC::ResponseBuilder rb{ctx, 2, 1};
53 rb.Push(ResultSuccess);
54 rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
55}
56
57} // namespace Service::AM
diff --git a/src/core/hle/service/am/home_menu_functions.h b/src/core/hle/service/am/home_menu_functions.h
new file mode 100644
index 000000000..e082d5d73
--- /dev/null
+++ b/src/core/hle/service/am/home_menu_functions.h
@@ -0,0 +1,25 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
12public:
13 explicit IHomeMenuFunctions(Core::System& system_);
14 ~IHomeMenuFunctions() override;
15
16private:
17 void RequestToGetForeground(HLERequestContext& ctx);
18 void GetPopFromGeneralChannelEvent(HLERequestContext& ctx);
19
20 KernelHelpers::ServiceContext service_context;
21
22 Kernel::KEvent* pop_from_general_channel_event;
23};
24
25} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_accessor.cpp b/src/core/hle/service/am/library_applet_accessor.cpp
new file mode 100644
index 000000000..1cccdfcf2
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_accessor.cpp
@@ -0,0 +1,178 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/am_results.h"
5#include "core/hle/service/am/library_applet_accessor.h"
6#include "core/hle/service/am/storage.h"
7#include "core/hle/service/ipc_helpers.h"
8
9namespace Service::AM {
10
11ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
12 std::shared_ptr<Applets::Applet> applet_)
13 : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} {
14 // clang-format off
15 static const FunctionInfo functions[] = {
16 {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
17 {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
18 {10, &ILibraryAppletAccessor::Start, "Start"},
19 {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"},
20 {25, nullptr, "Terminate"},
21 {30, &ILibraryAppletAccessor::GetResult, "GetResult"},
22 {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
23 {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"},
24 {100, &ILibraryAppletAccessor::PushInData, "PushInData"},
25 {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
26 {102, nullptr, "PushExtraStorage"},
27 {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
28 {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
29 {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
30 {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
31 {110, nullptr, "NeedsToExitProcess"},
32 {120, nullptr, "GetLibraryAppletInfo"},
33 {150, nullptr, "RequestForAppletToGetForeground"},
34 {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"},
35 };
36 // clang-format on
37
38 RegisterHandlers(functions);
39}
40
41void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) {
42 LOG_DEBUG(Service_AM, "called");
43
44 IPC::ResponseBuilder rb{ctx, 2, 1};
45 rb.Push(ResultSuccess);
46 rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent());
47}
48
49void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) {
50 LOG_DEBUG(Service_AM, "called");
51
52 IPC::ResponseBuilder rb{ctx, 3};
53 rb.Push(ResultSuccess);
54 rb.Push<u32>(applet->TransactionComplete());
55}
56
57void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) {
58 LOG_DEBUG(Service_AM, "called");
59
60 IPC::ResponseBuilder rb{ctx, 2};
61 rb.Push(applet->GetStatus());
62}
63
64void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
65 LOG_WARNING(Service_AM, "(STUBBED) called");
66
67 IPC::ResponseBuilder rb{ctx, 2};
68 rb.Push(ResultSuccess);
69}
70
71void ILibraryAppletAccessor::Start(HLERequestContext& ctx) {
72 LOG_DEBUG(Service_AM, "called");
73
74 ASSERT(applet != nullptr);
75
76 applet->Initialize();
77 applet->Execute();
78
79 IPC::ResponseBuilder rb{ctx, 2};
80 rb.Push(ResultSuccess);
81}
82
83void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) {
84 LOG_DEBUG(Service_AM, "called");
85
86 ASSERT(applet != nullptr);
87
88 IPC::ResponseBuilder rb{ctx, 2};
89 rb.Push(applet->RequestExit());
90}
91
92void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
93 LOG_DEBUG(Service_AM, "called");
94
95 IPC::RequestParser rp{ctx};
96 applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>().lock());
97
98 IPC::ResponseBuilder rb{ctx, 2};
99 rb.Push(ResultSuccess);
100}
101
102void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) {
103 LOG_DEBUG(Service_AM, "called");
104
105 auto storage = applet->GetBroker().PopNormalDataToGame();
106 if (storage == nullptr) {
107 LOG_DEBUG(Service_AM,
108 "storage is a nullptr. There is no data in the current normal channel");
109 IPC::ResponseBuilder rb{ctx, 2};
110 rb.Push(AM::ResultNoDataInChannel);
111 return;
112 }
113
114 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
115 rb.Push(ResultSuccess);
116 rb.PushIpcInterface<IStorage>(std::move(storage));
117}
118
119void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
120 LOG_DEBUG(Service_AM, "called");
121
122 IPC::RequestParser rp{ctx};
123 applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>().lock());
124
125 ASSERT(applet->IsInitialized());
126 applet->ExecuteInteractive();
127 applet->Execute();
128
129 IPC::ResponseBuilder rb{ctx, 2};
130 rb.Push(ResultSuccess);
131}
132
133void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) {
134 LOG_DEBUG(Service_AM, "called");
135
136 auto storage = applet->GetBroker().PopInteractiveDataToGame();
137 if (storage == nullptr) {
138 LOG_DEBUG(Service_AM,
139 "storage is a nullptr. There is no data in the current interactive channel");
140 IPC::ResponseBuilder rb{ctx, 2};
141 rb.Push(AM::ResultNoDataInChannel);
142 return;
143 }
144
145 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
146 rb.Push(ResultSuccess);
147 rb.PushIpcInterface<IStorage>(std::move(storage));
148}
149
150void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
151 LOG_DEBUG(Service_AM, "called");
152
153 IPC::ResponseBuilder rb{ctx, 2, 1};
154 rb.Push(ResultSuccess);
155 rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
156}
157
158void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
159 LOG_DEBUG(Service_AM, "called");
160
161 IPC::ResponseBuilder rb{ctx, 2, 1};
162 rb.Push(ResultSuccess);
163 rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
164}
165
166void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) {
167 LOG_WARNING(Service_AM, "(STUBBED) called");
168
169 // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
170 // actually used anywhere
171 constexpr u64 handle = 0xdeadbeef;
172
173 IPC::ResponseBuilder rb{ctx, 4};
174 rb.Push(ResultSuccess);
175 rb.Push(handle);
176}
177
178} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_accessor.h b/src/core/hle/service/am/library_applet_accessor.h
new file mode 100644
index 000000000..698467233
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_accessor.h
@@ -0,0 +1,34 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/applets/applets.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
12public:
13 explicit ILibraryAppletAccessor(Core::System& system_,
14 std::shared_ptr<Applets::Applet> applet_);
15
16private:
17 void GetAppletStateChangedEvent(HLERequestContext& ctx);
18 void IsCompleted(HLERequestContext& ctx);
19 void GetResult(HLERequestContext& ctx);
20 void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx);
21 void Start(HLERequestContext& ctx);
22 void RequestExit(HLERequestContext& ctx);
23 void PushInData(HLERequestContext& ctx);
24 void PopOutData(HLERequestContext& ctx);
25 void PushInteractiveInData(HLERequestContext& ctx);
26 void PopInteractiveOutData(HLERequestContext& ctx);
27 void GetPopOutDataEvent(HLERequestContext& ctx);
28 void GetPopInteractiveOutDataEvent(HLERequestContext& ctx);
29 void GetIndirectLayerConsumerHandle(HLERequestContext& ctx);
30
31 std::shared_ptr<Applets::Applet> applet;
32};
33
34} // 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
new file mode 100644
index 000000000..c33f50a40
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_creator.cpp
@@ -0,0 +1,145 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/kernel/k_transfer_memory.h"
5#include "core/hle/service/am/applets/applets.h"
6#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/storage.h"
9#include "core/hle/service/ipc_helpers.h"
10
11namespace Service::AM {
12
13ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
14 : ServiceFramework{system_, "ILibraryAppletCreator"} {
15 static const FunctionInfo functions[] = {
16 {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
17 {1, nullptr, "TerminateAllLibraryApplets"},
18 {2, nullptr, "AreAnyLibraryAppletsLeft"},
19 {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
20 {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
21 {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
22 };
23 RegisterHandlers(functions);
24}
25
26ILibraryAppletCreator::~ILibraryAppletCreator() = default;
27
28void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
29 IPC::RequestParser rp{ctx};
30
31 const auto applet_id = rp.PopRaw<Applets::AppletId>();
32 const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>();
33
34 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
35 applet_mode);
36
37 const auto& applet_manager{system.GetAppletManager()};
38 const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
39
40 if (applet == nullptr) {
41 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
42
43 IPC::ResponseBuilder rb{ctx, 2};
44 rb.Push(ResultUnknown);
45 return;
46 }
47
48 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
49
50 rb.Push(ResultSuccess);
51 rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
52}
53
54void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) {
55 IPC::RequestParser rp{ctx};
56
57 const s64 size{rp.Pop<s64>()};
58
59 LOG_DEBUG(Service_AM, "called, size={}", size);
60
61 if (size <= 0) {
62 LOG_ERROR(Service_AM, "size is less than or equal to 0");
63 IPC::ResponseBuilder rb{ctx, 2};
64 rb.Push(ResultUnknown);
65 return;
66 }
67
68 std::vector<u8> buffer(size);
69
70 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
71 rb.Push(ResultSuccess);
72 rb.PushIpcInterface<IStorage>(system, std::move(buffer));
73}
74
75void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) {
76 IPC::RequestParser rp{ctx};
77
78 struct Parameters {
79 u8 permissions;
80 s64 size;
81 };
82
83 const auto parameters{rp.PopRaw<Parameters>()};
84 const auto handle{ctx.GetCopyHandle(0)};
85
86 LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions,
87 parameters.size, handle);
88
89 if (parameters.size <= 0) {
90 LOG_ERROR(Service_AM, "size is less than or equal to 0");
91 IPC::ResponseBuilder rb{ctx, 2};
92 rb.Push(ResultUnknown);
93 return;
94 }
95
96 auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
97
98 if (transfer_mem.IsNull()) {
99 LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
100 IPC::ResponseBuilder rb{ctx, 2};
101 rb.Push(ResultUnknown);
102 return;
103 }
104
105 std::vector<u8> memory(transfer_mem->GetSize());
106 ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
107
108 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
109 rb.Push(ResultSuccess);
110 rb.PushIpcInterface<IStorage>(system, std::move(memory));
111}
112
113void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
114 IPC::RequestParser rp{ctx};
115
116 const s64 size{rp.Pop<s64>()};
117 const auto handle{ctx.GetCopyHandle(0)};
118
119 LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
120
121 if (size <= 0) {
122 LOG_ERROR(Service_AM, "size is less than or equal to 0");
123 IPC::ResponseBuilder rb{ctx, 2};
124 rb.Push(ResultUnknown);
125 return;
126 }
127
128 auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
129
130 if (transfer_mem.IsNull()) {
131 LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
132 IPC::ResponseBuilder rb{ctx, 2};
133 rb.Push(ResultUnknown);
134 return;
135 }
136
137 std::vector<u8> memory(transfer_mem->GetSize());
138 ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
139
140 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
141 rb.Push(ResultSuccess);
142 rb.PushIpcInterface<IStorage>(system, std::move(memory));
143}
144
145} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_creator.h b/src/core/hle/service/am/library_applet_creator.h
new file mode 100644
index 000000000..97f236fbc
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_creator.h
@@ -0,0 +1,22 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
11public:
12 explicit ILibraryAppletCreator(Core::System& system_);
13 ~ILibraryAppletCreator() override;
14
15private:
16 void CreateLibraryApplet(HLERequestContext& ctx);
17 void CreateStorage(HLERequestContext& ctx);
18 void CreateTransferMemoryStorage(HLERequestContext& ctx);
19 void CreateHandleStorage(HLERequestContext& ctx);
20};
21
22} // 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
new file mode 100644
index 000000000..047fc40f4
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_proxy.cpp
@@ -0,0 +1,142 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applet_common_functions.h"
5#include "core/hle/service/am/audio_controller.h"
6#include "core/hle/service/am/common_state_getter.h"
7#include "core/hle/service/am/debug_functions.h"
8#include "core/hle/service/am/display_controller.h"
9#include "core/hle/service/am/global_state_controller.h"
10#include "core/hle/service/am/home_menu_functions.h"
11#include "core/hle/service/am/library_applet_creator.h"
12#include "core/hle/service/am/library_applet_proxy.h"
13#include "core/hle/service/am/library_applet_self_accessor.h"
14#include "core/hle/service/am/process_winding_controller.h"
15#include "core/hle/service/am/self_controller.h"
16#include "core/hle/service/am/window_controller.h"
17#include "core/hle/service/ipc_helpers.h"
18
19namespace Service::AM {
20
21ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
22 std::shared_ptr<AppletMessageQueue> msg_queue_,
23 Core::System& system_)
24 : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_},
25 msg_queue{std::move(msg_queue_)} {
26 // clang-format off
27 static const FunctionInfo functions[] = {
28 {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
29 {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
30 {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
31 {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
32 {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
33 {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
34 {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
35 {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
36 {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
37 {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
38 {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
39 {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
40 };
41 // clang-format on
42
43 RegisterHandlers(functions);
44}
45
46void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
47 LOG_DEBUG(Service_AM, "called");
48
49 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
50 rb.Push(ResultSuccess);
51 rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
52}
53
54void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
55 LOG_DEBUG(Service_AM, "called");
56
57 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
58 rb.Push(ResultSuccess);
59 rb.PushIpcInterface<ISelfController>(system, nvnflinger);
60}
61
62void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) {
63 LOG_DEBUG(Service_AM, "called");
64
65 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
66 rb.Push(ResultSuccess);
67 rb.PushIpcInterface<IWindowController>(system);
68}
69
70void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) {
71 LOG_DEBUG(Service_AM, "called");
72
73 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
74 rb.Push(ResultSuccess);
75 rb.PushIpcInterface<IAudioController>(system);
76}
77
78void ILibraryAppletProxy::GetDisplayController(HLERequestContext& ctx) {
79 LOG_DEBUG(Service_AM, "called");
80
81 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
82 rb.Push(ResultSuccess);
83 rb.PushIpcInterface<IDisplayController>(system);
84}
85
86void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) {
87 LOG_DEBUG(Service_AM, "called");
88
89 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
90 rb.Push(ResultSuccess);
91 rb.PushIpcInterface<IProcessWindingController>(system);
92}
93
94void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
95 LOG_DEBUG(Service_AM, "called");
96
97 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
98 rb.Push(ResultSuccess);
99 rb.PushIpcInterface<ILibraryAppletCreator>(system);
100}
101
102void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
103 LOG_DEBUG(Service_AM, "called");
104
105 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
106 rb.Push(ResultSuccess);
107 rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
108}
109
110void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
111 LOG_DEBUG(Service_AM, "called");
112
113 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
114 rb.Push(ResultSuccess);
115 rb.PushIpcInterface<IAppletCommonFunctions>(system);
116}
117
118void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
119 LOG_DEBUG(Service_AM, "called");
120
121 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
122 rb.Push(ResultSuccess);
123 rb.PushIpcInterface<IHomeMenuFunctions>(system);
124}
125
126void ILibraryAppletProxy::GetGlobalStateController(HLERequestContext& ctx) {
127 LOG_DEBUG(Service_AM, "called");
128
129 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
130 rb.Push(ResultSuccess);
131 rb.PushIpcInterface<IGlobalStateController>(system);
132}
133
134void ILibraryAppletProxy::GetDebugFunctions(HLERequestContext& ctx) {
135 LOG_DEBUG(Service_AM, "called");
136
137 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
138 rb.Push(ResultSuccess);
139 rb.PushIpcInterface<IDebugFunctions>(system);
140}
141
142} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_proxy.h b/src/core/hle/service/am/library_applet_proxy.h
new file mode 100644
index 000000000..cd9e6d02b
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_proxy.h
@@ -0,0 +1,35 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/applet_message_queue.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
12public:
13 explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
14 std::shared_ptr<AppletMessageQueue> msg_queue_,
15 Core::System& system_);
16
17private:
18 void GetCommonStateGetter(HLERequestContext& ctx);
19 void GetSelfController(HLERequestContext& ctx);
20 void GetWindowController(HLERequestContext& ctx);
21 void GetAudioController(HLERequestContext& ctx);
22 void GetDisplayController(HLERequestContext& ctx);
23 void GetProcessWindingController(HLERequestContext& ctx);
24 void GetLibraryAppletCreator(HLERequestContext& ctx);
25 void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx);
26 void GetAppletCommonFunctions(HLERequestContext& ctx);
27 void GetHomeMenuFunctions(HLERequestContext& ctx);
28 void GetGlobalStateController(HLERequestContext& ctx);
29 void GetDebugFunctions(HLERequestContext& ctx);
30
31 Nvnflinger::Nvnflinger& nvnflinger;
32 std::shared_ptr<AppletMessageQueue> msg_queue;
33};
34
35} // 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
new file mode 100644
index 000000000..0a12afbbd
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_self_accessor.cpp
@@ -0,0 +1,382 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/core_timing.h"
5#include "core/hle/service/acc/profile_manager.h"
6#include "core/hle/service/am/am_results.h"
7#include "core/hle/service/am/applets/applet_cabinet.h"
8#include "core/hle/service/am/applets/applet_controller.h"
9#include "core/hle/service/am/applets/applet_mii_edit_types.h"
10#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
11#include "core/hle/service/am/applets/applets.h"
12#include "core/hle/service/am/library_applet_self_accessor.h"
13#include "core/hle/service/am/storage.h"
14#include "core/hle/service/ipc_helpers.h"
15#include "hid_core/hid_types.h"
16
17namespace Service::AM {
18
19ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
20 : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
21 // clang-format off
22 static const FunctionInfo functions[] = {
23 {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
24 {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
25 {2, nullptr, "PopInteractiveInData"},
26 {3, nullptr, "PushInteractiveOutData"},
27 {5, nullptr, "GetPopInDataEvent"},
28 {6, nullptr, "GetPopInteractiveInDataEvent"},
29 {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
30 {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
31 {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
32 {13, nullptr, "CanUseApplicationCore"},
33 {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
34 {15, nullptr, "GetMainAppletApplicationControlProperty"},
35 {16, nullptr, "GetMainAppletStorageId"},
36 {17, nullptr, "GetCallerAppletIdentityInfoStack"},
37 {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
38 {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"},
39 {20, nullptr, "PopExtraStorage"},
40 {25, nullptr, "GetPopExtraStorageEvent"},
41 {30, nullptr, "UnpopInData"},
42 {31, nullptr, "UnpopExtraStorage"},
43 {40, nullptr, "GetIndirectLayerProducerHandle"},
44 {50, nullptr, "ReportVisibleError"},
45 {51, nullptr, "ReportVisibleErrorWithErrorContext"},
46 {60, nullptr, "GetMainAppletApplicationDesiredLanguage"},
47 {70, nullptr, "GetCurrentApplicationId"},
48 {80, nullptr, "RequestExitToSelf"},
49 {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
50 {100, nullptr, "CreateGameMovieTrimmer"},
51 {101, nullptr, "ReserveResourceForMovieOperation"},
52 {102, nullptr, "UnreserveResourceForMovieOperation"},
53 {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"},
54 {120, nullptr, "GetLaunchStorageInfoForDebug"},
55 {130, nullptr, "GetGpuErrorDetectedSystemEvent"},
56 {140, nullptr, "SetApplicationMemoryReservation"},
57 {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
58 };
59 // clang-format on
60 RegisterHandlers(functions);
61
62 switch (system.GetAppletManager().GetCurrentAppletId()) {
63 case Applets::AppletId::Cabinet:
64 PushInShowCabinetData();
65 break;
66 case Applets::AppletId::MiiEdit:
67 PushInShowMiiEditData();
68 break;
69 case Applets::AppletId::PhotoViewer:
70 PushInShowAlbum();
71 break;
72 case Applets::AppletId::SoftwareKeyboard:
73 PushInShowSoftwareKeyboard();
74 break;
75 case Applets::AppletId::Controller:
76 PushInShowController();
77 break;
78 default:
79 break;
80 }
81}
82
83ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
84
85void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
86 LOG_INFO(Service_AM, "called");
87
88 if (queue_data.empty()) {
89 IPC::ResponseBuilder rb{ctx, 2};
90 rb.Push(AM::ResultNoDataInChannel);
91 return;
92 }
93
94 auto data = queue_data.front();
95 queue_data.pop_front();
96
97 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
98 rb.Push(ResultSuccess);
99 rb.PushIpcInterface<IStorage>(system, std::move(data));
100}
101
102void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
103 LOG_WARNING(Service_AM, "(STUBBED) called");
104
105 IPC::ResponseBuilder rb{ctx, 2};
106 rb.Push(ResultSuccess);
107}
108
109void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
110 LOG_WARNING(Service_AM, "(STUBBED) called");
111
112 system.Exit();
113
114 IPC::ResponseBuilder rb{ctx, 2};
115 rb.Push(ResultSuccess);
116}
117
118void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
119 struct LibraryAppletInfo {
120 Applets::AppletId applet_id;
121 Applets::LibraryAppletMode library_applet_mode;
122 };
123
124 LOG_WARNING(Service_AM, "(STUBBED) called");
125
126 const LibraryAppletInfo applet_info{
127 .applet_id = system.GetAppletManager().GetCurrentAppletId(),
128 .library_applet_mode = Applets::LibraryAppletMode::AllForeground,
129 };
130
131 IPC::ResponseBuilder rb{ctx, 4};
132 rb.Push(ResultSuccess);
133 rb.PushRaw(applet_info);
134}
135
136void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
137 struct AppletIdentityInfo {
138 Applets::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");
145
146 const AppletIdentityInfo applet_info{
147 .applet_id = Applets::AppletId::QLaunch,
148 .application_id = 0x0100000000001000ull,
149 };
150
151 IPC::ResponseBuilder rb{ctx, 6};
152 rb.Push(ResultSuccess);
153 rb.PushRaw(applet_info);
154}
155
156void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
157 struct AppletIdentityInfo {
158 Applets::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");
164
165 const AppletIdentityInfo applet_info{
166 .applet_id = Applets::AppletId::QLaunch,
167 .application_id = 0x0100000000001000ull,
168 };
169
170 IPC::ResponseBuilder rb{ctx, 6};
171 rb.Push(ResultSuccess);
172 rb.PushRaw(applet_info);
173}
174
175void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
176 LOG_WARNING(Service_AM, "(STUBBED) called");
177
178 IPC::ResponseBuilder rb{ctx, 3};
179 rb.Push(ResultSuccess);
180 rb.Push<u32>(0);
181}
182
183void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) {
184 const Service::Account::ProfileManager manager{};
185 bool is_empty{true};
186 s32 user_count{-1};
187
188 LOG_INFO(Service_AM, "called");
189
190 if (manager.GetUserCount() > 0) {
191 is_empty = false;
192 user_count = static_cast<s32>(manager.GetUserCount());
193 ctx.WriteBuffer(manager.GetAllUsers());
194 }
195
196 IPC::ResponseBuilder rb{ctx, 4};
197 rb.Push(ResultSuccess);
198 rb.Push<u8>(is_empty);
199 rb.Push(user_count);
200}
201
202void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) {
203 LOG_WARNING(Service_AM, "(STUBBED) called");
204
205 IPC::ResponseBuilder rb{ctx, 3};
206 rb.Push(ResultSuccess);
207 rb.Push<u8>(0);
208}
209
210void ILibraryAppletSelfAccessor::PushInShowAlbum() {
211 const Applets::CommonArguments arguments{
212 .arguments_version = Applets::CommonArgumentVersion::Version3,
213 .size = Applets::CommonArgumentSize::Version3,
214 .library_version = 1,
215 .theme_color = Applets::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 Applets::CommonArguments common_args = {
229 .arguments_version = Applets::CommonArgumentVersion::Version3,
230 .size = Applets::CommonArgumentSize::Version3,
231 .library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8),
232 .theme_color = Applets::ThemeColor::BasicBlack,
233 .play_startup_sound = true,
234 .system_tick = system.CoreTiming().GetClockTicks(),
235 };
236
237 Applets::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 Applets::ControllerSupportArgPrivate private_args = {
251 .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate),
252 .arg_size = sizeof(Applets::ControllerSupportArgNew),
253 .is_home_menu = true,
254 .flag_1 = true,
255 .mode = Applets::ControllerSupportMode::ShowControllerSupport,
256 .caller = Applets::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 Applets::CommonArguments arguments{
278 .arguments_version = Applets::CommonArgumentVersion::Version3,
279 .size = Applets::CommonArgumentSize::Version3,
280 .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1),
281 .theme_color = Applets::ThemeColor::BasicBlack,
282 .play_startup_sound = true,
283 .system_tick = system.CoreTiming().GetClockTicks(),
284 };
285
286 const Applets::StartParamForAmiiboSettings amiibo_settings{
287 .param_1 = 0,
288 .applet_mode = system.GetAppletManager().GetCabinetMode(),
289 .flags = Applets::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 Applets::MiiEditAppletInputCommon common;
308 Applets::MiiEditAppletInputV3 input;
309 };
310 static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
311
312 MiiEditV3 mii_arguments{
313 .common =
314 {
315 .version = Applets::MiiEditAppletVersion::Version3,
316 .applet_mode = Applets::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 Applets::CommonArguments arguments{
329 .arguments_version = Applets::CommonArgumentVersion::Version3,
330 .size = Applets::CommonArgumentSize::Version3,
331 .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301),
332 .theme_color = Applets::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 Applets::SwkbdConfigCommon swkbd_config{
340 .type = Applets::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 = Applets::SwkbdInitialCursorPosition::Start,
347 .header_text{},
348 .sub_text{},
349 .guide_text{},
350 .max_text_length = 500,
351 .min_text_length = 0,
352 .password_mode = Applets::SwkbdPasswordMode::Disabled,
353 .text_draw_type = Applets::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 Applets::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(Applets::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
diff --git a/src/core/hle/service/am/library_applet_self_accessor.h b/src/core/hle/service/am/library_applet_self_accessor.h
new file mode 100644
index 000000000..45b325b77
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_self_accessor.h
@@ -0,0 +1,38 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <deque>
7#include <vector>
8
9#include "core/hle/service/service.h"
10
11namespace Service::AM {
12
13class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
14public:
15 explicit ILibraryAppletSelfAccessor(Core::System& system_);
16 ~ILibraryAppletSelfAccessor() override;
17
18private:
19 void PopInData(HLERequestContext& ctx);
20 void PushOutData(HLERequestContext& ctx);
21 void GetLibraryAppletInfo(HLERequestContext& ctx);
22 void GetMainAppletIdentityInfo(HLERequestContext& ctx);
23 void ExitProcessAndReturn(HLERequestContext& ctx);
24 void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
25 void GetDesirableKeyboardLayout(HLERequestContext& ctx);
26 void GetMainAppletAvailableUsers(HLERequestContext& ctx);
27 void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
28
29 void PushInShowAlbum();
30 void PushInShowCabinetData();
31 void PushInShowMiiEditData();
32 void PushInShowSoftwareKeyboard();
33 void PushInShowController();
34
35 std::deque<std::vector<u8>> queue_data;
36};
37
38} // namespace Service::AM
diff --git a/src/core/hle/service/am/lock_accessor.cpp b/src/core/hle/service/am/lock_accessor.cpp
new file mode 100644
index 000000000..d0bd8d95e
--- /dev/null
+++ b/src/core/hle/service/am/lock_accessor.cpp
@@ -0,0 +1,71 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/lock_accessor.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9ILockAccessor::ILockAccessor(Core::System& system_)
10 : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {1, &ILockAccessor::TryLock, "TryLock"},
14 {2, &ILockAccessor::Unlock, "Unlock"},
15 {3, &ILockAccessor::GetEvent, "GetEvent"},
16 {4,&ILockAccessor::IsLocked, "IsLocked"},
17 };
18 // clang-format on
19
20 RegisterHandlers(functions);
21
22 lock_event = service_context.CreateEvent("ILockAccessor::LockEvent");
23}
24
25ILockAccessor::~ILockAccessor() {
26 service_context.CloseEvent(lock_event);
27};
28
29void ILockAccessor::TryLock(HLERequestContext& ctx) {
30 IPC::RequestParser rp{ctx};
31 const auto return_handle = rp.Pop<bool>();
32
33 LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle);
34
35 // TODO: When return_handle is true this function should return the lock handle
36
37 is_locked = true;
38
39 IPC::ResponseBuilder rb{ctx, 3};
40 rb.Push(ResultSuccess);
41 rb.Push<u8>(is_locked);
42}
43
44void ILockAccessor::Unlock(HLERequestContext& ctx) {
45 LOG_INFO(Service_AM, "called");
46
47 is_locked = false;
48
49 IPC::ResponseBuilder rb{ctx, 2};
50 rb.Push(ResultSuccess);
51}
52
53void ILockAccessor::GetEvent(HLERequestContext& ctx) {
54 LOG_INFO(Service_AM, "called");
55
56 lock_event->Signal();
57
58 IPC::ResponseBuilder rb{ctx, 2, 1};
59 rb.Push(ResultSuccess);
60 rb.PushCopyObjects(lock_event->GetReadableEvent());
61}
62
63void ILockAccessor::IsLocked(HLERequestContext& ctx) {
64 LOG_INFO(Service_AM, "called");
65
66 IPC::ResponseBuilder rb{ctx, 2};
67 rb.Push(ResultSuccess);
68 rb.Push<u8>(is_locked);
69}
70
71} // namespace Service::AM
diff --git a/src/core/hle/service/am/lock_accessor.h b/src/core/hle/service/am/lock_accessor.h
new file mode 100644
index 000000000..626f60e07
--- /dev/null
+++ b/src/core/hle/service/am/lock_accessor.h
@@ -0,0 +1,28 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class ILockAccessor final : public ServiceFramework<ILockAccessor> {
12public:
13 explicit ILockAccessor(Core::System& system_);
14 ~ILockAccessor() override;
15
16private:
17 void TryLock(HLERequestContext& ctx);
18 void Unlock(HLERequestContext& ctx);
19 void GetEvent(HLERequestContext& ctx);
20 void IsLocked(HLERequestContext& ctx);
21
22 bool is_locked{};
23
24 Kernel::KEvent* lock_event;
25 KernelHelpers::ServiceContext service_context;
26};
27
28} // 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
new file mode 100644
index 000000000..7b3ab157f
--- /dev/null
+++ b/src/core/hle/service/am/process_winding_controller.cpp
@@ -0,0 +1,73 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applets/applets.h"
5#include "core/hle/service/am/library_applet_accessor.h"
6#include "core/hle/service/am/process_winding_controller.h"
7#include "core/hle/service/ipc_helpers.h"
8
9namespace Service::AM {
10
11IProcessWindingController::IProcessWindingController(Core::System& system_)
12 : ServiceFramework{system_, "IProcessWindingController"} {
13 // clang-format off
14 static const FunctionInfo functions[] = {
15 {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
16 {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"},
17 {21, nullptr, "PushContext"},
18 {22, nullptr, "PopContext"},
19 {23, nullptr, "CancelWindingReservation"},
20 {30, nullptr, "WindAndDoReserved"},
21 {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
22 {41, nullptr, "ReserveToStartAndWait"},
23 };
24 // clang-format on
25
26 RegisterHandlers(functions);
27}
28
29IProcessWindingController::~IProcessWindingController() = default;
30
31void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
32 LOG_WARNING(Service_AM, "(STUBBED) called");
33
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};
46 rb.Push(ResultSuccess);
47 rb.PushRaw(reason);
48}
49
50void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
51 const auto applet_id = system.GetAppletManager().GetCurrentAppletId();
52 const auto applet_mode = Applets::LibraryAppletMode::AllForeground;
53
54 LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
55 applet_mode);
56
57 const auto& applet_manager{system.GetAppletManager()};
58 const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
59
60 if (applet == nullptr) {
61 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
62
63 IPC::ResponseBuilder rb{ctx, 2};
64 rb.Push(ResultUnknown);
65 return;
66 }
67
68 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
69 rb.Push(ResultSuccess);
70 rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
71}
72
73} // 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
new file mode 100644
index 000000000..9b9704201
--- /dev/null
+++ b/src/core/hle/service/am/process_winding_controller.h
@@ -0,0 +1,20 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
11public:
12 explicit IProcessWindingController(Core::System& system_);
13 ~IProcessWindingController() override;
14
15private:
16 void GetLaunchReason(HLERequestContext& ctx);
17 void OpenCallingLibraryApplet(HLERequestContext& ctx);
18};
19
20} // namespace Service::AM
diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp
new file mode 100644
index 000000000..0f495c871
--- /dev/null
+++ b/src/core/hle/service/am/self_controller.cpp
@@ -0,0 +1,438 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applets/applets.h"
5#include "core/hle/service/am/self_controller.h"
6#include "core/hle/service/caps/caps_su.h"
7#include "core/hle/service/ipc_helpers.h"
8#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
9#include "core/hle/service/nvnflinger/nvnflinger.h"
10#include "core/hle/service/sm/sm.h"
11#include "core/hle/service/vi/vi_results.h"
12
13namespace Service::AM {
14
15ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
16 : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_},
17 service_context{system, "ISelfController"} {
18 // clang-format off
19 static const FunctionInfo functions[] = {
20 {0, &ISelfController::Exit, "Exit"},
21 {1, &ISelfController::LockExit, "LockExit"},
22 {2, &ISelfController::UnlockExit, "UnlockExit"},
23 {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
24 {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
25 {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
26 {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
27 {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
28 {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"},
29 {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
30 {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
31 {15, nullptr, "SetScreenShotAppletIdentityInfo"},
32 {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
33 {17, nullptr, "SetControllerFirmwareUpdateSection"},
34 {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
35 {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
36 {20, nullptr, "SetDesirableKeyboardLayout"},
37 {21, nullptr, "GetScreenShotProgramId"},
38 {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
39 {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"},
40 {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"},
41 {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"},
42 {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
43 {45, nullptr, "SetManagedDisplayLayerSeparationMode"},
44 {46, nullptr, "SetRecordingLayerCompositionEnabled"},
45 {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
46 {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
47 {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
48 {61, nullptr, "SetMediaPlaybackState"},
49 {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
50 {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
51 {64, nullptr, "SetInputDetectionSourceSet"},
52 {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"},
53 {66, nullptr, "GetCurrentIlluminance"},
54 {67, nullptr, "IsIlluminanceAvailable"},
55 {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"},
56 {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"},
57 {70, nullptr, "ReportMultimediaError"},
58 {71, nullptr, "GetCurrentIlluminanceEx"},
59 {72, nullptr, "SetInputDetectionPolicy"},
60 {80, nullptr, "SetWirelessPriorityMode"},
61 {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
62 {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
63 {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
64 {110, nullptr, "SetApplicationAlbumUserData"},
65 {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"},
66 {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"},
67 {1000, nullptr, "GetDebugStorageChannel"},
68 };
69 // clang-format on
70
71 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}
85
86ISelfController::~ISelfController() {
87 service_context.CloseEvent(launchable_event);
88 service_context.CloseEvent(accumulated_suspended_tick_changed_event);
89}
90
91void ISelfController::Exit(HLERequestContext& ctx) {
92 LOG_DEBUG(Service_AM, "called");
93
94 IPC::ResponseBuilder rb{ctx, 2};
95 rb.Push(ResultSuccess);
96
97 system.Exit();
98}
99
100void ISelfController::LockExit(HLERequestContext& ctx) {
101 LOG_DEBUG(Service_AM, "called");
102
103 system.SetExitLocked(true);
104
105 IPC::ResponseBuilder rb{ctx, 2};
106 rb.Push(ResultSuccess);
107}
108
109void ISelfController::UnlockExit(HLERequestContext& ctx) {
110 LOG_DEBUG(Service_AM, "called");
111
112 system.SetExitLocked(false);
113
114 IPC::ResponseBuilder rb{ctx, 2};
115 rb.Push(ResultSuccess);
116
117 if (system.GetExitRequested()) {
118 system.Exit();
119 }
120}
121
122void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
123 ++num_fatal_sections_entered;
124 LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
125
126 IPC::ResponseBuilder rb{ctx, 2};
127 rb.Push(ResultSuccess);
128}
129
130void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
131 LOG_DEBUG(Service_AM, "called.");
132
133 // Entry and exit of fatal sections must be balanced.
134 if (num_fatal_sections_entered == 0) {
135 IPC::ResponseBuilder rb{ctx, 2};
136 rb.Push(Result{ErrorModule::AM, 512});
137 return;
138 }
139
140 --num_fatal_sections_entered;
141
142 IPC::ResponseBuilder rb{ctx, 2};
143 rb.Push(ResultSuccess);
144}
145
146void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
147 LOG_WARNING(Service_AM, "(STUBBED) called");
148
149 launchable_event->Signal();
150
151 IPC::ResponseBuilder rb{ctx, 2, 1};
152 rb.Push(ResultSuccess);
153 rb.PushCopyObjects(launchable_event->GetReadableEvent());
154}
155
156void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
157 IPC::RequestParser rp{ctx};
158 const auto permission = rp.PopEnum<ScreenshotPermission>();
159 LOG_DEBUG(Service_AM, "called, permission={}", permission);
160
161 screenshot_permission = permission;
162
163 IPC::ResponseBuilder rb{ctx, 2};
164 rb.Push(ResultSuccess);
165}
166
167void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
168 IPC::RequestParser rp{ctx};
169
170 bool flag = rp.Pop<bool>();
171 LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
172
173 IPC::ResponseBuilder rb{ctx, 2};
174 rb.Push(ResultSuccess);
175}
176
177void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
178 IPC::RequestParser rp{ctx};
179
180 bool flag = rp.Pop<bool>();
181 LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
182
183 IPC::ResponseBuilder rb{ctx, 2};
184 rb.Push(ResultSuccess);
185}
186
187void 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};
191
192 struct FocusHandlingModeParams {
193 u8 unknown0;
194 u8 unknown1;
195 u8 unknown2;
196 };
197 const auto flags = rp.PopRaw<FocusHandlingModeParams>();
198
199 LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
200 flags.unknown0, flags.unknown1, flags.unknown2);
201
202 IPC::ResponseBuilder rb{ctx, 2};
203 rb.Push(ResultSuccess);
204}
205
206void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
207 LOG_WARNING(Service_AM, "(STUBBED) called");
208
209 IPC::ResponseBuilder rb{ctx, 2};
210 rb.Push(ResultSuccess);
211}
212
213void 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};
217
218 bool enabled = rp.Pop<bool>();
219 LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
220
221 IPC::ResponseBuilder rb{ctx, 2};
222 rb.Push(ResultSuccess);
223}
224
225void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
226 LOG_WARNING(Service_AM, "(STUBBED) called");
227
228 IPC::ResponseBuilder rb{ctx, 2};
229 rb.Push(ResultSuccess);
230}
231
232void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
233 LOG_WARNING(Service_AM, "(STUBBED) called");
234
235 // TODO(Subv): Find out how AM determines the display to use, for now just
236 // create the layer in the Default display.
237 const auto display_id = nvnflinger.OpenDisplay("Default");
238 const auto layer_id = nvnflinger.CreateLayer(*display_id);
239
240 IPC::ResponseBuilder rb{ctx, 4};
241 rb.Push(ResultSuccess);
242 rb.Push(*layer_id);
243}
244
245void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
246 LOG_WARNING(Service_AM, "(STUBBED) called");
247
248 IPC::ResponseBuilder rb{ctx, 2};
249 rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
250}
251
252void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
253 LOG_WARNING(Service_AM, "(STUBBED) called");
254
255 IPC::ResponseBuilder rb{ctx, 6};
256 rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
257 rb.Push<s64>(system_shared_buffer_id);
258 rb.Push<s64>(system_shared_layer_id);
259}
260
261void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
262 LOG_WARNING(Service_AM, "(STUBBED) called");
263
264 IPC::ResponseBuilder rb{ctx, 4};
265 rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
266 rb.Push<s64>(system_shared_buffer_id);
267}
268
269Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) {
270 if (buffer_sharing_enabled) {
271 return ResultSuccess;
272 }
273
274 if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) {
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}
288
289void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
290 LOG_WARNING(Service_AM, "(STUBBED) called");
291
292 // TODO(Subv): Find out how AM determines the display to use, for now just
293 // create the layer in the Default display.
294 // This calls nn::vi::CreateRecordingLayer() which creates another layer.
295 // Currently we do not support more than 1 layer per display, output 1 layer id for now.
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
302 IPC::ResponseBuilder rb{ctx, 4};
303 rb.Push(ResultSuccess);
304 rb.Push(*layer_id);
305}
306
307void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
308 LOG_WARNING(Service_AM, "(STUBBED) called");
309
310 IPC::ResponseBuilder rb{ctx, 2};
311 rb.Push(ResultSuccess);
312}
313
314void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
315 LOG_WARNING(Service_AM, "(STUBBED) called");
316
317 IPC::ResponseBuilder rb{ctx, 2};
318 rb.Push(ResultSuccess);
319}
320
321void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
322 IPC::RequestParser rp{ctx};
323 idle_time_detection_extension = rp.Pop<u32>();
324 LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
325 idle_time_detection_extension);
326
327 IPC::ResponseBuilder rb{ctx, 2};
328 rb.Push(ResultSuccess);
329}
330
331void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
332 LOG_WARNING(Service_AM, "(STUBBED) called");
333
334 IPC::ResponseBuilder rb{ctx, 3};
335 rb.Push(ResultSuccess);
336 rb.Push<u32>(idle_time_detection_extension);
337}
338
339void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
340 LOG_WARNING(Service_AM, "(STUBBED) called");
341
342 IPC::ResponseBuilder rb{ctx, 2};
343 rb.Push(ResultSuccess);
344}
345
346void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
347 IPC::RequestParser rp{ctx};
348 is_auto_sleep_disabled = rp.Pop<bool>();
349
350 // 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 // window manager to update (and also increment some statistics like update counts)
353 //
354 // It'd also indicate this change to an idle handling context.
355 //
356 // However, given we're emulating this behavior, most of this can be ignored
357 // and it's sufficient to simply set the member variable for querying via
358 // IsAutoSleepDisabled().
359
360 LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled);
361
362 IPC::ResponseBuilder rb{ctx, 2};
363 rb.Push(ResultSuccess);
364}
365
366void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
367 LOG_DEBUG(Service_AM, "called.");
368
369 IPC::ResponseBuilder rb{ctx, 3};
370 rb.Push(ResultSuccess);
371 rb.Push(is_auto_sleep_disabled);
372}
373
374void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
375 LOG_DEBUG(Service_AM, "called.");
376
377 // 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
379 // can just always return 0 ticks.
380 IPC::ResponseBuilder rb{ctx, 4};
381 rb.Push(ResultSuccess);
382 rb.Push<u64>(0);
383}
384
385void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
386 LOG_DEBUG(Service_AM, "called.");
387
388 IPC::ResponseBuilder rb{ctx, 2, 1};
389 rb.Push(ResultSuccess);
390 rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
391}
392
393void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) {
394 IPC::RequestParser rp{ctx};
395
396 // 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
398 // stubbed for now.
399 const bool album_image_taken_notification_enabled = rp.Pop<bool>();
400
401 LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}",
402 album_image_taken_notification_enabled);
403
404 IPC::ResponseBuilder rb{ctx, 2};
405 rb.Push(ResultSuccess);
406}
407
408void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
409 IPC::RequestParser rp{ctx};
410
411 const auto report_option = rp.PopEnum<Capture::AlbumReportOption>();
412
413 LOG_INFO(Service_AM, "called, report_option={}", report_option);
414
415 const auto screenshot_service =
416 system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
417 "caps:su");
418
419 if (screenshot_service) {
420 screenshot_service->CaptureAndSaveScreenshot(report_option);
421 }
422
423 IPC::ResponseBuilder rb{ctx, 2};
424 rb.Push(ResultSuccess);
425}
426
427void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) {
428 IPC::RequestParser rp{ctx};
429
430 const auto is_record_volume_muted = rp.Pop<bool>();
431
432 LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted);
433
434 IPC::ResponseBuilder rb{ctx, 2};
435 rb.Push(ResultSuccess);
436}
437
438} // namespace Service::AM
diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h
new file mode 100644
index 000000000..f157bb826
--- /dev/null
+++ b/src/core/hle/service/am/self_controller.h
@@ -0,0 +1,72 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class ISelfController final : public ServiceFramework<ISelfController> {
12public:
13 explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_);
14 ~ISelfController() override;
15
16private:
17 void Exit(HLERequestContext& ctx);
18 void LockExit(HLERequestContext& ctx);
19 void UnlockExit(HLERequestContext& ctx);
20 void EnterFatalSection(HLERequestContext& ctx);
21 void LeaveFatalSection(HLERequestContext& ctx);
22 void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx);
23 void SetScreenShotPermission(HLERequestContext& ctx);
24 void SetOperationModeChangedNotification(HLERequestContext& ctx);
25 void SetPerformanceModeChangedNotification(HLERequestContext& ctx);
26 void SetFocusHandlingMode(HLERequestContext& ctx);
27 void SetRestartMessageEnabled(HLERequestContext& ctx);
28 void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx);
29 void SetAlbumImageOrientation(HLERequestContext& ctx);
30 void IsSystemBufferSharingEnabled(HLERequestContext& ctx);
31 void GetSystemSharedBufferHandle(HLERequestContext& ctx);
32 void GetSystemSharedLayerHandle(HLERequestContext& ctx);
33 void CreateManagedDisplayLayer(HLERequestContext& ctx);
34 void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
35 void SetHandlesRequestToDisplay(HLERequestContext& ctx);
36 void ApproveToDisplay(HLERequestContext& ctx);
37 void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
38 void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
39 void ReportUserIsActive(HLERequestContext& ctx);
40 void SetAutoSleepDisabled(HLERequestContext& ctx);
41 void IsAutoSleepDisabled(HLERequestContext& ctx);
42 void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx);
43 void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx);
44 void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx);
45 void SaveCurrentScreenshot(HLERequestContext& ctx);
46 void SetRecordVolumeMuted(HLERequestContext& ctx);
47
48 Result EnsureBufferSharingEnabled(Kernel::KProcess* process);
49
50 enum class ScreenshotPermission : u32 {
51 Inherit = 0,
52 Enable = 1,
53 Disable = 2,
54 };
55
56 Nvnflinger::Nvnflinger& nvnflinger;
57
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};
71
72} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage.cpp b/src/core/hle/service/am/storage.cpp
new file mode 100644
index 000000000..9a86c867a
--- /dev/null
+++ b/src/core/hle/service/am/storage.cpp
@@ -0,0 +1,60 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/storage.h"
5#include "core/hle/service/am/storage_accessor.h"
6#include "core/hle/service/ipc_helpers.h"
7
8namespace Service::AM {
9
10IStorageImpl::~IStorageImpl() = default;
11
12class StorageDataImpl final : public IStorageImpl {
13public:
14 explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {}
15
16 std::vector<u8>& GetData() override {
17 return buffer;
18 }
19
20 const std::vector<u8>& GetData() const override {
21 return buffer;
22 }
23
24 std::size_t GetSize() const override {
25 return buffer.size();
26 }
27
28private:
29 std::vector<u8> buffer;
30};
31
32IStorage::IStorage(Core::System& system_, std::vector<u8>&& buffer)
33 : ServiceFramework{system_, "IStorage"},
34 impl{std::make_shared<StorageDataImpl>(std::move(buffer))} {
35 Register();
36}
37
38void IStorage::Register() {
39 // clang-format off
40 static const FunctionInfo functions[] = {
41 {0, &IStorage::Open, "Open"},
42 {1, nullptr, "OpenTransferStorage"},
43 };
44 // clang-format on
45
46 RegisterHandlers(functions);
47}
48
49IStorage::~IStorage() = default;
50
51void IStorage::Open(HLERequestContext& ctx) {
52 LOG_DEBUG(Service_AM, "called");
53
54 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
55
56 rb.Push(ResultSuccess);
57 rb.PushIpcInterface<IStorageAccessor>(system, *this);
58}
59
60} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage.h b/src/core/hle/service/am/storage.h
new file mode 100644
index 000000000..d47a8d89f
--- /dev/null
+++ b/src/core/hle/service/am/storage.h
@@ -0,0 +1,42 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IStorageImpl {
11public:
12 virtual ~IStorageImpl();
13 virtual std::vector<u8>& GetData() = 0;
14 virtual const std::vector<u8>& GetData() const = 0;
15 virtual std::size_t GetSize() const = 0;
16};
17
18class IStorage final : public ServiceFramework<IStorage> {
19public:
20 explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
21 ~IStorage() override;
22
23 std::vector<u8>& GetData() {
24 return impl->GetData();
25 }
26
27 const std::vector<u8>& GetData() const {
28 return impl->GetData();
29 }
30
31 std::size_t GetSize() const {
32 return impl->GetSize();
33 }
34
35private:
36 void Register();
37 void Open(HLERequestContext& ctx);
38
39 std::shared_ptr<IStorageImpl> impl;
40};
41
42} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage_accessor.cpp b/src/core/hle/service/am/storage_accessor.cpp
new file mode 100644
index 000000000..7d8c82de3
--- /dev/null
+++ b/src/core/hle/service/am/storage_accessor.cpp
@@ -0,0 +1,82 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/am_results.h"
5#include "core/hle/service/am/storage_accessor.h"
6#include "core/hle/service/ipc_helpers.h"
7
8namespace Service::AM {
9
10IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_)
11 : ServiceFramework{system_, "IStorageAccessor"}, backing{backing_} {
12 // clang-format off
13 static const FunctionInfo functions[] = {
14 {0, &IStorageAccessor::GetSize, "GetSize"},
15 {10, &IStorageAccessor::Write, "Write"},
16 {11, &IStorageAccessor::Read, "Read"},
17 };
18 // clang-format on
19
20 RegisterHandlers(functions);
21}
22
23IStorageAccessor::~IStorageAccessor() = default;
24
25void IStorageAccessor::GetSize(HLERequestContext& ctx) {
26 LOG_DEBUG(Service_AM, "called");
27
28 IPC::ResponseBuilder rb{ctx, 4};
29
30 rb.Push(ResultSuccess);
31 rb.Push(static_cast<u64>(backing.GetSize()));
32}
33
34void IStorageAccessor::Write(HLERequestContext& ctx) {
35 IPC::RequestParser rp{ctx};
36
37 const u64 offset{rp.Pop<u64>()};
38 const auto data{ctx.ReadBuffer()};
39 const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)};
40
41 LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
42
43 if (offset > backing.GetSize()) {
44 LOG_ERROR(Service_AM,
45 "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}",
46 backing.GetSize(), size, offset);
47
48 IPC::ResponseBuilder rb{ctx, 2};
49 rb.Push(AM::ResultInvalidOffset);
50 return;
51 }
52
53 std::memcpy(backing.GetData().data() + offset, data.data(), size);
54
55 IPC::ResponseBuilder rb{ctx, 2};
56 rb.Push(ResultSuccess);
57}
58
59void IStorageAccessor::Read(HLERequestContext& ctx) {
60 IPC::RequestParser rp{ctx};
61
62 const u64 offset{rp.Pop<u64>()};
63 const std::size_t size{std::min<u64>(ctx.GetWriteBufferSize(), backing.GetSize() - offset)};
64
65 LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
66
67 if (offset > backing.GetSize()) {
68 LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}",
69 backing.GetSize(), size, offset);
70
71 IPC::ResponseBuilder rb{ctx, 2};
72 rb.Push(AM::ResultInvalidOffset);
73 return;
74 }
75
76 ctx.WriteBuffer(backing.GetData().data() + offset, size);
77
78 IPC::ResponseBuilder rb{ctx, 2};
79 rb.Push(ResultSuccess);
80}
81
82} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage_accessor.h b/src/core/hle/service/am/storage_accessor.h
new file mode 100644
index 000000000..8648bfc13
--- /dev/null
+++ b/src/core/hle/service/am/storage_accessor.h
@@ -0,0 +1,24 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/storage.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
12public:
13 explicit IStorageAccessor(Core::System& system_, IStorage& backing_);
14 ~IStorageAccessor() override;
15
16private:
17 void GetSize(HLERequestContext& ctx);
18 void Write(HLERequestContext& ctx);
19 void Read(HLERequestContext& ctx);
20
21 IStorage& backing;
22};
23
24} // 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
new file mode 100644
index 000000000..d51a2c8db
--- /dev/null
+++ b/src/core/hle/service/am/system_applet_proxy.cpp
@@ -0,0 +1,135 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applet_common_functions.h"
5#include "core/hle/service/am/application_creator.h"
6#include "core/hle/service/am/audio_controller.h"
7#include "core/hle/service/am/common_state_getter.h"
8#include "core/hle/service/am/debug_functions.h"
9#include "core/hle/service/am/display_controller.h"
10#include "core/hle/service/am/global_state_controller.h"
11#include "core/hle/service/am/home_menu_functions.h"
12#include "core/hle/service/am/library_applet_creator.h"
13#include "core/hle/service/am/library_applet_self_accessor.h"
14#include "core/hle/service/am/process_winding_controller.h"
15#include "core/hle/service/am/self_controller.h"
16#include "core/hle/service/am/system_applet_proxy.h"
17#include "core/hle/service/am/window_controller.h"
18#include "core/hle/service/ipc_helpers.h"
19
20namespace Service::AM {
21
22ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
23 std::shared_ptr<AppletMessageQueue> msg_queue_,
24 Core::System& system_)
25 : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_},
26 msg_queue{std::move(msg_queue_)} {
27 // clang-format off
28 static const FunctionInfo functions[] = {
29 {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
30 {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"},
31 {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"},
32 {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"},
33 {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"},
34 {10, nullptr, "GetProcessWindingController"},
35 {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
36 {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
37 {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
38 {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
39 {23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
40 {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
41 };
42 // clang-format on
43
44 RegisterHandlers(functions);
45}
46
47void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
48 LOG_DEBUG(Service_AM, "called");
49
50 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
51 rb.Push(ResultSuccess);
52 rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
53}
54
55void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) {
56 LOG_DEBUG(Service_AM, "called");
57
58 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
59 rb.Push(ResultSuccess);
60 rb.PushIpcInterface<ISelfController>(system, nvnflinger);
61}
62
63void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) {
64 LOG_DEBUG(Service_AM, "called");
65
66 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
67 rb.Push(ResultSuccess);
68 rb.PushIpcInterface<IWindowController>(system);
69}
70
71void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) {
72 LOG_DEBUG(Service_AM, "called");
73
74 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
75 rb.Push(ResultSuccess);
76 rb.PushIpcInterface<IAudioController>(system);
77}
78
79void ISystemAppletProxy::GetDisplayController(HLERequestContext& ctx) {
80 LOG_DEBUG(Service_AM, "called");
81
82 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
83 rb.Push(ResultSuccess);
84 rb.PushIpcInterface<IDisplayController>(system);
85}
86
87void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
88 LOG_DEBUG(Service_AM, "called");
89
90 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
91 rb.Push(ResultSuccess);
92 rb.PushIpcInterface<ILibraryAppletCreator>(system);
93}
94
95void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
96 LOG_DEBUG(Service_AM, "called");
97
98 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
99 rb.Push(ResultSuccess);
100 rb.PushIpcInterface<IHomeMenuFunctions>(system);
101}
102
103void ISystemAppletProxy::GetGlobalStateController(HLERequestContext& ctx) {
104 LOG_DEBUG(Service_AM, "called");
105
106 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
107 rb.Push(ResultSuccess);
108 rb.PushIpcInterface<IGlobalStateController>(system);
109}
110
111void ISystemAppletProxy::GetApplicationCreator(HLERequestContext& ctx) {
112 LOG_DEBUG(Service_AM, "called");
113
114 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
115 rb.Push(ResultSuccess);
116 rb.PushIpcInterface<IApplicationCreator>(system);
117}
118
119void ISystemAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
120 LOG_DEBUG(Service_AM, "called");
121
122 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
123 rb.Push(ResultSuccess);
124 rb.PushIpcInterface<IAppletCommonFunctions>(system);
125}
126
127void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) {
128 LOG_DEBUG(Service_AM, "called");
129
130 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
131 rb.Push(ResultSuccess);
132 rb.PushIpcInterface<IDebugFunctions>(system);
133}
134
135} // namespace Service::AM
diff --git a/src/core/hle/service/am/system_applet_proxy.h b/src/core/hle/service/am/system_applet_proxy.h
new file mode 100644
index 000000000..b8855b1d6
--- /dev/null
+++ b/src/core/hle/service/am/system_applet_proxy.h
@@ -0,0 +1,34 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/applet_message_queue.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
12public:
13 explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
14 std::shared_ptr<AppletMessageQueue> msg_queue_,
15 Core::System& system_);
16
17private:
18 void GetCommonStateGetter(HLERequestContext& ctx);
19 void GetSelfController(HLERequestContext& ctx);
20 void GetWindowController(HLERequestContext& ctx);
21 void GetAudioController(HLERequestContext& ctx);
22 void GetDisplayController(HLERequestContext& ctx);
23 void GetLibraryAppletCreator(HLERequestContext& ctx);
24 void GetHomeMenuFunctions(HLERequestContext& ctx);
25 void GetGlobalStateController(HLERequestContext& ctx);
26 void GetApplicationCreator(HLERequestContext& ctx);
27 void GetAppletCommonFunctions(HLERequestContext& ctx);
28 void GetDebugFunctions(HLERequestContext& ctx);
29
30 Nvnflinger::Nvnflinger& nvnflinger;
31 std::shared_ptr<AppletMessageQueue> msg_queue;
32};
33
34} // namespace Service::AM
diff --git a/src/core/hle/service/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp
new file mode 100644
index 000000000..f2ba3c134
--- /dev/null
+++ b/src/core/hle/service/am/window_controller.cpp
@@ -0,0 +1,55 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/window_controller.h"
5#include "core/hle/service/ipc_helpers.h"
6
7namespace Service::AM {
8
9IWindowController::IWindowController(Core::System& system_)
10 : ServiceFramework{system_, "IWindowController"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, nullptr, "CreateWindow"},
14 {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
15 {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"},
16 {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
17 {11, nullptr, "ReleaseForegroundRights"},
18 {12, nullptr, "RejectToChangeIntoBackground"},
19 {20, nullptr, "SetAppletWindowVisibility"},
20 {21, nullptr, "SetAppletGpuTimeSlice"},
21 };
22 // clang-format on
23
24 RegisterHandlers(functions);
25}
26
27IWindowController::~IWindowController() = default;
28
29void 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};
35 rb.Push(ResultSuccess);
36 rb.Push<u64>(process_id);
37}
38
39void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
40 const u64 process_id = 0;
41
42 LOG_WARNING(Service_AM, "(STUBBED) called");
43
44 IPC::ResponseBuilder rb{ctx, 4};
45 rb.Push(ResultSuccess);
46 rb.Push<u64>(process_id);
47}
48
49void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) {
50 LOG_WARNING(Service_AM, "(STUBBED) called");
51 IPC::ResponseBuilder rb{ctx, 2};
52 rb.Push(ResultSuccess);
53}
54
55} // namespace Service::AM
diff --git a/src/core/hle/service/am/window_controller.h b/src/core/hle/service/am/window_controller.h
new file mode 100644
index 000000000..07b0e0e17
--- /dev/null
+++ b/src/core/hle/service/am/window_controller.h
@@ -0,0 +1,21 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IWindowController final : public ServiceFramework<IWindowController> {
11public:
12 explicit IWindowController(Core::System& system_);
13 ~IWindowController() override;
14
15private:
16 void GetAppletResourceUserId(HLERequestContext& ctx);
17 void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
18 void AcquireForegroundRights(HLERequestContext& ctx);
19};
20
21} // namespace Service::AM
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 49ec52546..718534ba1 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_message_queue.h"
12#include "core/hle/service/am/applet_oe.h" 13#include "core/hle/service/am/applet_oe.h"
13#include "core/hle/service/sm/sm.h" 14#include "core/hle/service/sm/sm.h"
14#include "hid_core/frontend/emulated_controller.h" 15#include "hid_core/frontend/emulated_controller.h"
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 782bcbb61..f51fd3fa3 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -44,6 +44,7 @@
44#include "core/frontend/applets/software_keyboard.h" 44#include "core/frontend/applets/software_keyboard.h"
45#include "core/hle/service/acc/profile_manager.h" 45#include "core/hle/service/acc/profile_manager.h"
46#include "core/hle/service/am/applet_ae.h" 46#include "core/hle/service/am/applet_ae.h"
47#include "core/hle/service/am/applet_message_queue.h"
47#include "core/hle/service/am/applet_oe.h" 48#include "core/hle/service/am/applet_oe.h"
48#include "core/hle/service/am/applets/applets.h" 49#include "core/hle/service/am/applets/applets.h"
49#include "core/hle/service/set/system_settings_server.h" 50#include "core/hle/service/set/system_settings_server.h"