diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/core/hle/service/am/am_types.h | 38 | ||||
| -rw-r--r-- | src/core/hle/service/am/applet.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/am/application_functions.cpp | 594 | ||||
| -rw-r--r-- | src/core/hle/service/am/application_functions.h | 58 | ||||
| -rw-r--r-- | src/core/hle/service/am/service/application_functions.cpp | 465 | ||||
| -rw-r--r-- | src/core/hle/service/am/service/application_functions.h | 83 | ||||
| -rw-r--r-- | src/core/hle/service/am/service/application_proxy.cpp | 2 |
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 | ||
| 21 | enum class GameplayRecordingState : u32 { | 21 | enum 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 | ||
| 139 | enum class LaunchParameterKind : u32 { | ||
| 140 | UserChannel = 1, | ||
| 141 | AccountPreselectedUser = 2, | ||
| 142 | }; | ||
| 143 | |||
| 139 | enum class CommonArgumentVersion : u32 { | 144 | enum 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 | ||
| 160 | enum class InputDetectionPolicy : u32 { | ||
| 161 | Unknown0 = 0, | ||
| 162 | Unknown1 = 1, | ||
| 163 | }; | ||
| 164 | |||
| 165 | enum class WindowOriginMode : u32 { | ||
| 166 | LowerLeft = 0, | ||
| 167 | UpperLeft = 1, | ||
| 168 | }; | ||
| 169 | |||
| 170 | enum class ProgramSpecifyKind : u32 { | ||
| 171 | ExecuteProgram = 0, | ||
| 172 | JumpToSubApplicationProgramForDevelopment = 1, | ||
| 173 | RestartProgram = 2, | ||
| 174 | }; | ||
| 175 | |||
| 155 | struct CommonArguments { | 176 | struct CommonArguments { |
| 156 | CommonArgumentVersion arguments_version; | 177 | CommonArgumentVersion arguments_version; |
| 157 | CommonArgumentSize size; | 178 | CommonArgumentSize size; |
| @@ -175,6 +196,21 @@ struct AppletAttribute { | |||
| 175 | }; | 196 | }; |
| 176 | static_assert(sizeof(AppletAttribute) == 0x80, "AppletAttribute has incorrect size."); | 197 | static_assert(sizeof(AppletAttribute) == 0x80, "AppletAttribute has incorrect size."); |
| 177 | 198 | ||
| 199 | // This is nn::oe::DisplayVersion | ||
| 200 | struct DisplayVersion { | ||
| 201 | std::array<char, 0x10> string; | ||
| 202 | }; | ||
| 203 | static_assert(sizeof(DisplayVersion) == 0x10, "DisplayVersion has incorrect size."); | ||
| 204 | |||
| 205 | // This is nn::pdm::ApplicationPlayStatistics | ||
| 206 | struct ApplicationPlayStatistics { | ||
| 207 | u64 application_id; | ||
| 208 | u64 play_time_ns; | ||
| 209 | u64 launch_count; | ||
| 210 | }; | ||
| 211 | static_assert(sizeof(ApplicationPlayStatistics) == 0x18, | ||
| 212 | "ApplicationPlayStatistics has incorrect size."); | ||
| 213 | |||
| 178 | using AppletResourceUserId = u64; | 214 | using AppletResourceUserId = u64; |
| 179 | using ProgramId = u64; | 215 | using 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 | |||
| 21 | namespace Service::AM { | ||
| 22 | |||
| 23 | enum class LaunchParameterKind : u32 { | ||
| 24 | UserChannel = 1, | ||
| 25 | AccountPreselectedUser = 2, | ||
| 26 | }; | ||
| 27 | |||
| 28 | IApplicationFunctions::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 | |||
| 100 | IApplicationFunctions::~IApplicationFunctions() = default; | ||
| 101 | |||
| 102 | void 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 | |||
| 112 | void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) { | ||
| 113 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 114 | |||
| 115 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 116 | rb.Push(ResultSuccess); | ||
| 117 | } | ||
| 118 | |||
| 119 | void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) { | ||
| 120 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 121 | |||
| 122 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 123 | rb.Push(ResultSuccess); | ||
| 124 | } | ||
| 125 | |||
| 126 | void 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 | |||
| 136 | void 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 | |||
| 147 | void 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 | |||
| 158 | void 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 | |||
| 170 | void 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 | |||
| 182 | void 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 | |||
| 209 | void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { | ||
| 210 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 211 | |||
| 212 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 213 | rb.Push(ResultSuccess); | ||
| 214 | } | ||
| 215 | |||
| 216 | void 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 | |||
| 236 | void 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 | |||
| 252 | void 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 | |||
| 284 | void 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 | |||
| 342 | void 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 | |||
| 350 | void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) { | ||
| 351 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 352 | |||
| 353 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 354 | rb.Push(ResultSuccess); | ||
| 355 | } | ||
| 356 | |||
| 357 | void 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 | |||
| 369 | void 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 | |||
| 380 | void 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 | |||
| 391 | void 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 | |||
| 419 | void 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 | |||
| 441 | void 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 | |||
| 471 | void 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 | |||
| 483 | void 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 | |||
| 491 | void 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 | |||
| 499 | void 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 | |||
| 515 | void 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 | |||
| 524 | void 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 | |||
| 537 | void 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 | |||
| 545 | void 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 | |||
| 553 | void 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 | |||
| 561 | void 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 | |||
| 568 | void 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 | |||
| 576 | void 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 | |||
| 584 | void 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 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | struct Applet; | ||
| 12 | |||
| 13 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | ||
| 14 | public: | ||
| 15 | explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_); | ||
| 16 | ~IApplicationFunctions() override; | ||
| 17 | |||
| 18 | private: | ||
| 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 | |||
| 21 | namespace Service::AM { | ||
| 22 | |||
| 23 | IApplicationFunctions::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 | |||
| 95 | IApplicationFunctions::~IApplicationFunctions() = default; | ||
| 96 | |||
| 97 | Result 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 | |||
| 120 | Result 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 | |||
| 136 | Result 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 | |||
| 179 | Result 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 | |||
| 190 | Result 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 | |||
| 220 | Result 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 | |||
| 236 | Result 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 | |||
| 248 | Result 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 | |||
| 260 | Result 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 | |||
| 270 | Result 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 | |||
| 280 | Result 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 | |||
| 290 | Result 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 | |||
| 301 | Result 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 | |||
| 312 | Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) { | ||
| 313 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 314 | *out_became_running = true; | ||
| 315 | R_SUCCEED(); | ||
| 316 | } | ||
| 317 | |||
| 318 | Result 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 | |||
| 324 | Result 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 | |||
| 331 | Result 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 | |||
| 337 | Result 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 | |||
| 347 | Result 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 | |||
| 356 | Result 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 | |||
| 363 | Result 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 | |||
| 370 | Result IApplicationFunctions::SetApplicationCopyrightVisibility(bool visible) { | ||
| 371 | LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", visible); | ||
| 372 | R_SUCCEED(); | ||
| 373 | } | ||
| 374 | |||
| 375 | Result 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 | |||
| 384 | Result 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 | |||
| 393 | Result 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 | |||
| 404 | Result IApplicationFunctions::ClearUserChannel() { | ||
| 405 | LOG_DEBUG(Service_AM, "called"); | ||
| 406 | m_applet->user_channel_launch_parameter.clear(); | ||
| 407 | R_SUCCEED(); | ||
| 408 | } | ||
| 409 | |||
| 410 | Result 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 | |||
| 416 | Result 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 | |||
| 422 | Result 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 | |||
| 429 | Result 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 | |||
| 436 | Result IApplicationFunctions::TryPopFromFriendInvitationStorageChannel( | ||
| 437 | Out<SharedPointer<IStorage>> out_storage) { | ||
| 438 | LOG_INFO(Service_AM, "(STUBBED) called"); | ||
| 439 | R_THROW(AM::ResultNoDataInChannel); | ||
| 440 | } | ||
| 441 | |||
| 442 | Result 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 | |||
| 449 | Result 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 | |||
| 456 | Result 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 | |||
| 11 | namespace FileSys { | ||
| 12 | enum class SaveDataType : u8; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Kernel { | ||
| 16 | class KReadableEvent; | ||
| 17 | } | ||
| 18 | |||
| 19 | namespace Service::AM { | ||
| 20 | |||
| 21 | struct Applet; | ||
| 22 | class IStorage; | ||
| 23 | |||
| 24 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | ||
| 25 | public: | ||
| 26 | explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet); | ||
| 27 | ~IApplicationFunctions() override; | ||
| 28 | |||
| 29 | private: | ||
| 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" |