summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/hle/service/am/am_types.h38
-rw-r--r--src/core/hle/service/am/applet.h4
-rw-r--r--src/core/hle/service/am/application_functions.cpp594
-rw-r--r--src/core/hle/service/am/application_functions.h58
-rw-r--r--src/core/hle/service/am/service/application_functions.cpp465
-rw-r--r--src/core/hle/service/am/service/application_functions.h83
-rw-r--r--src/core/hle/service/am/service/application_proxy.cpp2
8 files changed, 590 insertions, 658 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 236051515..5d3f4cf1d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -425,8 +425,6 @@ add_library(core STATIC
425 hle/service/am/applet_message_queue.h 425 hle/service/am/applet_message_queue.h
426 hle/service/am/application_creator.cpp 426 hle/service/am/application_creator.cpp
427 hle/service/am/application_creator.h 427 hle/service/am/application_creator.h
428 hle/service/am/application_functions.cpp
429 hle/service/am/application_functions.h
430 hle/service/am/common_state_getter.cpp 428 hle/service/am/common_state_getter.cpp
431 hle/service/am/common_state_getter.h 429 hle/service/am/common_state_getter.h
432 hle/service/am/debug_functions.cpp 430 hle/service/am/debug_functions.cpp
@@ -465,6 +463,8 @@ add_library(core STATIC
465 hle/service/am/service/all_system_applet_proxies_service.h 463 hle/service/am/service/all_system_applet_proxies_service.h
466 hle/service/am/service/applet_common_functions.cpp 464 hle/service/am/service/applet_common_functions.cpp
467 hle/service/am/service/applet_common_functions.h 465 hle/service/am/service/applet_common_functions.h
466 hle/service/am/service/application_functions.cpp
467 hle/service/am/service/application_functions.h
468 hle/service/am/service/application_proxy_service.cpp 468 hle/service/am/service/application_proxy_service.cpp
469 hle/service/am/service/application_proxy_service.h 469 hle/service/am/service/application_proxy_service.h
470 hle/service/am/service/application_proxy.cpp 470 hle/service/am/service/application_proxy.cpp
diff --git a/src/core/hle/service/am/am_types.h b/src/core/hle/service/am/am_types.h
index 749081e3d..bf2272c0e 100644
--- a/src/core/hle/service/am/am_types.h
+++ b/src/core/hle/service/am/am_types.h
@@ -18,7 +18,7 @@ enum class AppletType {
18 SystemApplet, 18 SystemApplet,
19}; 19};
20 20
21enum class GameplayRecordingState : u32 { 21enum class GamePlayRecordingState : u32 {
22 Disabled, 22 Disabled,
23 Enabled, 23 Enabled,
24}; 24};
@@ -136,6 +136,11 @@ enum class LibraryAppletMode : u32 {
136 AllForegroundInitiallyHidden = 4, 136 AllForegroundInitiallyHidden = 4,
137}; 137};
138 138
139enum class LaunchParameterKind : u32 {
140 UserChannel = 1,
141 AccountPreselectedUser = 2,
142};
143
139enum class CommonArgumentVersion : u32 { 144enum class CommonArgumentVersion : u32 {
140 Version0, 145 Version0,
141 Version1, 146 Version1,
@@ -152,6 +157,22 @@ enum class ThemeColor : u32 {
152 BasicBlack = 3, 157 BasicBlack = 3,
153}; 158};
154 159
160enum class InputDetectionPolicy : u32 {
161 Unknown0 = 0,
162 Unknown1 = 1,
163};
164
165enum class WindowOriginMode : u32 {
166 LowerLeft = 0,
167 UpperLeft = 1,
168};
169
170enum class ProgramSpecifyKind : u32 {
171 ExecuteProgram = 0,
172 JumpToSubApplicationProgramForDevelopment = 1,
173 RestartProgram = 2,
174};
175
155struct CommonArguments { 176struct CommonArguments {
156 CommonArgumentVersion arguments_version; 177 CommonArgumentVersion arguments_version;
157 CommonArgumentSize size; 178 CommonArgumentSize size;
@@ -175,6 +196,21 @@ struct AppletAttribute {
175}; 196};
176static_assert(sizeof(AppletAttribute) == 0x80, "AppletAttribute has incorrect size."); 197static_assert(sizeof(AppletAttribute) == 0x80, "AppletAttribute has incorrect size.");
177 198
199// This is nn::oe::DisplayVersion
200struct DisplayVersion {
201 std::array<char, 0x10> string;
202};
203static_assert(sizeof(DisplayVersion) == 0x10, "DisplayVersion has incorrect size.");
204
205// This is nn::pdm::ApplicationPlayStatistics
206struct ApplicationPlayStatistics {
207 u64 application_id;
208 u64 play_time_ns;
209 u64 launch_count;
210};
211static_assert(sizeof(ApplicationPlayStatistics) == 0x18,
212 "ApplicationPlayStatistics has incorrect size.");
213
178using AppletResourceUserId = u64; 214using AppletResourceUserId = u64;
179using ProgramId = u64; 215using ProgramId = u64;
180 216
diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h
index b29ecdfed..6c593ab1a 100644
--- a/src/core/hle/service/am/applet.h
+++ b/src/core/hle/service/am/applet.h
@@ -76,8 +76,8 @@ struct Applet {
76 u32 application_core_usage_mode{}; 76 u32 application_core_usage_mode{};
77 77
78 // Application functions 78 // Application functions
79 bool gameplay_recording_supported{}; 79 bool game_play_recording_supported{};
80 GameplayRecordingState gameplay_recording_state{GameplayRecordingState::Disabled}; 80 GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled};
81 bool jit_service_launched{}; 81 bool jit_service_launched{};
82 bool is_running{}; 82 bool is_running{};
83 bool application_crash_report_enabled{}; 83 bool application_crash_report_enabled{};
diff --git a/src/core/hle/service/am/application_functions.cpp b/src/core/hle/service/am/application_functions.cpp
deleted file mode 100644
index 51c5be2d1..000000000
--- a/src/core/hle/service/am/application_functions.cpp
+++ /dev/null
@@ -1,594 +0,0 @@
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/applet.h"
13#include "core/hle/service/am/application_functions.h"
14#include "core/hle/service/am/storage.h"
15#include "core/hle/service/filesystem/filesystem.h"
16#include "core/hle/service/filesystem/save_data_controller.h"
17#include "core/hle/service/ipc_helpers.h"
18#include "core/hle/service/ns/ns.h"
19#include "core/hle/service/sm/sm.h"
20
21namespace Service::AM {
22
23enum class LaunchParameterKind : u32 {
24 UserChannel = 1,
25 AccountPreselectedUser = 2,
26};
27
28IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_)
29 : ServiceFramework{system_, "IApplicationFunctions"}, applet{std::move(applet_)} {
30 // clang-format off
31 static const FunctionInfo functions[] = {
32 {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
33 {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
34 {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
35 {12, nullptr, "CreateApplicationAndRequestToStart"},
36 {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
37 {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
38 {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
39 {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
40 {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
41 {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
42 {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
43 {24, nullptr, "GetLaunchStorageInfoForDebug"},
44 {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
45 {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
46 {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"},
47 {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"},
48 {29, nullptr, "GetCacheStorageMax"},
49 {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
50 {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
51 {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
52 {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
53 {34, nullptr, "SelectApplicationLicense"},
54 {35, nullptr, "GetDeviceSaveDataSizeMax"},
55 {36, nullptr, "GetLimitedApplicationLicense"},
56 {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
57 {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
58 {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
59 {60, nullptr, "SetMediaPlaybackStateForApplication"},
60 {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"},
61 {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
62 {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
63 {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
64 {70, nullptr, "RequestToShutdown"},
65 {71, nullptr, "RequestToReboot"},
66 {72, nullptr, "RequestToSleep"},
67 {80, nullptr, "ExitAndRequestToShowThanksMessage"},
68 {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
69 {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
70 {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
71 {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
72 {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"},
73 {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"},
74 {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"},
75 {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"},
76 {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"},
77 {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
78 {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
79 {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
80 {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
81 {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
82 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
83 {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
84 {151, nullptr, "TryPopFromNotificationStorageChannel"},
85 {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
86 {170, nullptr, "SetHdcpAuthenticationActivated"},
87 {180, nullptr, "GetLaunchRequiredVersion"},
88 {181, nullptr, "UpgradeLaunchRequiredVersion"},
89 {190, nullptr, "SendServerMaintenanceOverlayNotification"},
90 {200, nullptr, "GetLastApplicationExitReason"},
91 {500, nullptr, "StartContinuousRecordingFlushForDebug"},
92 {1000, nullptr, "CreateMovieMaker"},
93 {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"},
94 };
95 // clang-format on
96
97 RegisterHandlers(functions);
98}
99
100IApplicationFunctions::~IApplicationFunctions() = default;
101
102void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
103 LOG_WARNING(Service_AM, "(STUBBED) called");
104
105 std::scoped_lock lk{applet->lock};
106 applet->application_crash_report_enabled = true;
107
108 IPC::ResponseBuilder rb{ctx, 2};
109 rb.Push(ResultSuccess);
110}
111
112void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) {
113 LOG_WARNING(Service_AM, "(STUBBED) called");
114
115 IPC::ResponseBuilder rb{ctx, 2};
116 rb.Push(ResultSuccess);
117}
118
119void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) {
120 LOG_WARNING(Service_AM, "(STUBBED) called");
121
122 IPC::ResponseBuilder rb{ctx, 2};
123 rb.Push(ResultSuccess);
124}
125
126void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) {
127 IPC::RequestParser rp{ctx};
128 const auto is_visible = rp.Pop<bool>();
129
130 LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
131
132 IPC::ResponseBuilder rb{ctx, 2};
133 rb.Push(ResultSuccess);
134}
135
136void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
137 LOG_WARNING(Service_AM, "(STUBBED) called");
138
139 std::scoped_lock lk{applet->lock};
140 applet->home_button_long_pressed_blocked = true;
141 applet->home_button_short_pressed_blocked = true;
142
143 IPC::ResponseBuilder rb{ctx, 2};
144 rb.Push(ResultSuccess);
145}
146
147void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
148 LOG_WARNING(Service_AM, "(STUBBED) called");
149
150 std::scoped_lock lk{applet->lock};
151 applet->home_button_long_pressed_blocked = false;
152 applet->home_button_short_pressed_blocked = false;
153
154 IPC::ResponseBuilder rb{ctx, 2};
155 rb.Push(ResultSuccess);
156}
157
158void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
159 LOG_WARNING(Service_AM, "(STUBBED) called");
160
161 std::scoped_lock lk{applet->lock};
162 applet->home_button_long_pressed_blocked = true;
163 applet->home_button_short_pressed_blocked = true;
164 applet->home_button_double_click_enabled = true;
165
166 IPC::ResponseBuilder rb{ctx, 2};
167 rb.Push(ResultSuccess);
168}
169
170void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
171 LOG_WARNING(Service_AM, "(STUBBED) called");
172
173 std::scoped_lock lk{applet->lock};
174 applet->home_button_long_pressed_blocked = false;
175 applet->home_button_short_pressed_blocked = false;
176 applet->home_button_double_click_enabled = false;
177
178 IPC::ResponseBuilder rb{ctx, 2};
179 rb.Push(ResultSuccess);
180}
181
182void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
183 IPC::RequestParser rp{ctx};
184 const auto kind = rp.PopEnum<LaunchParameterKind>();
185
186 LOG_INFO(Service_AM, "called, kind={:08X}", kind);
187
188 std::scoped_lock lk{applet->lock};
189
190 auto& channel = kind == LaunchParameterKind::UserChannel
191 ? applet->user_channel_launch_parameter
192 : applet->preselected_user_launch_parameter;
193
194 if (channel.empty()) {
195 LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", kind);
196 IPC::ResponseBuilder rb{ctx, 2};
197 rb.Push(AM::ResultNoDataInChannel);
198 return;
199 }
200
201 auto data = channel.back();
202 channel.pop_back();
203
204 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
205 rb.Push(ResultSuccess);
206 rb.PushIpcInterface<IStorage>(system, std::move(data));
207}
208
209void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
210 LOG_WARNING(Service_AM, "(STUBBED) called");
211
212 IPC::ResponseBuilder rb{ctx, 2};
213 rb.Push(ResultSuccess);
214}
215
216void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
217 IPC::RequestParser rp{ctx};
218 u128 user_id = rp.PopRaw<u128>();
219
220 LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
221
222 FileSys::SaveDataAttribute attribute{};
223 attribute.title_id = applet->program_id;
224 attribute.user_id = user_id;
225 attribute.type = FileSys::SaveDataType::SaveData;
226
227 FileSys::VirtualDir save_data{};
228 const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
229 &save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
230
231 IPC::ResponseBuilder rb{ctx, 4};
232 rb.Push(res);
233 rb.Push<u64>(0);
234}
235
236void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) {
237 // Takes an input u32 Result, no output.
238 // For example, in some cases official apps use this with error 0x2A2 then
239 // uses svcBreak.
240
241 IPC::RequestParser rp{ctx};
242 u32 result = rp.Pop<u32>();
243 LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
244
245 std::scoped_lock lk{applet->lock};
246 applet->terminate_result = Result(result);
247
248 IPC::ResponseBuilder rb{ctx, 2};
249 rb.Push(ResultSuccess);
250}
251
252void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) {
253 LOG_DEBUG(Service_AM, "called");
254
255 std::array<u8, 0x10> version_string{};
256
257 const auto res = [this] {
258 const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
259 system.GetContentProvider()};
260 auto metadata = pm.GetControlMetadata();
261 if (metadata.first != nullptr) {
262 return metadata;
263 }
264
265 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
266 system.GetFileSystemController(),
267 system.GetContentProvider()};
268 return pm_update.GetControlMetadata();
269 }();
270
271 if (res.first != nullptr) {
272 const auto& version = res.first->GetVersionString();
273 std::copy(version.begin(), version.end(), version_string.begin());
274 } else {
275 static constexpr char default_version[]{"1.0.0"};
276 std::memcpy(version_string.data(), default_version, sizeof(default_version));
277 }
278
279 IPC::ResponseBuilder rb{ctx, 6};
280 rb.Push(ResultSuccess);
281 rb.PushRaw(version_string);
282}
283
284void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
285 // TODO(bunnei): This should be configurable
286 LOG_DEBUG(Service_AM, "called");
287
288 // Get supported languages from NACP, if possible
289 // Default to 0 (all languages supported)
290 u32 supported_languages = 0;
291
292 const auto res = [this] {
293 const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
294 system.GetContentProvider()};
295 auto metadata = pm.GetControlMetadata();
296 if (metadata.first != nullptr) {
297 return metadata;
298 }
299
300 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
301 system.GetFileSystemController(),
302 system.GetContentProvider()};
303 return pm_update.GetControlMetadata();
304 }();
305
306 if (res.first != nullptr) {
307 supported_languages = res.first->GetSupportedLanguages();
308 }
309
310 // Call IApplicationManagerInterface implementation.
311 auto& service_manager = system.ServiceManager();
312 auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
313 auto app_man = ns_am2->GetApplicationManagerInterface();
314
315 // Get desired application language
316 u8 desired_language{};
317 const auto res_lang =
318 app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
319 if (res_lang != ResultSuccess) {
320 IPC::ResponseBuilder rb{ctx, 2};
321 rb.Push(res_lang);
322 return;
323 }
324
325 // Convert to settings language code.
326 u64 language_code{};
327 const auto res_code =
328 app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
329 if (res_code != ResultSuccess) {
330 IPC::ResponseBuilder rb{ctx, 2};
331 rb.Push(res_code);
332 return;
333 }
334
335 LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
336
337 IPC::ResponseBuilder rb{ctx, 4};
338 rb.Push(ResultSuccess);
339 rb.Push(language_code);
340}
341
342void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
343 LOG_WARNING(Service_AM, "(STUBBED) called");
344
345 IPC::ResponseBuilder rb{ctx, 3};
346 rb.Push(ResultSuccess);
347 rb.Push(applet->gameplay_recording_supported);
348}
349
350void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
351 LOG_WARNING(Service_AM, "(STUBBED) called");
352
353 IPC::ResponseBuilder rb{ctx, 2};
354 rb.Push(ResultSuccess);
355}
356
357void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
358 LOG_WARNING(Service_AM, "(STUBBED) called");
359
360 IPC::RequestParser rp{ctx};
361
362 std::scoped_lock lk{applet->lock};
363 applet->gameplay_recording_state = rp.PopRaw<GameplayRecordingState>();
364
365 IPC::ResponseBuilder rb{ctx, 2};
366 rb.Push(ResultSuccess);
367}
368
369void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
370 LOG_WARNING(Service_AM, "(STUBBED) called");
371
372 std::scoped_lock lk{applet->lock};
373 applet->is_running = true;
374
375 IPC::ResponseBuilder rb{ctx, 3};
376 rb.Push(ResultSuccess);
377 rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
378}
379
380void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) {
381 LOG_WARNING(Service_AM, "(STUBBED) called");
382
383 IPC::ResponseBuilder rb{ctx, 6};
384 rb.Push(ResultSuccess);
385
386 // Returns a 128-bit UUID
387 rb.Push<u64>(0);
388 rb.Push<u64>(0);
389}
390
391void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
392 struct Parameters {
393 FileSys::SaveDataType type;
394 u128 user_id;
395 u64 new_normal_size;
396 u64 new_journal_size;
397 };
398 static_assert(sizeof(Parameters) == 40);
399
400 IPC::RequestParser rp{ctx};
401 const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>();
402
403 LOG_DEBUG(Service_AM,
404 "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
405 "new_journal={:016X}",
406 static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
407
408 system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
409 type, applet->program_id, user_id, {new_normal_size, new_journal_size});
410
411 IPC::ResponseBuilder rb{ctx, 4};
412 rb.Push(ResultSuccess);
413
414 // The following value is used upon failure to help the system recover.
415 // Since we always succeed, this should be 0.
416 rb.Push<u64>(0);
417}
418
419void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
420 struct Parameters {
421 FileSys::SaveDataType type;
422 u128 user_id;
423 };
424 static_assert(sizeof(Parameters) == 24);
425
426 IPC::RequestParser rp{ctx};
427 const auto [type, user_id] = rp.PopRaw<Parameters>();
428
429 LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1],
430 user_id[0]);
431
432 const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
433 type, applet->program_id, user_id);
434
435 IPC::ResponseBuilder rb{ctx, 6};
436 rb.Push(ResultSuccess);
437 rb.Push(size.normal);
438 rb.Push(size.journal);
439}
440
441void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) {
442 struct InputParameters {
443 u16 index;
444 s64 size;
445 s64 journal_size;
446 };
447 static_assert(sizeof(InputParameters) == 24);
448
449 struct OutputParameters {
450 u32 storage_target;
451 u64 required_size;
452 };
453 static_assert(sizeof(OutputParameters) == 16);
454
455 IPC::RequestParser rp{ctx};
456 const auto params = rp.PopRaw<InputParameters>();
457
458 LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}",
459 params.index, params.size, params.journal_size);
460
461 const OutputParameters resp{
462 .storage_target = 1,
463 .required_size = 0,
464 };
465
466 IPC::ResponseBuilder rb{ctx, 6};
467 rb.Push(ResultSuccess);
468 rb.PushRaw(resp);
469}
470
471void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) {
472 LOG_WARNING(Service_AM, "(STUBBED) called");
473
474 constexpr u64 size_max_normal = 0xFFFFFFF;
475 constexpr u64 size_max_journal = 0xFFFFFFF;
476
477 IPC::ResponseBuilder rb{ctx, 6};
478 rb.Push(ResultSuccess);
479 rb.Push(size_max_normal);
480 rb.Push(size_max_journal);
481}
482
483void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) {
484 LOG_WARNING(Service_AM, "(STUBBED) called");
485
486 IPC::ResponseBuilder rb{ctx, 3};
487 rb.Push(ResultSuccess);
488 rb.Push<u32>(0);
489}
490
491void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) {
492 LOG_WARNING(Service_AM, "(STUBBED) called");
493
494 IPC::ResponseBuilder rb{ctx, 3};
495 rb.Push(ResultSuccess);
496 rb.Push<u32>(0);
497}
498
499void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
500 LOG_WARNING(Service_AM, "(STUBBED) called");
501
502 IPC::RequestParser rp{ctx};
503 [[maybe_unused]] const auto unk_1 = rp.Pop<u32>();
504 [[maybe_unused]] const auto unk_2 = rp.Pop<u32>();
505 const auto program_index = rp.Pop<u64>();
506
507 IPC::ResponseBuilder rb{ctx, 2};
508 rb.Push(ResultSuccess);
509
510 // Swap user channel ownership into the system so that it will be preserved
511 system.GetUserChannel().swap(applet->user_channel_launch_parameter);
512 system.ExecuteProgram(program_index);
513}
514
515void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
516 LOG_DEBUG(Service_AM, "called");
517
518 applet->user_channel_launch_parameter.clear();
519
520 IPC::ResponseBuilder rb{ctx, 2};
521 rb.Push(ResultSuccess);
522}
523
524void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
525 LOG_DEBUG(Service_AM, "called");
526
527 IPC::RequestParser rp{ctx};
528 const auto storage = rp.PopIpcInterface<IStorage>().lock();
529 if (storage) {
530 applet->user_channel_launch_parameter.push_back(storage->GetData());
531 }
532
533 IPC::ResponseBuilder rb{ctx, 2};
534 rb.Push(ResultSuccess);
535}
536
537void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) {
538 LOG_WARNING(Service_AM, "(STUBBED) called");
539
540 IPC::ResponseBuilder rb{ctx, 3};
541 rb.Push(ResultSuccess);
542 rb.Push<s32>(applet->previous_program_index);
543}
544
545void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
546 LOG_WARNING(Service_AM, "(STUBBED) called");
547
548 IPC::ResponseBuilder rb{ctx, 2, 1};
549 rb.Push(ResultSuccess);
550 rb.PushCopyObjects(applet->gpu_error_detected_event.GetHandle());
551}
552
553void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
554 LOG_DEBUG(Service_AM, "called");
555
556 IPC::ResponseBuilder rb{ctx, 2, 1};
557 rb.Push(ResultSuccess);
558 rb.PushCopyObjects(applet->friend_invitation_storage_channel_event.GetHandle());
559}
560
561void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
562 LOG_DEBUG(Service_AM, "(STUBBED) called");
563
564 IPC::ResponseBuilder rb{ctx, 2};
565 rb.Push(AM::ResultNoDataInChannel);
566}
567
568void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) {
569 LOG_DEBUG(Service_AM, "called");
570
571 IPC::ResponseBuilder rb{ctx, 2, 1};
572 rb.Push(ResultSuccess);
573 rb.PushCopyObjects(applet->notification_storage_channel_event.GetHandle());
574}
575
576void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
577 LOG_DEBUG(Service_AM, "called");
578
579 IPC::ResponseBuilder rb{ctx, 2, 1};
580 rb.Push(ResultSuccess);
581 rb.PushCopyObjects(applet->health_warning_disappeared_system_event.GetHandle());
582}
583
584void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
585 LOG_WARNING(Service_AM, "(STUBBED) called");
586
587 std::scoped_lock lk{applet->lock};
588 applet->jit_service_launched = true;
589
590 IPC::ResponseBuilder rb{ctx, 2};
591 rb.Push(ResultSuccess);
592}
593
594} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_functions.h b/src/core/hle/service/am/application_functions.h
deleted file mode 100644
index 55eb21d39..000000000
--- a/src/core/hle/service/am/application_functions.h
+++ /dev/null
@@ -1,58 +0,0 @@
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
11struct Applet;
12
13class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
14public:
15 explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
16 ~IApplicationFunctions() override;
17
18private:
19 void PopLaunchParameter(HLERequestContext& ctx);
20 void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx);
21 void EnsureSaveData(HLERequestContext& ctx);
22 void SetTerminateResult(HLERequestContext& ctx);
23 void GetDisplayVersion(HLERequestContext& ctx);
24 void GetDesiredLanguage(HLERequestContext& ctx);
25 void IsGamePlayRecordingSupported(HLERequestContext& ctx);
26 void InitializeGamePlayRecording(HLERequestContext& ctx);
27 void SetGamePlayRecordingState(HLERequestContext& ctx);
28 void NotifyRunning(HLERequestContext& ctx);
29 void GetPseudoDeviceId(HLERequestContext& ctx);
30 void ExtendSaveData(HLERequestContext& ctx);
31 void GetSaveDataSize(HLERequestContext& ctx);
32 void CreateCacheStorage(HLERequestContext& ctx);
33 void GetSaveDataSizeMax(HLERequestContext& ctx);
34 void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
35 void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
36 void BeginBlockingHomeButton(HLERequestContext& ctx);
37 void EndBlockingHomeButton(HLERequestContext& ctx);
38 void EnableApplicationCrashReport(HLERequestContext& ctx);
39 void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx);
40 void SetApplicationCopyrightImage(HLERequestContext& ctx);
41 void SetApplicationCopyrightVisibility(HLERequestContext& ctx);
42 void QueryApplicationPlayStatistics(HLERequestContext& ctx);
43 void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx);
44 void ExecuteProgram(HLERequestContext& ctx);
45 void ClearUserChannel(HLERequestContext& ctx);
46 void UnpopToUserChannel(HLERequestContext& ctx);
47 void GetPreviousProgramIndex(HLERequestContext& ctx);
48 void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx);
49 void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx);
50 void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx);
51 void GetNotificationStorageChannelEvent(HLERequestContext& ctx);
52 void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
53 void PrepareForJit(HLERequestContext& ctx);
54
55 const std::shared_ptr<Applet> applet;
56};
57
58} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp
new file mode 100644
index 000000000..346ab42ab
--- /dev/null
+++ b/src/core/hle/service/am/service/application_functions.cpp
@@ -0,0 +1,465 @@
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/kernel/k_transfer_memory.h"
11#include "core/hle/service/am/am_results.h"
12#include "core/hle/service/am/applet.h"
13#include "core/hle/service/am/service/application_functions.h"
14#include "core/hle/service/am/storage.h"
15#include "core/hle/service/cmif_serialization.h"
16#include "core/hle/service/filesystem/filesystem.h"
17#include "core/hle/service/filesystem/save_data_controller.h"
18#include "core/hle/service/ns/ns.h"
19#include "core/hle/service/sm/sm.h"
20
21namespace Service::AM {
22
23IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
24 : ServiceFramework{system_, "IApplicationFunctions"}, m_applet{std::move(applet)} {
25 // clang-format off
26 static const FunctionInfo functions[] = {
27 {1, D<&IApplicationFunctions::PopLaunchParameter>, "PopLaunchParameter"},
28 {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
29 {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
30 {12, nullptr, "CreateApplicationAndRequestToStart"},
31 {13, nullptr, "CreateApplicationAndRequestToStartForQuest"},
32 {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
33 {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
34 {20, D<&IApplicationFunctions::EnsureSaveData>, "EnsureSaveData"},
35 {21, D<&IApplicationFunctions::GetDesiredLanguage>, "GetDesiredLanguage"},
36 {22, D<&IApplicationFunctions::SetTerminateResult>, "SetTerminateResult"},
37 {23, D<&IApplicationFunctions::GetDisplayVersion>, "GetDisplayVersion"},
38 {24, nullptr, "GetLaunchStorageInfoForDebug"},
39 {25, D<&IApplicationFunctions::ExtendSaveData>, "ExtendSaveData"},
40 {26, D<&IApplicationFunctions::GetSaveDataSize>, "GetSaveDataSize"},
41 {27, D<&IApplicationFunctions::CreateCacheStorage>, "CreateCacheStorage"},
42 {28, D<&IApplicationFunctions::GetSaveDataSizeMax>, "GetSaveDataSizeMax"},
43 {29, nullptr, "GetCacheStorageMax"},
44 {30, D<&IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed>, "BeginBlockingHomeButtonShortAndLongPressed"},
45 {31, D<&IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed>, "EndBlockingHomeButtonShortAndLongPressed"},
46 {32, D<&IApplicationFunctions::BeginBlockingHomeButton>, "BeginBlockingHomeButton"},
47 {33, D<&IApplicationFunctions::EndBlockingHomeButton>, "EndBlockingHomeButton"},
48 {34, nullptr, "SelectApplicationLicense"},
49 {35, nullptr, "GetDeviceSaveDataSizeMax"},
50 {36, nullptr, "GetLimitedApplicationLicense"},
51 {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
52 {40, D<&IApplicationFunctions::NotifyRunning>, "NotifyRunning"},
53 {50, D<&IApplicationFunctions::GetPseudoDeviceId>, "GetPseudoDeviceId"},
54 {60, nullptr, "SetMediaPlaybackStateForApplication"},
55 {65, D<&IApplicationFunctions::IsGamePlayRecordingSupported>, "IsGamePlayRecordingSupported"},
56 {66, D<&IApplicationFunctions::InitializeGamePlayRecording>, "InitializeGamePlayRecording"},
57 {67, D<&IApplicationFunctions::SetGamePlayRecordingState>, "SetGamePlayRecordingState"},
58 {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
59 {70, nullptr, "RequestToShutdown"},
60 {71, nullptr, "RequestToReboot"},
61 {72, nullptr, "RequestToSleep"},
62 {80, nullptr, "ExitAndRequestToShowThanksMessage"},
63 {90, D<&IApplicationFunctions::EnableApplicationCrashReport>, "EnableApplicationCrashReport"},
64 {100, D<&IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer>, "InitializeApplicationCopyrightFrameBuffer"},
65 {101, D<&IApplicationFunctions::SetApplicationCopyrightImage>, "SetApplicationCopyrightImage"},
66 {102, D<&IApplicationFunctions::SetApplicationCopyrightVisibility>, "SetApplicationCopyrightVisibility"},
67 {110, D<&IApplicationFunctions::QueryApplicationPlayStatistics>, "QueryApplicationPlayStatistics"},
68 {111, D<&IApplicationFunctions::QueryApplicationPlayStatisticsByUid>, "QueryApplicationPlayStatisticsByUid"},
69 {120, D<&IApplicationFunctions::ExecuteProgram>, "ExecuteProgram"},
70 {121, D<&IApplicationFunctions::ClearUserChannel>, "ClearUserChannel"},
71 {122, D<&IApplicationFunctions::UnpopToUserChannel>, "UnpopToUserChannel"},
72 {123, D<&IApplicationFunctions::GetPreviousProgramIndex>, "GetPreviousProgramIndex"},
73 {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
74 {130, D<&IApplicationFunctions::GetGpuErrorDetectedSystemEvent>, "GetGpuErrorDetectedSystemEvent"},
75 {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
76 {140, D<&IApplicationFunctions::GetFriendInvitationStorageChannelEvent>, "GetFriendInvitationStorageChannelEvent"},
77 {141, D<&IApplicationFunctions::TryPopFromFriendInvitationStorageChannel>, "TryPopFromFriendInvitationStorageChannel"},
78 {150, D<&IApplicationFunctions::GetNotificationStorageChannelEvent>, "GetNotificationStorageChannelEvent"},
79 {151, nullptr, "TryPopFromNotificationStorageChannel"},
80 {160, D<&IApplicationFunctions::GetHealthWarningDisappearedSystemEvent>, "GetHealthWarningDisappearedSystemEvent"},
81 {170, nullptr, "SetHdcpAuthenticationActivated"},
82 {180, nullptr, "GetLaunchRequiredVersion"},
83 {181, nullptr, "UpgradeLaunchRequiredVersion"},
84 {190, nullptr, "SendServerMaintenanceOverlayNotification"},
85 {200, nullptr, "GetLastApplicationExitReason"},
86 {500, nullptr, "StartContinuousRecordingFlushForDebug"},
87 {1000, nullptr, "CreateMovieMaker"},
88 {1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"},
89 };
90 // clang-format on
91
92 RegisterHandlers(functions);
93}
94
95IApplicationFunctions::~IApplicationFunctions() = default;
96
97Result IApplicationFunctions::PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage,
98 LaunchParameterKind launch_parameter_kind) {
99 LOG_INFO(Service_AM, "called, kind={}", launch_parameter_kind);
100
101 std::scoped_lock lk{m_applet->lock};
102
103 auto& channel = launch_parameter_kind == LaunchParameterKind::UserChannel
104 ? m_applet->user_channel_launch_parameter
105 : m_applet->preselected_user_launch_parameter;
106
107 if (channel.empty()) {
108 LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!",
109 launch_parameter_kind);
110 R_THROW(AM::ResultNoDataInChannel);
111 }
112
113 auto data = channel.back();
114 channel.pop_back();
115
116 *out_storage = std::make_shared<IStorage>(system, std::move(data));
117 R_SUCCEED();
118}
119
120Result IApplicationFunctions::EnsureSaveData(Out<u64> out_size, Common::UUID user_id) {
121 LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString());
122
123 FileSys::SaveDataAttribute attribute{};
124 attribute.title_id = m_applet->program_id;
125 attribute.user_id = user_id.AsU128();
126 attribute.type = FileSys::SaveDataType::SaveData;
127
128 FileSys::VirtualDir save_data{};
129 R_TRY(system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
130 &save_data, FileSys::SaveDataSpaceId::NandUser, attribute));
131
132 *out_size = 0;
133 R_SUCCEED();
134}
135
136Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
137 // FIXME: all of this stuff belongs to ns
138 // TODO(bunnei): This should be configurable
139 LOG_DEBUG(Service_AM, "called");
140
141 // Get supported languages from NACP, if possible
142 // Default to 0 (all languages supported)
143 u32 supported_languages = 0;
144
145 const auto res = [this] {
146 const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
147 system.GetContentProvider()};
148 auto metadata = pm.GetControlMetadata();
149 if (metadata.first != nullptr) {
150 return metadata;
151 }
152
153 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
154 system.GetFileSystemController(),
155 system.GetContentProvider()};
156 return pm_update.GetControlMetadata();
157 }();
158
159 if (res.first != nullptr) {
160 supported_languages = res.first->GetSupportedLanguages();
161 }
162
163 // Call IApplicationManagerInterface implementation.
164 auto& service_manager = system.ServiceManager();
165 auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
166 auto app_man = ns_am2->GetApplicationManagerInterface();
167
168 // Get desired application language
169 u8 desired_language{};
170 R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
171
172 // Convert to settings language code.
173 R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(out_language_code, desired_language));
174
175 LOG_DEBUG(Service_AM, "got desired_language={:016X}", *out_language_code);
176 R_SUCCEED();
177}
178
179Result IApplicationFunctions::SetTerminateResult(Result terminate_result) {
180 LOG_INFO(Service_AM, "(STUBBED) called, result={:#x} ({}-{})", terminate_result.GetInnerValue(),
181 static_cast<u32>(terminate_result.GetModule()) + 2000,
182 terminate_result.GetDescription());
183
184 std::scoped_lock lk{m_applet->lock};
185 m_applet->terminate_result = terminate_result;
186
187 R_SUCCEED();
188}
189
190Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) {
191 LOG_DEBUG(Service_AM, "called");
192
193 const auto res = [this] {
194 const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
195 system.GetContentProvider()};
196 auto metadata = pm.GetControlMetadata();
197 if (metadata.first != nullptr) {
198 return metadata;
199 }
200
201 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
202 system.GetFileSystemController(),
203 system.GetContentProvider()};
204 return pm_update.GetControlMetadata();
205 }();
206
207 if (res.first != nullptr) {
208 const auto& version = res.first->GetVersionString();
209 std::memcpy(out_display_version->string.data(), version.data(),
210 std::min(version.size(), out_display_version->string.size()));
211 } else {
212 static constexpr char default_version[]{"1.0.0"};
213 std::memcpy(out_display_version->string.data(), default_version, sizeof(default_version));
214 }
215
216 out_display_version->string[out_display_version->string.size() - 1] = '\0';
217 R_SUCCEED();
218}
219
220Result IApplicationFunctions::ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type,
221 Common::UUID user_id, u64 normal_size,
222 u64 journal_size) {
223 LOG_DEBUG(Service_AM, "called with type={} user_id={} normal={:#x} journal={:#x}",
224 static_cast<u8>(type), user_id.FormattedString(), normal_size, journal_size);
225
226 system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
227 type, m_applet->program_id, user_id.AsU128(), {normal_size, journal_size});
228
229 // The following value is used to indicate the amount of space remaining on failure
230 // due to running out of space. Since we always succeed, this should be 0.
231 *out_required_size = 0;
232
233 R_SUCCEED();
234}
235
236Result IApplicationFunctions::GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size,
237 FileSys::SaveDataType type, Common::UUID user_id) {
238 LOG_DEBUG(Service_AM, "called with type={} user_id={}", type, user_id.FormattedString());
239
240 const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
241 type, m_applet->program_id, user_id.AsU128());
242
243 *out_normal_size = size.normal;
244 *out_journal_size = size.journal;
245 R_SUCCEED();
246}
247
248Result IApplicationFunctions::CreateCacheStorage(Out<u32> out_target_media,
249 Out<u64> out_required_size, u16 index,
250 u64 normal_size, u64 journal_size) {
251 LOG_WARNING(Service_AM, "(STUBBED) called with index={} size={:#x} journal_size={:#x}", index,
252 normal_size, journal_size);
253
254 *out_target_media = 1; // Nand
255 *out_required_size = 0;
256
257 R_SUCCEED();
258}
259
260Result IApplicationFunctions::GetSaveDataSizeMax(Out<u64> out_max_normal_size,
261 Out<u64> out_max_journal_size) {
262 LOG_WARNING(Service_AM, "(STUBBED) called");
263
264 *out_max_normal_size = 0xFFFFFFF;
265 *out_max_journal_size = 0xFFFFFFF;
266
267 R_SUCCEED();
268}
269
270Result IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(s64 unused) {
271 LOG_WARNING(Service_AM, "(STUBBED) called");
272
273 std::scoped_lock lk{m_applet->lock};
274 m_applet->home_button_long_pressed_blocked = true;
275 m_applet->home_button_short_pressed_blocked = true;
276
277 R_SUCCEED();
278}
279
280Result IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed() {
281 LOG_WARNING(Service_AM, "(STUBBED) called");
282
283 std::scoped_lock lk{m_applet->lock};
284 m_applet->home_button_long_pressed_blocked = false;
285 m_applet->home_button_short_pressed_blocked = false;
286
287 R_SUCCEED();
288}
289
290Result IApplicationFunctions::BeginBlockingHomeButton(s64 timeout_ns) {
291 LOG_WARNING(Service_AM, "(STUBBED) called, timeout_ns={}", timeout_ns);
292
293 std::scoped_lock lk{m_applet->lock};
294 m_applet->home_button_long_pressed_blocked = true;
295 m_applet->home_button_short_pressed_blocked = true;
296 m_applet->home_button_double_click_enabled = true;
297
298 R_SUCCEED();
299}
300
301Result IApplicationFunctions::EndBlockingHomeButton() {
302 LOG_WARNING(Service_AM, "(STUBBED) called");
303
304 std::scoped_lock lk{m_applet->lock};
305 m_applet->home_button_long_pressed_blocked = false;
306 m_applet->home_button_short_pressed_blocked = false;
307 m_applet->home_button_double_click_enabled = false;
308
309 R_SUCCEED();
310}
311
312Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) {
313 LOG_WARNING(Service_AM, "(STUBBED) called");
314 *out_became_running = true;
315 R_SUCCEED();
316}
317
318Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) {
319 LOG_WARNING(Service_AM, "(STUBBED) called");
320 *out_pseudo_device_id = {};
321 R_SUCCEED();
322}
323
324Result IApplicationFunctions::IsGamePlayRecordingSupported(
325 Out<bool> out_is_game_play_recording_supported) {
326 LOG_WARNING(Service_AM, "(STUBBED) called");
327 *out_is_game_play_recording_supported = m_applet->game_play_recording_supported;
328 R_SUCCEED();
329}
330
331Result IApplicationFunctions::InitializeGamePlayRecording(
332 u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
333 LOG_WARNING(Service_AM, "(STUBBED) called");
334 R_SUCCEED();
335}
336
337Result IApplicationFunctions::SetGamePlayRecordingState(
338 GamePlayRecordingState game_play_recording_state) {
339 LOG_WARNING(Service_AM, "(STUBBED) called");
340
341 std::scoped_lock lk{m_applet->lock};
342 m_applet->game_play_recording_state = game_play_recording_state;
343
344 R_SUCCEED();
345}
346
347Result IApplicationFunctions::EnableApplicationCrashReport(bool enabled) {
348 LOG_WARNING(Service_AM, "(STUBBED) called");
349
350 std::scoped_lock lk{m_applet->lock};
351 m_applet->application_crash_report_enabled = enabled;
352
353 R_SUCCEED();
354}
355
356Result IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(
357 s32 width, s32 height, u64 transfer_memory_size,
358 InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
359 LOG_WARNING(Service_AM, "(STUBBED) called");
360 R_SUCCEED();
361}
362
363Result IApplicationFunctions::SetApplicationCopyrightImage(
364 s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode,
365 InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data) {
366 LOG_WARNING(Service_AM, "(STUBBED) called");
367 R_SUCCEED();
368}
369
370Result IApplicationFunctions::SetApplicationCopyrightVisibility(bool visible) {
371 LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", visible);
372 R_SUCCEED();
373}
374
375Result IApplicationFunctions::QueryApplicationPlayStatistics(
376 Out<s32> out_entries,
377 OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
378 InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
379 LOG_WARNING(Service_AM, "(STUBBED) called");
380 *out_entries = 0;
381 R_SUCCEED();
382}
383
384Result IApplicationFunctions::QueryApplicationPlayStatisticsByUid(
385 Out<s32> out_entries,
386 OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
387 Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
388 LOG_WARNING(Service_AM, "(STUBBED) called");
389 *out_entries = 0;
390 R_SUCCEED();
391}
392
393Result IApplicationFunctions::ExecuteProgram(ProgramSpecifyKind kind, u64 value) {
394 LOG_WARNING(Service_AM, "(STUBBED) called, kind={}, value={}", kind, value);
395 ASSERT(kind == ProgramSpecifyKind::ExecuteProgram ||
396 kind == ProgramSpecifyKind::RestartProgram);
397
398 // Copy user channel ownership into the system so that it will be preserved
399 system.GetUserChannel() = m_applet->user_channel_launch_parameter;
400 system.ExecuteProgram(value);
401 R_SUCCEED();
402}
403
404Result IApplicationFunctions::ClearUserChannel() {
405 LOG_DEBUG(Service_AM, "called");
406 m_applet->user_channel_launch_parameter.clear();
407 R_SUCCEED();
408}
409
410Result IApplicationFunctions::UnpopToUserChannel(SharedPointer<IStorage> storage) {
411 LOG_DEBUG(Service_AM, "called");
412 m_applet->user_channel_launch_parameter.push_back(storage->GetData());
413 R_SUCCEED();
414}
415
416Result IApplicationFunctions::GetPreviousProgramIndex(Out<s32> out_previous_program_index) {
417 LOG_WARNING(Service_AM, "(STUBBED) called");
418 *out_previous_program_index = m_applet->previous_program_index;
419 R_SUCCEED();
420}
421
422Result IApplicationFunctions::GetGpuErrorDetectedSystemEvent(
423 OutCopyHandle<Kernel::KReadableEvent> out_event) {
424 LOG_WARNING(Service_AM, "(STUBBED) called");
425 *out_event = m_applet->gpu_error_detected_event.GetHandle();
426 R_SUCCEED();
427}
428
429Result IApplicationFunctions::GetFriendInvitationStorageChannelEvent(
430 OutCopyHandle<Kernel::KReadableEvent> out_event) {
431 LOG_DEBUG(Service_AM, "called");
432 *out_event = m_applet->friend_invitation_storage_channel_event.GetHandle();
433 R_SUCCEED();
434}
435
436Result IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
437 Out<SharedPointer<IStorage>> out_storage) {
438 LOG_INFO(Service_AM, "(STUBBED) called");
439 R_THROW(AM::ResultNoDataInChannel);
440}
441
442Result IApplicationFunctions::GetNotificationStorageChannelEvent(
443 OutCopyHandle<Kernel::KReadableEvent> out_event) {
444 LOG_DEBUG(Service_AM, "called");
445 *out_event = m_applet->notification_storage_channel_event.GetHandle();
446 R_SUCCEED();
447}
448
449Result IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(
450 OutCopyHandle<Kernel::KReadableEvent> out_event) {
451 LOG_DEBUG(Service_AM, "called");
452 *out_event = m_applet->health_warning_disappeared_system_event.GetHandle();
453 R_SUCCEED();
454}
455
456Result IApplicationFunctions::PrepareForJit() {
457 LOG_WARNING(Service_AM, "(STUBBED) called");
458
459 std::scoped_lock lk{m_applet->lock};
460 m_applet->jit_service_launched = true;
461
462 R_SUCCEED();
463}
464
465} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_functions.h b/src/core/hle/service/am/service/application_functions.h
new file mode 100644
index 000000000..3548202f8
--- /dev/null
+++ b/src/core/hle/service/am/service/application_functions.h
@@ -0,0 +1,83 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/uuid.h"
7#include "core/hle/service/am/am_types.h"
8#include "core/hle/service/cmif_types.h"
9#include "core/hle/service/service.h"
10
11namespace FileSys {
12enum class SaveDataType : u8;
13}
14
15namespace Kernel {
16class KReadableEvent;
17}
18
19namespace Service::AM {
20
21struct Applet;
22class IStorage;
23
24class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
25public:
26 explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet);
27 ~IApplicationFunctions() override;
28
29private:
30 Result PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage,
31 LaunchParameterKind launch_parameter_kind);
32 Result EnsureSaveData(Out<u64> out_size, Common::UUID user_id);
33 Result GetDesiredLanguage(Out<u64> out_language_code);
34 Result SetTerminateResult(Result terminate_result);
35 Result GetDisplayVersion(Out<DisplayVersion> out_display_version);
36 Result ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type,
37 Common::UUID user_id, u64 normal_size, u64 journal_size);
38 Result GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size,
39 FileSys::SaveDataType type, Common::UUID user_id);
40 Result CreateCacheStorage(Out<u32> out_target_media, Out<u64> out_required_size, u16 index,
41 u64 normal_size, u64 journal_size);
42 Result GetSaveDataSizeMax(Out<u64> out_max_normal_size, Out<u64> out_max_journal_size);
43 Result BeginBlockingHomeButtonShortAndLongPressed(s64 unused);
44 Result EndBlockingHomeButtonShortAndLongPressed();
45 Result BeginBlockingHomeButton(s64 timeout_ns);
46 Result EndBlockingHomeButton();
47 Result NotifyRunning(Out<bool> out_became_running);
48 Result GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id);
49 Result IsGamePlayRecordingSupported(Out<bool> out_is_game_play_recording_supported);
50 Result InitializeGamePlayRecording(
51 u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
52 Result SetGamePlayRecordingState(GamePlayRecordingState game_play_recording_state);
53 Result EnableApplicationCrashReport(bool enabled);
54 Result InitializeApplicationCopyrightFrameBuffer(
55 s32 width, s32 height, u64 transfer_memory_size,
56 InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
57 Result SetApplicationCopyrightImage(
58 s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode,
59 InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data);
60 Result SetApplicationCopyrightVisibility(bool visible);
61 Result QueryApplicationPlayStatistics(
62 Out<s32> out_entries,
63 OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
64 InArray<u64, BufferAttr_HipcMapAlias> application_ids);
65 Result QueryApplicationPlayStatisticsByUid(
66 Out<s32> out_entries,
67 OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
68 Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids);
69 Result ExecuteProgram(ProgramSpecifyKind kind, u64 value);
70 Result ClearUserChannel();
71 Result UnpopToUserChannel(SharedPointer<IStorage> storage);
72 Result GetPreviousProgramIndex(Out<s32> out_previous_program_index);
73 Result GetGpuErrorDetectedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
74 Result GetFriendInvitationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
75 Result TryPopFromFriendInvitationStorageChannel(Out<SharedPointer<IStorage>> out_storage);
76 Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
77 Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
78 Result PrepareForJit();
79
80 const std::shared_ptr<Applet> m_applet;
81};
82
83} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_proxy.cpp b/src/core/hle/service/am/service/application_proxy.cpp
index b22960610..55a4ea72f 100644
--- a/src/core/hle/service/am/service/application_proxy.cpp
+++ b/src/core/hle/service/am/service/application_proxy.cpp
@@ -1,7 +1,6 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/am/application_functions.h"
5#include "core/hle/service/am/common_state_getter.h" 4#include "core/hle/service/am/common_state_getter.h"
6#include "core/hle/service/am/debug_functions.h" 5#include "core/hle/service/am/debug_functions.h"
7#include "core/hle/service/am/display_controller.h" 6#include "core/hle/service/am/display_controller.h"
@@ -10,6 +9,7 @@
10#include "core/hle/service/am/process_winding_controller.h" 9#include "core/hle/service/am/process_winding_controller.h"
11#include "core/hle/service/am/self_controller.h" 10#include "core/hle/service/am/self_controller.h"
12#include "core/hle/service/am/service/applet_common_functions.h" 11#include "core/hle/service/am/service/applet_common_functions.h"
12#include "core/hle/service/am/service/application_functions.h"
13#include "core/hle/service/am/service/application_proxy.h" 13#include "core/hle/service/am/service/application_proxy.h"
14#include "core/hle/service/am/service/audio_controller.h" 14#include "core/hle/service/am/service/audio_controller.h"
15#include "core/hle/service/am/window_controller.h" 15#include "core/hle/service/am/window_controller.h"