diff options
| author | 2023-12-30 20:51:23 -0500 | |
|---|---|---|
| committer | 2024-01-29 18:43:45 -0500 | |
| commit | 7de6b410305fcfcd34078e62fbe0ceedb43663f9 (patch) | |
| tree | b5f3dc0d7631852a64466f3765e62e0707b8d0c8 /src | |
| parent | Merge pull request #12846 from german77/mii_const (diff) | |
| download | yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar.gz yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar.xz yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.zip | |
service: split am into components
Diffstat (limited to 'src')
61 files changed, 4093 insertions, 3482 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ea6b2c285..3a2ba9ed4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -392,6 +392,7 @@ add_library(core STATIC | |||
| 392 | hle/service/acc/profile_manager.h | 392 | hle/service/acc/profile_manager.h |
| 393 | hle/service/am/am.cpp | 393 | hle/service/am/am.cpp |
| 394 | hle/service/am/am.h | 394 | hle/service/am/am.h |
| 395 | hle/service/am/am_results.h | ||
| 395 | hle/service/am/applet_ae.cpp | 396 | hle/service/am/applet_ae.cpp |
| 396 | hle/service/am/applet_ae.h | 397 | hle/service/am/applet_ae.h |
| 397 | hle/service/am/applet_oe.cpp | 398 | hle/service/am/applet_oe.cpp |
| @@ -417,12 +418,56 @@ add_library(core STATIC | |||
| 417 | hle/service/am/applets/applet_web_browser_types.h | 418 | hle/service/am/applets/applet_web_browser_types.h |
| 418 | hle/service/am/applets/applets.cpp | 419 | hle/service/am/applets/applets.cpp |
| 419 | hle/service/am/applets/applets.h | 420 | hle/service/am/applets/applets.h |
| 421 | hle/service/am/applet_common_functions.cpp | ||
| 422 | hle/service/am/applet_common_functions.h | ||
| 423 | hle/service/am/applet_message_queue.cpp | ||
| 424 | hle/service/am/applet_message_queue.h | ||
| 425 | hle/service/am/application_creator.cpp | ||
| 426 | hle/service/am/application_creator.h | ||
| 427 | hle/service/am/application_functions.cpp | ||
| 428 | hle/service/am/application_functions.h | ||
| 429 | hle/service/am/application_proxy.cpp | ||
| 430 | hle/service/am/application_proxy.h | ||
| 431 | hle/service/am/audio_controller.cpp | ||
| 432 | hle/service/am/audio_controller.h | ||
| 433 | hle/service/am/common_state_getter.cpp | ||
| 434 | hle/service/am/common_state_getter.h | ||
| 435 | hle/service/am/debug_functions.cpp | ||
| 436 | hle/service/am/debug_functions.h | ||
| 437 | hle/service/am/display_controller.cpp | ||
| 438 | hle/service/am/display_controller.h | ||
| 439 | hle/service/am/global_state_controller.cpp | ||
| 440 | hle/service/am/global_state_controller.h | ||
| 441 | hle/service/am/home_menu_functions.cpp | ||
| 442 | hle/service/am/home_menu_functions.h | ||
| 420 | hle/service/am/idle.cpp | 443 | hle/service/am/idle.cpp |
| 421 | hle/service/am/idle.h | 444 | hle/service/am/idle.h |
| 445 | hle/service/am/library_applet_accessor.cpp | ||
| 446 | hle/service/am/library_applet_accessor.h | ||
| 447 | hle/service/am/library_applet_creator.cpp | ||
| 448 | hle/service/am/library_applet_creator.h | ||
| 449 | hle/service/am/library_applet_proxy.cpp | ||
| 450 | hle/service/am/library_applet_proxy.h | ||
| 451 | hle/service/am/library_applet_self_accessor.cpp | ||
| 452 | hle/service/am/library_applet_self_accessor.h | ||
| 453 | hle/service/am/lock_accessor.cpp | ||
| 454 | hle/service/am/lock_accessor.h | ||
| 422 | hle/service/am/omm.cpp | 455 | hle/service/am/omm.cpp |
| 423 | hle/service/am/omm.h | 456 | hle/service/am/omm.h |
| 457 | hle/service/am/process_winding_controller.cpp | ||
| 458 | hle/service/am/process_winding_controller.h | ||
| 459 | hle/service/am/self_controller.cpp | ||
| 460 | hle/service/am/self_controller.h | ||
| 461 | hle/service/am/system_applet_proxy.cpp | ||
| 462 | hle/service/am/system_applet_proxy.h | ||
| 424 | hle/service/am/spsm.cpp | 463 | hle/service/am/spsm.cpp |
| 425 | hle/service/am/spsm.h | 464 | hle/service/am/spsm.h |
| 465 | hle/service/am/storage_accessor.cpp | ||
| 466 | hle/service/am/storage_accessor.h | ||
| 467 | hle/service/am/storage.cpp | ||
| 468 | hle/service/am/storage.h | ||
| 469 | hle/service/am/window_controller.cpp | ||
| 470 | hle/service/am/window_controller.h | ||
| 426 | hle/service/aoc/aoc_u.cpp | 471 | hle/service/aoc/aoc_u.cpp |
| 427 | hle/service/aoc/aoc_u.h | 472 | hle/service/aoc/aoc_u.h |
| 428 | hle/service/apm/apm.cpp | 473 | hle/service/apm/apm.cpp |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 38f67adcd..46bc4f703 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1,2541 +1,17 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | ||
| 5 | #include <array> | ||
| 6 | #include <cinttypes> | ||
| 7 | #include <cstring> | ||
| 8 | #include "common/settings.h" | ||
| 9 | #include "common/settings_enums.h" | ||
| 10 | #include "core/core.h" | ||
| 11 | #include "core/core_timing.h" | ||
| 12 | #include "core/file_sys/control_metadata.h" | ||
| 13 | #include "core/file_sys/patch_manager.h" | ||
| 14 | #include "core/file_sys/registered_cache.h" | ||
| 15 | #include "core/file_sys/savedata_factory.h" | ||
| 16 | #include "core/hle/kernel/k_event.h" | ||
| 17 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 18 | #include "core/hle/result.h" | ||
| 19 | #include "core/hle/service/acc/profile_manager.h" | ||
| 20 | #include "core/hle/service/am/am.h" | 4 | #include "core/hle/service/am/am.h" |
| 21 | #include "core/hle/service/am/applet_ae.h" | 5 | #include "core/hle/service/am/applet_ae.h" |
| 6 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 22 | #include "core/hle/service/am/applet_oe.h" | 7 | #include "core/hle/service/am/applet_oe.h" |
| 23 | #include "core/hle/service/am/applets/applet_cabinet.h" | ||
| 24 | #include "core/hle/service/am/applets/applet_controller.h" | ||
| 25 | #include "core/hle/service/am/applets/applet_mii_edit_types.h" | ||
| 26 | #include "core/hle/service/am/applets/applet_profile_select.h" | ||
| 27 | #include "core/hle/service/am/applets/applet_software_keyboard_types.h" | ||
| 28 | #include "core/hle/service/am/applets/applet_web_browser.h" | ||
| 29 | #include "core/hle/service/am/applets/applets.h" | ||
| 30 | #include "core/hle/service/am/idle.h" | 8 | #include "core/hle/service/am/idle.h" |
| 31 | #include "core/hle/service/am/omm.h" | 9 | #include "core/hle/service/am/omm.h" |
| 32 | #include "core/hle/service/am/spsm.h" | 10 | #include "core/hle/service/am/spsm.h" |
| 33 | #include "core/hle/service/apm/apm_controller.h" | ||
| 34 | #include "core/hle/service/apm/apm_interface.h" | ||
| 35 | #include "core/hle/service/bcat/backend/backend.h" | ||
| 36 | #include "core/hle/service/caps/caps_su.h" | ||
| 37 | #include "core/hle/service/caps/caps_types.h" | ||
| 38 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 39 | #include "core/hle/service/filesystem/save_data_controller.h" | ||
| 40 | #include "core/hle/service/ipc_helpers.h" | ||
| 41 | #include "core/hle/service/ns/ns.h" | ||
| 42 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 43 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 44 | #include "core/hle/service/pm/pm.h" | ||
| 45 | #include "core/hle/service/server_manager.h" | 11 | #include "core/hle/service/server_manager.h" |
| 46 | #include "core/hle/service/sm/sm.h" | ||
| 47 | #include "core/hle/service/vi/vi.h" | ||
| 48 | #include "core/hle/service/vi/vi_results.h" | ||
| 49 | #include "core/memory.h" | ||
| 50 | #include "hid_core/hid_types.h" | ||
| 51 | #include "hid_core/resources/npad/npad.h" | ||
| 52 | 12 | ||
| 53 | namespace Service::AM { | 13 | namespace Service::AM { |
| 54 | 14 | ||
| 55 | constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2}; | ||
| 56 | constexpr Result ResultNoMessages{ErrorModule::AM, 3}; | ||
| 57 | constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; | ||
| 58 | |||
| 59 | enum class LaunchParameterKind : u32 { | ||
| 60 | UserChannel = 1, | ||
| 61 | AccountPreselectedUser = 2, | ||
| 62 | }; | ||
| 63 | |||
| 64 | constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA; | ||
| 65 | |||
| 66 | struct LaunchParameterAccountPreselectedUser { | ||
| 67 | u32_le magic; | ||
| 68 | u32_le is_account_selected; | ||
| 69 | Common::UUID current_user; | ||
| 70 | INSERT_PADDING_BYTES(0x70); | ||
| 71 | }; | ||
| 72 | static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); | ||
| 73 | |||
| 74 | IWindowController::IWindowController(Core::System& system_) | ||
| 75 | : ServiceFramework{system_, "IWindowController"} { | ||
| 76 | // clang-format off | ||
| 77 | static const FunctionInfo functions[] = { | ||
| 78 | {0, nullptr, "CreateWindow"}, | ||
| 79 | {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, | ||
| 80 | {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"}, | ||
| 81 | {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, | ||
| 82 | {11, nullptr, "ReleaseForegroundRights"}, | ||
| 83 | {12, nullptr, "RejectToChangeIntoBackground"}, | ||
| 84 | {20, nullptr, "SetAppletWindowVisibility"}, | ||
| 85 | {21, nullptr, "SetAppletGpuTimeSlice"}, | ||
| 86 | }; | ||
| 87 | // clang-format on | ||
| 88 | |||
| 89 | RegisterHandlers(functions); | ||
| 90 | } | ||
| 91 | |||
| 92 | IWindowController::~IWindowController() = default; | ||
| 93 | |||
| 94 | void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) { | ||
| 95 | const u64 process_id = system.ApplicationProcess()->GetProcessId(); | ||
| 96 | |||
| 97 | LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id); | ||
| 98 | |||
| 99 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 100 | rb.Push(ResultSuccess); | ||
| 101 | rb.Push<u64>(process_id); | ||
| 102 | } | ||
| 103 | |||
| 104 | void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) { | ||
| 105 | const u64 process_id = 0; | ||
| 106 | |||
| 107 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 108 | |||
| 109 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 110 | rb.Push(ResultSuccess); | ||
| 111 | rb.Push<u64>(process_id); | ||
| 112 | } | ||
| 113 | |||
| 114 | void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { | ||
| 115 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 116 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 117 | rb.Push(ResultSuccess); | ||
| 118 | } | ||
| 119 | |||
| 120 | IAudioController::IAudioController(Core::System& system_) | ||
| 121 | : ServiceFramework{system_, "IAudioController"} { | ||
| 122 | // clang-format off | ||
| 123 | static const FunctionInfo functions[] = { | ||
| 124 | {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"}, | ||
| 125 | {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"}, | ||
| 126 | {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"}, | ||
| 127 | {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"}, | ||
| 128 | {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"}, | ||
| 129 | }; | ||
| 130 | // clang-format on | ||
| 131 | |||
| 132 | RegisterHandlers(functions); | ||
| 133 | } | ||
| 134 | |||
| 135 | IAudioController::~IAudioController() = default; | ||
| 136 | |||
| 137 | void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 138 | IPC::RequestParser rp{ctx}; | ||
| 139 | const float main_applet_volume_tmp = rp.Pop<float>(); | ||
| 140 | const float library_applet_volume_tmp = rp.Pop<float>(); | ||
| 141 | |||
| 142 | LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}", | ||
| 143 | main_applet_volume_tmp, library_applet_volume_tmp); | ||
| 144 | |||
| 145 | // Ensure the volume values remain within the 0-100% range | ||
| 146 | main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume); | ||
| 147 | library_applet_volume = | ||
| 148 | std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume); | ||
| 149 | |||
| 150 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 151 | rb.Push(ResultSuccess); | ||
| 152 | } | ||
| 153 | |||
| 154 | void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 155 | LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume); | ||
| 156 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 157 | rb.Push(ResultSuccess); | ||
| 158 | rb.Push(main_applet_volume); | ||
| 159 | } | ||
| 160 | |||
| 161 | void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 162 | LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume); | ||
| 163 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 164 | rb.Push(ResultSuccess); | ||
| 165 | rb.Push(library_applet_volume); | ||
| 166 | } | ||
| 167 | |||
| 168 | void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) { | ||
| 169 | struct Parameters { | ||
| 170 | float volume; | ||
| 171 | s64 fade_time_ns; | ||
| 172 | }; | ||
| 173 | static_assert(sizeof(Parameters) == 16); | ||
| 174 | |||
| 175 | IPC::RequestParser rp{ctx}; | ||
| 176 | const auto parameters = rp.PopRaw<Parameters>(); | ||
| 177 | |||
| 178 | LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume, | ||
| 179 | parameters.fade_time_ns); | ||
| 180 | |||
| 181 | main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume); | ||
| 182 | fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns}; | ||
| 183 | |||
| 184 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 185 | rb.Push(ResultSuccess); | ||
| 186 | } | ||
| 187 | |||
| 188 | void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) { | ||
| 189 | IPC::RequestParser rp{ctx}; | ||
| 190 | const float transparent_volume_rate_tmp = rp.Pop<float>(); | ||
| 191 | |||
| 192 | LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp); | ||
| 193 | |||
| 194 | // Clamp volume range to 0-100%. | ||
| 195 | transparent_volume_rate = | ||
| 196 | std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume); | ||
| 197 | |||
| 198 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 199 | rb.Push(ResultSuccess); | ||
| 200 | } | ||
| 201 | |||
| 202 | IDisplayController::IDisplayController(Core::System& system_) | ||
| 203 | : ServiceFramework{system_, "IDisplayController"} { | ||
| 204 | // clang-format off | ||
| 205 | static const FunctionInfo functions[] = { | ||
| 206 | {0, nullptr, "GetLastForegroundCaptureImage"}, | ||
| 207 | {1, nullptr, "UpdateLastForegroundCaptureImage"}, | ||
| 208 | {2, nullptr, "GetLastApplicationCaptureImage"}, | ||
| 209 | {3, nullptr, "GetCallerAppletCaptureImage"}, | ||
| 210 | {4, nullptr, "UpdateCallerAppletCaptureImage"}, | ||
| 211 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, | ||
| 212 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, | ||
| 213 | {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"}, | ||
| 214 | {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"}, | ||
| 215 | {9, nullptr, "CopyBetweenCaptureBuffers"}, | ||
| 216 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, | ||
| 217 | {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, | ||
| 218 | {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, | ||
| 219 | {13, nullptr, "ReleaseLastForegroundCaptureBuffer"}, | ||
| 220 | {14, nullptr, "AcquireCallerAppletCaptureBuffer"}, | ||
| 221 | {15, nullptr, "ReleaseCallerAppletCaptureBuffer"}, | ||
| 222 | {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, | ||
| 223 | {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, | ||
| 224 | {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, | ||
| 225 | {20, nullptr, "ClearCaptureBuffer"}, | ||
| 226 | {21, nullptr, "ClearAppletTransitionBuffer"}, | ||
| 227 | {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"}, | ||
| 228 | {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, | ||
| 229 | {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"}, | ||
| 230 | {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"}, | ||
| 231 | {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"}, | ||
| 232 | {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"}, | ||
| 233 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, | ||
| 234 | }; | ||
| 235 | // clang-format on | ||
| 236 | |||
| 237 | RegisterHandlers(functions); | ||
| 238 | } | ||
| 239 | |||
| 240 | IDisplayController::~IDisplayController() = default; | ||
| 241 | |||
| 242 | void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) { | ||
| 243 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 244 | |||
| 245 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 246 | rb.Push(ResultSuccess); | ||
| 247 | rb.Push(1u); | ||
| 248 | rb.Push(0); | ||
| 249 | } | ||
| 250 | |||
| 251 | void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { | ||
| 252 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 253 | |||
| 254 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 255 | rb.Push(ResultSuccess); | ||
| 256 | } | ||
| 257 | |||
| 258 | void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 259 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 260 | |||
| 261 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 262 | rb.Push(ResultSuccess); | ||
| 263 | rb.Push(1U); | ||
| 264 | rb.Push(0); | ||
| 265 | } | ||
| 266 | |||
| 267 | void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 268 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 269 | |||
| 270 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 271 | rb.Push(ResultSuccess); | ||
| 272 | } | ||
| 273 | |||
| 274 | void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 275 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 276 | |||
| 277 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 278 | rb.Push(ResultSuccess); | ||
| 279 | rb.Push(1U); | ||
| 280 | rb.Push(0); | ||
| 281 | } | ||
| 282 | |||
| 283 | void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 284 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 285 | |||
| 286 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 287 | rb.Push(ResultSuccess); | ||
| 288 | } | ||
| 289 | |||
| 290 | IDebugFunctions::IDebugFunctions(Core::System& system_) | ||
| 291 | : ServiceFramework{system_, "IDebugFunctions"} { | ||
| 292 | // clang-format off | ||
| 293 | static const FunctionInfo functions[] = { | ||
| 294 | {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, | ||
| 295 | {1, nullptr, "OpenMainApplication"}, | ||
| 296 | {10, nullptr, "PerformSystemButtonPressing"}, | ||
| 297 | {20, nullptr, "InvalidateTransitionLayer"}, | ||
| 298 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, | ||
| 299 | {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"}, | ||
| 300 | {40, nullptr, "GetAppletResourceUsageInfo"}, | ||
| 301 | {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"}, | ||
| 302 | {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"}, | ||
| 303 | {100, nullptr, "SetCpuBoostModeForApplet"}, | ||
| 304 | {101, nullptr, "CancelCpuBoostModeForApplet"}, | ||
| 305 | {110, nullptr, "PushToAppletBoundChannelForDebug"}, | ||
| 306 | {111, nullptr, "TryPopFromAppletBoundChannelForDebug"}, | ||
| 307 | {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"}, | ||
| 308 | {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"}, | ||
| 309 | {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"}, | ||
| 310 | {130, nullptr, "FriendInvitationSetApplicationParameter"}, | ||
| 311 | {131, nullptr, "FriendInvitationClearApplicationParameter"}, | ||
| 312 | {132, nullptr, "FriendInvitationPushApplicationParameter"}, | ||
| 313 | {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"}, | ||
| 314 | {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"}, | ||
| 315 | {300, nullptr, "TerminateAllRunningApplicationsForDebug"}, | ||
| 316 | {900, nullptr, "GetGrcProcessLaunchedSystemEvent"}, | ||
| 317 | }; | ||
| 318 | // clang-format on | ||
| 319 | |||
| 320 | RegisterHandlers(functions); | ||
| 321 | } | ||
| 322 | |||
| 323 | IDebugFunctions::~IDebugFunctions() = default; | ||
| 324 | |||
| 325 | ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) | ||
| 326 | : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, | ||
| 327 | service_context{system, "ISelfController"} { | ||
| 328 | // clang-format off | ||
| 329 | static const FunctionInfo functions[] = { | ||
| 330 | {0, &ISelfController::Exit, "Exit"}, | ||
| 331 | {1, &ISelfController::LockExit, "LockExit"}, | ||
| 332 | {2, &ISelfController::UnlockExit, "UnlockExit"}, | ||
| 333 | {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, | ||
| 334 | {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"}, | ||
| 335 | {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, | ||
| 336 | {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, | ||
| 337 | {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, | ||
| 338 | {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"}, | ||
| 339 | {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, | ||
| 340 | {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, | ||
| 341 | {15, nullptr, "SetScreenShotAppletIdentityInfo"}, | ||
| 342 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, | ||
| 343 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, | ||
| 344 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, | ||
| 345 | {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"}, | ||
| 346 | {20, nullptr, "SetDesirableKeyboardLayout"}, | ||
| 347 | {21, nullptr, "GetScreenShotProgramId"}, | ||
| 348 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, | ||
| 349 | {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"}, | ||
| 350 | {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"}, | ||
| 351 | {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"}, | ||
| 352 | {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"}, | ||
| 353 | {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, | ||
| 354 | {46, nullptr, "SetRecordingLayerCompositionEnabled"}, | ||
| 355 | {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, | ||
| 356 | {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"}, | ||
| 357 | {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, | ||
| 358 | {61, nullptr, "SetMediaPlaybackState"}, | ||
| 359 | {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, | ||
| 360 | {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"}, | ||
| 361 | {64, nullptr, "SetInputDetectionSourceSet"}, | ||
| 362 | {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"}, | ||
| 363 | {66, nullptr, "GetCurrentIlluminance"}, | ||
| 364 | {67, nullptr, "IsIlluminanceAvailable"}, | ||
| 365 | {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"}, | ||
| 366 | {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"}, | ||
| 367 | {70, nullptr, "ReportMultimediaError"}, | ||
| 368 | {71, nullptr, "GetCurrentIlluminanceEx"}, | ||
| 369 | {72, nullptr, "SetInputDetectionPolicy"}, | ||
| 370 | {80, nullptr, "SetWirelessPriorityMode"}, | ||
| 371 | {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"}, | ||
| 372 | {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, | ||
| 373 | {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, | ||
| 374 | {110, nullptr, "SetApplicationAlbumUserData"}, | ||
| 375 | {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"}, | ||
| 376 | {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"}, | ||
| 377 | {1000, nullptr, "GetDebugStorageChannel"}, | ||
| 378 | }; | ||
| 379 | // clang-format on | ||
| 380 | |||
| 381 | RegisterHandlers(functions); | ||
| 382 | |||
| 383 | launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent"); | ||
| 384 | |||
| 385 | // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is | ||
| 386 | // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple | ||
| 387 | // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not | ||
| 388 | // suspended if the event has previously been created by a call to | ||
| 389 | // GetAccumulatedSuspendedTickChangedEvent. | ||
| 390 | |||
| 391 | accumulated_suspended_tick_changed_event = | ||
| 392 | service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent"); | ||
| 393 | accumulated_suspended_tick_changed_event->Signal(); | ||
| 394 | } | ||
| 395 | |||
| 396 | ISelfController::~ISelfController() { | ||
| 397 | service_context.CloseEvent(launchable_event); | ||
| 398 | service_context.CloseEvent(accumulated_suspended_tick_changed_event); | ||
| 399 | } | ||
| 400 | |||
| 401 | void ISelfController::Exit(HLERequestContext& ctx) { | ||
| 402 | LOG_DEBUG(Service_AM, "called"); | ||
| 403 | |||
| 404 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 405 | rb.Push(ResultSuccess); | ||
| 406 | |||
| 407 | system.Exit(); | ||
| 408 | } | ||
| 409 | |||
| 410 | void ISelfController::LockExit(HLERequestContext& ctx) { | ||
| 411 | LOG_DEBUG(Service_AM, "called"); | ||
| 412 | |||
| 413 | system.SetExitLocked(true); | ||
| 414 | |||
| 415 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 416 | rb.Push(ResultSuccess); | ||
| 417 | } | ||
| 418 | |||
| 419 | void ISelfController::UnlockExit(HLERequestContext& ctx) { | ||
| 420 | LOG_DEBUG(Service_AM, "called"); | ||
| 421 | |||
| 422 | system.SetExitLocked(false); | ||
| 423 | |||
| 424 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 425 | rb.Push(ResultSuccess); | ||
| 426 | |||
| 427 | if (system.GetExitRequested()) { | ||
| 428 | system.Exit(); | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 432 | void ISelfController::EnterFatalSection(HLERequestContext& ctx) { | ||
| 433 | ++num_fatal_sections_entered; | ||
| 434 | LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); | ||
| 435 | |||
| 436 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 437 | rb.Push(ResultSuccess); | ||
| 438 | } | ||
| 439 | |||
| 440 | void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { | ||
| 441 | LOG_DEBUG(Service_AM, "called."); | ||
| 442 | |||
| 443 | // Entry and exit of fatal sections must be balanced. | ||
| 444 | if (num_fatal_sections_entered == 0) { | ||
| 445 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 446 | rb.Push(Result{ErrorModule::AM, 512}); | ||
| 447 | return; | ||
| 448 | } | ||
| 449 | |||
| 450 | --num_fatal_sections_entered; | ||
| 451 | |||
| 452 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 453 | rb.Push(ResultSuccess); | ||
| 454 | } | ||
| 455 | |||
| 456 | void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { | ||
| 457 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 458 | |||
| 459 | launchable_event->Signal(); | ||
| 460 | |||
| 461 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 462 | rb.Push(ResultSuccess); | ||
| 463 | rb.PushCopyObjects(launchable_event->GetReadableEvent()); | ||
| 464 | } | ||
| 465 | |||
| 466 | void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { | ||
| 467 | IPC::RequestParser rp{ctx}; | ||
| 468 | const auto permission = rp.PopEnum<ScreenshotPermission>(); | ||
| 469 | LOG_DEBUG(Service_AM, "called, permission={}", permission); | ||
| 470 | |||
| 471 | screenshot_permission = permission; | ||
| 472 | |||
| 473 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 474 | rb.Push(ResultSuccess); | ||
| 475 | } | ||
| 476 | |||
| 477 | void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { | ||
| 478 | IPC::RequestParser rp{ctx}; | ||
| 479 | |||
| 480 | bool flag = rp.Pop<bool>(); | ||
| 481 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); | ||
| 482 | |||
| 483 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 484 | rb.Push(ResultSuccess); | ||
| 485 | } | ||
| 486 | |||
| 487 | void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { | ||
| 488 | IPC::RequestParser rp{ctx}; | ||
| 489 | |||
| 490 | bool flag = rp.Pop<bool>(); | ||
| 491 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); | ||
| 492 | |||
| 493 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 494 | rb.Push(ResultSuccess); | ||
| 495 | } | ||
| 496 | |||
| 497 | void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { | ||
| 498 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 499 | // u8, these are bool flags. No output. | ||
| 500 | IPC::RequestParser rp{ctx}; | ||
| 501 | |||
| 502 | struct FocusHandlingModeParams { | ||
| 503 | u8 unknown0; | ||
| 504 | u8 unknown1; | ||
| 505 | u8 unknown2; | ||
| 506 | }; | ||
| 507 | const auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||
| 508 | |||
| 509 | LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}", | ||
| 510 | flags.unknown0, flags.unknown1, flags.unknown2); | ||
| 511 | |||
| 512 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 513 | rb.Push(ResultSuccess); | ||
| 514 | } | ||
| 515 | |||
| 516 | void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { | ||
| 517 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 518 | |||
| 519 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 520 | rb.Push(ResultSuccess); | ||
| 521 | } | ||
| 522 | |||
| 523 | void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { | ||
| 524 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 525 | // u8, these are bool flags. No output. | ||
| 526 | IPC::RequestParser rp{ctx}; | ||
| 527 | |||
| 528 | bool enabled = rp.Pop<bool>(); | ||
| 529 | LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); | ||
| 530 | |||
| 531 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 532 | rb.Push(ResultSuccess); | ||
| 533 | } | ||
| 534 | |||
| 535 | void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { | ||
| 536 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 537 | |||
| 538 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 539 | rb.Push(ResultSuccess); | ||
| 540 | } | ||
| 541 | |||
| 542 | void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { | ||
| 543 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 544 | |||
| 545 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 546 | // create the layer in the Default display. | ||
| 547 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 548 | const auto layer_id = nvnflinger.CreateLayer(*display_id); | ||
| 549 | |||
| 550 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 551 | rb.Push(ResultSuccess); | ||
| 552 | rb.Push(*layer_id); | ||
| 553 | } | ||
| 554 | |||
| 555 | void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { | ||
| 556 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 557 | |||
| 558 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 559 | rb.Push(this->EnsureBufferSharingEnabled()); | ||
| 560 | } | ||
| 561 | |||
| 562 | void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { | ||
| 563 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 564 | |||
| 565 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 566 | rb.Push(this->EnsureBufferSharingEnabled()); | ||
| 567 | rb.Push<s64>(system_shared_buffer_id); | ||
| 568 | rb.Push<s64>(system_shared_layer_id); | ||
| 569 | } | ||
| 570 | |||
| 571 | void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { | ||
| 572 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 573 | |||
| 574 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 575 | rb.Push(this->EnsureBufferSharingEnabled()); | ||
| 576 | rb.Push<s64>(system_shared_buffer_id); | ||
| 577 | } | ||
| 578 | |||
| 579 | Result ISelfController::EnsureBufferSharingEnabled() { | ||
| 580 | if (buffer_sharing_enabled) { | ||
| 581 | return ResultSuccess; | ||
| 582 | } | ||
| 583 | |||
| 584 | if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) { | ||
| 585 | return VI::ResultOperationFailed; | ||
| 586 | } | ||
| 587 | |||
| 588 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 589 | const auto result = nvnflinger.GetSystemBufferManager().Initialize( | ||
| 590 | &system_shared_buffer_id, &system_shared_layer_id, *display_id); | ||
| 591 | |||
| 592 | if (result.IsSuccess()) { | ||
| 593 | buffer_sharing_enabled = true; | ||
| 594 | } | ||
| 595 | |||
| 596 | return result; | ||
| 597 | } | ||
| 598 | |||
| 599 | void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { | ||
| 600 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 601 | |||
| 602 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 603 | // create the layer in the Default display. | ||
| 604 | // This calls nn::vi::CreateRecordingLayer() which creates another layer. | ||
| 605 | // Currently we do not support more than 1 layer per display, output 1 layer id for now. | ||
| 606 | // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse | ||
| 607 | // side effects. | ||
| 608 | // TODO: Support multiple layers | ||
| 609 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 610 | const auto layer_id = nvnflinger.CreateLayer(*display_id); | ||
| 611 | |||
| 612 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 613 | rb.Push(ResultSuccess); | ||
| 614 | rb.Push(*layer_id); | ||
| 615 | } | ||
| 616 | |||
| 617 | void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { | ||
| 618 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 619 | |||
| 620 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 621 | rb.Push(ResultSuccess); | ||
| 622 | } | ||
| 623 | |||
| 624 | void ISelfController::ApproveToDisplay(HLERequestContext& ctx) { | ||
| 625 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 626 | |||
| 627 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 628 | rb.Push(ResultSuccess); | ||
| 629 | } | ||
| 630 | |||
| 631 | void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { | ||
| 632 | IPC::RequestParser rp{ctx}; | ||
| 633 | idle_time_detection_extension = rp.Pop<u32>(); | ||
| 634 | LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}", | ||
| 635 | idle_time_detection_extension); | ||
| 636 | |||
| 637 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 638 | rb.Push(ResultSuccess); | ||
| 639 | } | ||
| 640 | |||
| 641 | void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { | ||
| 642 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 643 | |||
| 644 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 645 | rb.Push(ResultSuccess); | ||
| 646 | rb.Push<u32>(idle_time_detection_extension); | ||
| 647 | } | ||
| 648 | |||
| 649 | void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { | ||
| 650 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 651 | |||
| 652 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 653 | rb.Push(ResultSuccess); | ||
| 654 | } | ||
| 655 | |||
| 656 | void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { | ||
| 657 | IPC::RequestParser rp{ctx}; | ||
| 658 | is_auto_sleep_disabled = rp.Pop<bool>(); | ||
| 659 | |||
| 660 | // On the system itself, if the previous state of is_auto_sleep_disabled | ||
| 661 | // differed from the current value passed in, it'd signify the internal | ||
| 662 | // window manager to update (and also increment some statistics like update counts) | ||
| 663 | // | ||
| 664 | // It'd also indicate this change to an idle handling context. | ||
| 665 | // | ||
| 666 | // However, given we're emulating this behavior, most of this can be ignored | ||
| 667 | // and it's sufficient to simply set the member variable for querying via | ||
| 668 | // IsAutoSleepDisabled(). | ||
| 669 | |||
| 670 | LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled); | ||
| 671 | |||
| 672 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 673 | rb.Push(ResultSuccess); | ||
| 674 | } | ||
| 675 | |||
| 676 | void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { | ||
| 677 | LOG_DEBUG(Service_AM, "called."); | ||
| 678 | |||
| 679 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 680 | rb.Push(ResultSuccess); | ||
| 681 | rb.Push(is_auto_sleep_disabled); | ||
| 682 | } | ||
| 683 | |||
| 684 | void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { | ||
| 685 | LOG_DEBUG(Service_AM, "called."); | ||
| 686 | |||
| 687 | // This command returns the total number of system ticks since ISelfController creation | ||
| 688 | // where the game was suspended. Since Yuzu doesn't implement game suspension, this command | ||
| 689 | // can just always return 0 ticks. | ||
| 690 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 691 | rb.Push(ResultSuccess); | ||
| 692 | rb.Push<u64>(0); | ||
| 693 | } | ||
| 694 | |||
| 695 | void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { | ||
| 696 | LOG_DEBUG(Service_AM, "called."); | ||
| 697 | |||
| 698 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 699 | rb.Push(ResultSuccess); | ||
| 700 | rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); | ||
| 701 | } | ||
| 702 | |||
| 703 | void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { | ||
| 704 | IPC::RequestParser rp{ctx}; | ||
| 705 | |||
| 706 | // This service call sets an internal flag whether a notification is shown when an image is | ||
| 707 | // captured. Currently we do not support capturing images via the capture button, so this can be | ||
| 708 | // stubbed for now. | ||
| 709 | const bool album_image_taken_notification_enabled = rp.Pop<bool>(); | ||
| 710 | |||
| 711 | LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}", | ||
| 712 | album_image_taken_notification_enabled); | ||
| 713 | |||
| 714 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 715 | rb.Push(ResultSuccess); | ||
| 716 | } | ||
| 717 | |||
| 718 | void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { | ||
| 719 | IPC::RequestParser rp{ctx}; | ||
| 720 | |||
| 721 | const auto report_option = rp.PopEnum<Capture::AlbumReportOption>(); | ||
| 722 | |||
| 723 | LOG_INFO(Service_AM, "called, report_option={}", report_option); | ||
| 724 | |||
| 725 | const auto screenshot_service = | ||
| 726 | system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>( | ||
| 727 | "caps:su"); | ||
| 728 | |||
| 729 | if (screenshot_service) { | ||
| 730 | screenshot_service->CaptureAndSaveScreenshot(report_option); | ||
| 731 | } | ||
| 732 | |||
| 733 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 734 | rb.Push(ResultSuccess); | ||
| 735 | } | ||
| 736 | |||
| 737 | void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { | ||
| 738 | IPC::RequestParser rp{ctx}; | ||
| 739 | |||
| 740 | const auto is_record_volume_muted = rp.Pop<bool>(); | ||
| 741 | |||
| 742 | LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted); | ||
| 743 | |||
| 744 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 745 | rb.Push(ResultSuccess); | ||
| 746 | } | ||
| 747 | |||
| 748 | AppletMessageQueue::AppletMessageQueue(Core::System& system) | ||
| 749 | : service_context{system, "AppletMessageQueue"} { | ||
| 750 | on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived"); | ||
| 751 | on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged"); | ||
| 752 | } | ||
| 753 | |||
| 754 | AppletMessageQueue::~AppletMessageQueue() { | ||
| 755 | service_context.CloseEvent(on_new_message); | ||
| 756 | service_context.CloseEvent(on_operation_mode_changed); | ||
| 757 | } | ||
| 758 | |||
| 759 | Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() { | ||
| 760 | return on_new_message->GetReadableEvent(); | ||
| 761 | } | ||
| 762 | |||
| 763 | Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() { | ||
| 764 | return on_operation_mode_changed->GetReadableEvent(); | ||
| 765 | } | ||
| 766 | |||
| 767 | void AppletMessageQueue::PushMessage(AppletMessage msg) { | ||
| 768 | messages.push(msg); | ||
| 769 | on_new_message->Signal(); | ||
| 770 | } | ||
| 771 | |||
| 772 | AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { | ||
| 773 | if (messages.empty()) { | ||
| 774 | on_new_message->Clear(); | ||
| 775 | return AppletMessage::None; | ||
| 776 | } | ||
| 777 | auto msg = messages.front(); | ||
| 778 | messages.pop(); | ||
| 779 | if (messages.empty()) { | ||
| 780 | on_new_message->Clear(); | ||
| 781 | } | ||
| 782 | return msg; | ||
| 783 | } | ||
| 784 | |||
| 785 | std::size_t AppletMessageQueue::GetMessageCount() const { | ||
| 786 | return messages.size(); | ||
| 787 | } | ||
| 788 | |||
| 789 | void AppletMessageQueue::RequestExit() { | ||
| 790 | PushMessage(AppletMessage::Exit); | ||
| 791 | } | ||
| 792 | |||
| 793 | void AppletMessageQueue::RequestResume() { | ||
| 794 | PushMessage(AppletMessage::Resume); | ||
| 795 | } | ||
| 796 | |||
| 797 | void AppletMessageQueue::FocusStateChanged() { | ||
| 798 | PushMessage(AppletMessage::FocusStateChanged); | ||
| 799 | } | ||
| 800 | |||
| 801 | void AppletMessageQueue::OperationModeChanged() { | ||
| 802 | PushMessage(AppletMessage::OperationModeChanged); | ||
| 803 | PushMessage(AppletMessage::PerformanceModeChanged); | ||
| 804 | on_operation_mode_changed->Signal(); | ||
| 805 | } | ||
| 806 | |||
| 807 | ILockAccessor::ILockAccessor(Core::System& system_) | ||
| 808 | : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} { | ||
| 809 | // clang-format off | ||
| 810 | static const FunctionInfo functions[] = { | ||
| 811 | {1, &ILockAccessor::TryLock, "TryLock"}, | ||
| 812 | {2, &ILockAccessor::Unlock, "Unlock"}, | ||
| 813 | {3, &ILockAccessor::GetEvent, "GetEvent"}, | ||
| 814 | {4,&ILockAccessor::IsLocked, "IsLocked"}, | ||
| 815 | }; | ||
| 816 | // clang-format on | ||
| 817 | |||
| 818 | RegisterHandlers(functions); | ||
| 819 | |||
| 820 | lock_event = service_context.CreateEvent("ILockAccessor::LockEvent"); | ||
| 821 | } | ||
| 822 | |||
| 823 | ILockAccessor::~ILockAccessor() { | ||
| 824 | service_context.CloseEvent(lock_event); | ||
| 825 | }; | ||
| 826 | |||
| 827 | void ILockAccessor::TryLock(HLERequestContext& ctx) { | ||
| 828 | IPC::RequestParser rp{ctx}; | ||
| 829 | const auto return_handle = rp.Pop<bool>(); | ||
| 830 | |||
| 831 | LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle); | ||
| 832 | |||
| 833 | // TODO: When return_handle is true this function should return the lock handle | ||
| 834 | |||
| 835 | is_locked = true; | ||
| 836 | |||
| 837 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 838 | rb.Push(ResultSuccess); | ||
| 839 | rb.Push<u8>(is_locked); | ||
| 840 | } | ||
| 841 | |||
| 842 | void ILockAccessor::Unlock(HLERequestContext& ctx) { | ||
| 843 | LOG_INFO(Service_AM, "called"); | ||
| 844 | |||
| 845 | is_locked = false; | ||
| 846 | |||
| 847 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 848 | rb.Push(ResultSuccess); | ||
| 849 | } | ||
| 850 | |||
| 851 | void ILockAccessor::GetEvent(HLERequestContext& ctx) { | ||
| 852 | LOG_INFO(Service_AM, "called"); | ||
| 853 | |||
| 854 | lock_event->Signal(); | ||
| 855 | |||
| 856 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 857 | rb.Push(ResultSuccess); | ||
| 858 | rb.PushCopyObjects(lock_event->GetReadableEvent()); | ||
| 859 | } | ||
| 860 | |||
| 861 | void ILockAccessor::IsLocked(HLERequestContext& ctx) { | ||
| 862 | LOG_INFO(Service_AM, "called"); | ||
| 863 | |||
| 864 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 865 | rb.Push(ResultSuccess); | ||
| 866 | rb.Push<u8>(is_locked); | ||
| 867 | } | ||
| 868 | |||
| 869 | ICommonStateGetter::ICommonStateGetter(Core::System& system_, | ||
| 870 | std::shared_ptr<AppletMessageQueue> msg_queue_) | ||
| 871 | : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)}, | ||
| 872 | service_context{system_, "ICommonStateGetter"} { | ||
| 873 | // clang-format off | ||
| 874 | static const FunctionInfo functions[] = { | ||
| 875 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, | ||
| 876 | {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, | ||
| 877 | {2, nullptr, "GetThisAppletKind"}, | ||
| 878 | {3, nullptr, "AllowToEnterSleep"}, | ||
| 879 | {4, nullptr, "DisallowToEnterSleep"}, | ||
| 880 | {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, | ||
| 881 | {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, | ||
| 882 | {7, nullptr, "GetCradleStatus"}, | ||
| 883 | {8, &ICommonStateGetter::GetBootMode, "GetBootMode"}, | ||
| 884 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, | ||
| 885 | {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"}, | ||
| 886 | {11, nullptr, "ReleaseSleepLock"}, | ||
| 887 | {12, nullptr, "ReleaseSleepLockTransiently"}, | ||
| 888 | {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"}, | ||
| 889 | {14, nullptr, "GetWakeupCount"}, | ||
| 890 | {20, nullptr, "PushToGeneralChannel"}, | ||
| 891 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, | ||
| 892 | {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"}, | ||
| 893 | {32, nullptr, "GetWriterLockAccessorEx"}, | ||
| 894 | {40, nullptr, "GetCradleFwVersion"}, | ||
| 895 | {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"}, | ||
| 896 | {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"}, | ||
| 897 | {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"}, | ||
| 898 | {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"}, | ||
| 899 | {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"}, | ||
| 900 | {55, nullptr, "IsInControllerFirmwareUpdateSection"}, | ||
| 901 | {59, nullptr, "SetVrPositionForDebug"}, | ||
| 902 | {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, | ||
| 903 | {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, | ||
| 904 | {62, nullptr, "GetHdcpAuthenticationState"}, | ||
| 905 | {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"}, | ||
| 906 | {64, nullptr, "SetTvPowerStateMatchingMode"}, | ||
| 907 | {65, nullptr, "GetApplicationIdByContentActionName"}, | ||
| 908 | {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, | ||
| 909 | {67, nullptr, "CancelCpuBoostMode"}, | ||
| 910 | {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"}, | ||
| 911 | {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"}, | ||
| 912 | {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, | ||
| 913 | {91, nullptr, "GetCurrentPerformanceConfiguration"}, | ||
| 914 | {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, | ||
| 915 | {110, nullptr, "OpenMyGpuErrorHandler"}, | ||
| 916 | {120, nullptr, "GetAppletLaunchedHistory"}, | ||
| 917 | {200, nullptr, "GetOperationModeSystemInfo"}, | ||
| 918 | {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"}, | ||
| 919 | {400, nullptr, "ActivateMigrationService"}, | ||
| 920 | {401, nullptr, "DeactivateMigrationService"}, | ||
| 921 | {500, nullptr, "DisableSleepTillShutdown"}, | ||
| 922 | {501, nullptr, "SuppressDisablingSleepTemporarily"}, | ||
| 923 | {502, nullptr, "IsSleepEnabled"}, | ||
| 924 | {503, nullptr, "IsDisablingSleepSuppressed"}, | ||
| 925 | {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, | ||
| 926 | }; | ||
| 927 | // clang-format on | ||
| 928 | |||
| 929 | RegisterHandlers(functions); | ||
| 930 | |||
| 931 | sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent"); | ||
| 932 | |||
| 933 | // Configure applets to be in foreground state | ||
| 934 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); | ||
| 935 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | ||
| 936 | } | ||
| 937 | |||
| 938 | ICommonStateGetter::~ICommonStateGetter() { | ||
| 939 | service_context.CloseEvent(sleep_lock_event); | ||
| 940 | }; | ||
| 941 | |||
| 942 | void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { | ||
| 943 | LOG_DEBUG(Service_AM, "called"); | ||
| 944 | |||
| 945 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 946 | rb.Push(ResultSuccess); | ||
| 947 | rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode | ||
| 948 | } | ||
| 949 | |||
| 950 | void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) { | ||
| 951 | LOG_DEBUG(Service_AM, "called"); | ||
| 952 | |||
| 953 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 954 | rb.Push(ResultSuccess); | ||
| 955 | rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent()); | ||
| 956 | } | ||
| 957 | |||
| 958 | void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) { | ||
| 959 | LOG_DEBUG(Service_AM, "called"); | ||
| 960 | |||
| 961 | const auto message = msg_queue->PopMessage(); | ||
| 962 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 963 | |||
| 964 | if (message == AppletMessageQueue::AppletMessage::None) { | ||
| 965 | LOG_ERROR(Service_AM, "Message queue is empty"); | ||
| 966 | rb.Push(AM::ResultNoMessages); | ||
| 967 | rb.PushEnum<AppletMessageQueue::AppletMessage>(message); | ||
| 968 | return; | ||
| 969 | } | ||
| 970 | |||
| 971 | rb.Push(ResultSuccess); | ||
| 972 | rb.PushEnum<AppletMessageQueue::AppletMessage>(message); | ||
| 973 | } | ||
| 974 | |||
| 975 | void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) { | ||
| 976 | LOG_DEBUG(Service_AM, "(STUBBED) called"); | ||
| 977 | |||
| 978 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 979 | rb.Push(ResultSuccess); | ||
| 980 | rb.Push(static_cast<u8>(FocusState::InFocus)); | ||
| 981 | } | ||
| 982 | |||
| 983 | void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) { | ||
| 984 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 985 | |||
| 986 | // Sleep lock is acquired immediately. | ||
| 987 | sleep_lock_event->Signal(); | ||
| 988 | |||
| 989 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 990 | rb.Push(ResultSuccess); | ||
| 991 | } | ||
| 992 | |||
| 993 | void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) { | ||
| 994 | IPC::RequestParser rp{ctx}; | ||
| 995 | const auto unknown = rp.Pop<u32>(); | ||
| 996 | |||
| 997 | LOG_INFO(Service_AM, "called, unknown={}", unknown); | ||
| 998 | |||
| 999 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1000 | |||
| 1001 | rb.Push(ResultSuccess); | ||
| 1002 | rb.PushIpcInterface<ILockAccessor>(system); | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) { | ||
| 1006 | LOG_WARNING(Service_AM, "called"); | ||
| 1007 | |||
| 1008 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1009 | rb.Push(ResultSuccess); | ||
| 1010 | rb.PushCopyObjects(sleep_lock_event->GetReadableEvent()); | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { | ||
| 1014 | LOG_DEBUG(Service_AM, "called"); | ||
| 1015 | |||
| 1016 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1017 | rb.Push(ResultSuccess); | ||
| 1018 | rb.Push(vr_mode_state); | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) { | ||
| 1022 | IPC::RequestParser rp{ctx}; | ||
| 1023 | vr_mode_state = rp.Pop<bool>(); | ||
| 1024 | |||
| 1025 | LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off"); | ||
| 1026 | |||
| 1027 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1028 | rb.Push(ResultSuccess); | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) { | ||
| 1032 | IPC::RequestParser rp{ctx}; | ||
| 1033 | const auto is_lcd_backlight_off_enabled = rp.Pop<bool>(); | ||
| 1034 | |||
| 1035 | LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}", | ||
| 1036 | is_lcd_backlight_off_enabled); | ||
| 1037 | |||
| 1038 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1039 | rb.Push(ResultSuccess); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) { | ||
| 1043 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1044 | |||
| 1045 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1046 | rb.Push(ResultSuccess); | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) { | ||
| 1050 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1051 | |||
| 1052 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1053 | rb.Push(ResultSuccess); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) { | ||
| 1057 | LOG_DEBUG(Service_AM, "called"); | ||
| 1058 | |||
| 1059 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1060 | rb.Push(ResultSuccess); | ||
| 1061 | rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent()); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) { | ||
| 1065 | LOG_DEBUG(Service_AM, "called"); | ||
| 1066 | |||
| 1067 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1068 | rb.Push(ResultSuccess); | ||
| 1069 | |||
| 1070 | if (Settings::IsDockedMode()) { | ||
| 1071 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); | ||
| 1072 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); | ||
| 1073 | } else { | ||
| 1074 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); | ||
| 1075 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); | ||
| 1076 | } | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) { | ||
| 1080 | LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS"); | ||
| 1081 | |||
| 1082 | const auto& sm = system.ServiceManager(); | ||
| 1083 | const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys"); | ||
| 1084 | ASSERT(apm_sys != nullptr); | ||
| 1085 | |||
| 1086 | apm_sys->SetCpuBoostMode(ctx); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) { | ||
| 1090 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1091 | |||
| 1092 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1093 | rb.Push(ResultSuccess); | ||
| 1094 | rb.Push(0); | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) { | ||
| 1098 | IPC::RequestParser rp{ctx}; | ||
| 1099 | const auto system_button{rp.PopEnum<SystemButtonType>()}; | ||
| 1100 | |||
| 1101 | LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button); | ||
| 1102 | |||
| 1103 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1104 | rb.Push(ResultSuccess); | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) { | ||
| 1108 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1109 | |||
| 1110 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1111 | rb.Push(ResultSuccess); | ||
| 1112 | rb.PushEnum(SysPlatformRegion::Global); | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled( | ||
| 1116 | HLERequestContext& ctx) { | ||
| 1117 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1118 | |||
| 1119 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1120 | rb.Push(ResultSuccess); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | IStorageImpl::~IStorageImpl() = default; | ||
| 1124 | |||
| 1125 | class StorageDataImpl final : public IStorageImpl { | ||
| 1126 | public: | ||
| 1127 | explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {} | ||
| 1128 | |||
| 1129 | std::vector<u8>& GetData() override { | ||
| 1130 | return buffer; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | const std::vector<u8>& GetData() const override { | ||
| 1134 | return buffer; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | std::size_t GetSize() const override { | ||
| 1138 | return buffer.size(); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | private: | ||
| 1142 | std::vector<u8> buffer; | ||
| 1143 | }; | ||
| 1144 | |||
| 1145 | IStorage::IStorage(Core::System& system_, std::vector<u8>&& buffer) | ||
| 1146 | : ServiceFramework{system_, "IStorage"}, impl{std::make_shared<StorageDataImpl>( | ||
| 1147 | std::move(buffer))} { | ||
| 1148 | Register(); | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | void IStorage::Register() { | ||
| 1152 | // clang-format off | ||
| 1153 | static const FunctionInfo functions[] = { | ||
| 1154 | {0, &IStorage::Open, "Open"}, | ||
| 1155 | {1, nullptr, "OpenTransferStorage"}, | ||
| 1156 | }; | ||
| 1157 | // clang-format on | ||
| 1158 | |||
| 1159 | RegisterHandlers(functions); | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | IStorage::~IStorage() = default; | ||
| 1163 | |||
| 1164 | void IStorage::Open(HLERequestContext& ctx) { | ||
| 1165 | LOG_DEBUG(Service_AM, "called"); | ||
| 1166 | |||
| 1167 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1168 | |||
| 1169 | rb.Push(ResultSuccess); | ||
| 1170 | rb.PushIpcInterface<IStorageAccessor>(system, *this); | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) { | ||
| 1174 | const bool use_docked_mode{Settings::IsDockedMode()}; | ||
| 1175 | LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); | ||
| 1176 | |||
| 1177 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1178 | rb.Push(ResultSuccess); | ||
| 1179 | rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) { | ||
| 1183 | LOG_DEBUG(Service_AM, "called"); | ||
| 1184 | |||
| 1185 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1186 | rb.Push(ResultSuccess); | ||
| 1187 | rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode()); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { | ||
| 1191 | public: | ||
| 1192 | explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<Applets::Applet> applet_) | ||
| 1193 | : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} { | ||
| 1194 | // clang-format off | ||
| 1195 | static const FunctionInfo functions[] = { | ||
| 1196 | {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, | ||
| 1197 | {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, | ||
| 1198 | {10, &ILibraryAppletAccessor::Start, "Start"}, | ||
| 1199 | {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"}, | ||
| 1200 | {25, nullptr, "Terminate"}, | ||
| 1201 | {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, | ||
| 1202 | {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, | ||
| 1203 | {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"}, | ||
| 1204 | {100, &ILibraryAppletAccessor::PushInData, "PushInData"}, | ||
| 1205 | {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"}, | ||
| 1206 | {102, nullptr, "PushExtraStorage"}, | ||
| 1207 | {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"}, | ||
| 1208 | {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"}, | ||
| 1209 | {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"}, | ||
| 1210 | {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"}, | ||
| 1211 | {110, nullptr, "NeedsToExitProcess"}, | ||
| 1212 | {120, nullptr, "GetLibraryAppletInfo"}, | ||
| 1213 | {150, nullptr, "RequestForAppletToGetForeground"}, | ||
| 1214 | {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"}, | ||
| 1215 | }; | ||
| 1216 | // clang-format on | ||
| 1217 | |||
| 1218 | RegisterHandlers(functions); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | private: | ||
| 1222 | void GetAppletStateChangedEvent(HLERequestContext& ctx) { | ||
| 1223 | LOG_DEBUG(Service_AM, "called"); | ||
| 1224 | |||
| 1225 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1226 | rb.Push(ResultSuccess); | ||
| 1227 | rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent()); | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | void IsCompleted(HLERequestContext& ctx) { | ||
| 1231 | LOG_DEBUG(Service_AM, "called"); | ||
| 1232 | |||
| 1233 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1234 | rb.Push(ResultSuccess); | ||
| 1235 | rb.Push<u32>(applet->TransactionComplete()); | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | void GetResult(HLERequestContext& ctx) { | ||
| 1239 | LOG_DEBUG(Service_AM, "called"); | ||
| 1240 | |||
| 1241 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1242 | rb.Push(applet->GetStatus()); | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) { | ||
| 1246 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1247 | |||
| 1248 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1249 | rb.Push(ResultSuccess); | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | void Start(HLERequestContext& ctx) { | ||
| 1253 | LOG_DEBUG(Service_AM, "called"); | ||
| 1254 | |||
| 1255 | ASSERT(applet != nullptr); | ||
| 1256 | |||
| 1257 | applet->Initialize(); | ||
| 1258 | applet->Execute(); | ||
| 1259 | |||
| 1260 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1261 | rb.Push(ResultSuccess); | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | void RequestExit(HLERequestContext& ctx) { | ||
| 1265 | LOG_DEBUG(Service_AM, "called"); | ||
| 1266 | |||
| 1267 | ASSERT(applet != nullptr); | ||
| 1268 | |||
| 1269 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1270 | rb.Push(applet->RequestExit()); | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | void PushInData(HLERequestContext& ctx) { | ||
| 1274 | LOG_DEBUG(Service_AM, "called"); | ||
| 1275 | |||
| 1276 | IPC::RequestParser rp{ctx}; | ||
| 1277 | applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>().lock()); | ||
| 1278 | |||
| 1279 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1280 | rb.Push(ResultSuccess); | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | void PopOutData(HLERequestContext& ctx) { | ||
| 1284 | LOG_DEBUG(Service_AM, "called"); | ||
| 1285 | |||
| 1286 | auto storage = applet->GetBroker().PopNormalDataToGame(); | ||
| 1287 | if (storage == nullptr) { | ||
| 1288 | LOG_DEBUG(Service_AM, | ||
| 1289 | "storage is a nullptr. There is no data in the current normal channel"); | ||
| 1290 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1291 | rb.Push(AM::ResultNoDataInChannel); | ||
| 1292 | return; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1296 | rb.Push(ResultSuccess); | ||
| 1297 | rb.PushIpcInterface<IStorage>(std::move(storage)); | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | void PushInteractiveInData(HLERequestContext& ctx) { | ||
| 1301 | LOG_DEBUG(Service_AM, "called"); | ||
| 1302 | |||
| 1303 | IPC::RequestParser rp{ctx}; | ||
| 1304 | applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>().lock()); | ||
| 1305 | |||
| 1306 | ASSERT(applet->IsInitialized()); | ||
| 1307 | applet->ExecuteInteractive(); | ||
| 1308 | applet->Execute(); | ||
| 1309 | |||
| 1310 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1311 | rb.Push(ResultSuccess); | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | void PopInteractiveOutData(HLERequestContext& ctx) { | ||
| 1315 | LOG_DEBUG(Service_AM, "called"); | ||
| 1316 | |||
| 1317 | auto storage = applet->GetBroker().PopInteractiveDataToGame(); | ||
| 1318 | if (storage == nullptr) { | ||
| 1319 | LOG_DEBUG(Service_AM, | ||
| 1320 | "storage is a nullptr. There is no data in the current interactive channel"); | ||
| 1321 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1322 | rb.Push(AM::ResultNoDataInChannel); | ||
| 1323 | return; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1327 | rb.Push(ResultSuccess); | ||
| 1328 | rb.PushIpcInterface<IStorage>(std::move(storage)); | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | void GetPopOutDataEvent(HLERequestContext& ctx) { | ||
| 1332 | LOG_DEBUG(Service_AM, "called"); | ||
| 1333 | |||
| 1334 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1335 | rb.Push(ResultSuccess); | ||
| 1336 | rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent()); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | void GetPopInteractiveOutDataEvent(HLERequestContext& ctx) { | ||
| 1340 | LOG_DEBUG(Service_AM, "called"); | ||
| 1341 | |||
| 1342 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1343 | rb.Push(ResultSuccess); | ||
| 1344 | rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent()); | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | void GetIndirectLayerConsumerHandle(HLERequestContext& ctx) { | ||
| 1348 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1349 | |||
| 1350 | // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is | ||
| 1351 | // actually used anywhere | ||
| 1352 | constexpr u64 handle = 0xdeadbeef; | ||
| 1353 | |||
| 1354 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1355 | rb.Push(ResultSuccess); | ||
| 1356 | rb.Push(handle); | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | std::shared_ptr<Applets::Applet> applet; | ||
| 1360 | }; | ||
| 1361 | |||
| 1362 | IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_) | ||
| 1363 | : ServiceFramework{system_, "IStorageAccessor"}, backing{backing_} { | ||
| 1364 | // clang-format off | ||
| 1365 | static const FunctionInfo functions[] = { | ||
| 1366 | {0, &IStorageAccessor::GetSize, "GetSize"}, | ||
| 1367 | {10, &IStorageAccessor::Write, "Write"}, | ||
| 1368 | {11, &IStorageAccessor::Read, "Read"}, | ||
| 1369 | }; | ||
| 1370 | // clang-format on | ||
| 1371 | |||
| 1372 | RegisterHandlers(functions); | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | IStorageAccessor::~IStorageAccessor() = default; | ||
| 1376 | |||
| 1377 | void IStorageAccessor::GetSize(HLERequestContext& ctx) { | ||
| 1378 | LOG_DEBUG(Service_AM, "called"); | ||
| 1379 | |||
| 1380 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1381 | |||
| 1382 | rb.Push(ResultSuccess); | ||
| 1383 | rb.Push(static_cast<u64>(backing.GetSize())); | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | void IStorageAccessor::Write(HLERequestContext& ctx) { | ||
| 1387 | IPC::RequestParser rp{ctx}; | ||
| 1388 | |||
| 1389 | const u64 offset{rp.Pop<u64>()}; | ||
| 1390 | const auto data{ctx.ReadBuffer()}; | ||
| 1391 | const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)}; | ||
| 1392 | |||
| 1393 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); | ||
| 1394 | |||
| 1395 | if (offset > backing.GetSize()) { | ||
| 1396 | LOG_ERROR(Service_AM, | ||
| 1397 | "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}", | ||
| 1398 | backing.GetSize(), size, offset); | ||
| 1399 | |||
| 1400 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1401 | rb.Push(AM::ResultInvalidOffset); | ||
| 1402 | return; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | std::memcpy(backing.GetData().data() + offset, data.data(), size); | ||
| 1406 | |||
| 1407 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1408 | rb.Push(ResultSuccess); | ||
| 1409 | } | ||
| 1410 | |||
| 1411 | void IStorageAccessor::Read(HLERequestContext& ctx) { | ||
| 1412 | IPC::RequestParser rp{ctx}; | ||
| 1413 | |||
| 1414 | const u64 offset{rp.Pop<u64>()}; | ||
| 1415 | const std::size_t size{std::min<u64>(ctx.GetWriteBufferSize(), backing.GetSize() - offset)}; | ||
| 1416 | |||
| 1417 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); | ||
| 1418 | |||
| 1419 | if (offset > backing.GetSize()) { | ||
| 1420 | LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}", | ||
| 1421 | backing.GetSize(), size, offset); | ||
| 1422 | |||
| 1423 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1424 | rb.Push(AM::ResultInvalidOffset); | ||
| 1425 | return; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | ctx.WriteBuffer(backing.GetData().data() + offset, size); | ||
| 1429 | |||
| 1430 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1431 | rb.Push(ResultSuccess); | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) | ||
| 1435 | : ServiceFramework{system_, "ILibraryAppletCreator"} { | ||
| 1436 | static const FunctionInfo functions[] = { | ||
| 1437 | {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, | ||
| 1438 | {1, nullptr, "TerminateAllLibraryApplets"}, | ||
| 1439 | {2, nullptr, "AreAnyLibraryAppletsLeft"}, | ||
| 1440 | {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, | ||
| 1441 | {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, | ||
| 1442 | {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"}, | ||
| 1443 | }; | ||
| 1444 | RegisterHandlers(functions); | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | ILibraryAppletCreator::~ILibraryAppletCreator() = default; | ||
| 1448 | |||
| 1449 | void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) { | ||
| 1450 | IPC::RequestParser rp{ctx}; | ||
| 1451 | |||
| 1452 | const auto applet_id = rp.PopRaw<Applets::AppletId>(); | ||
| 1453 | const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>(); | ||
| 1454 | |||
| 1455 | LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, | ||
| 1456 | applet_mode); | ||
| 1457 | |||
| 1458 | const auto& applet_manager{system.GetAppletManager()}; | ||
| 1459 | const auto applet = applet_manager.GetApplet(applet_id, applet_mode); | ||
| 1460 | |||
| 1461 | if (applet == nullptr) { | ||
| 1462 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); | ||
| 1463 | |||
| 1464 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1465 | rb.Push(ResultUnknown); | ||
| 1466 | return; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1470 | |||
| 1471 | rb.Push(ResultSuccess); | ||
| 1472 | rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) { | ||
| 1476 | IPC::RequestParser rp{ctx}; | ||
| 1477 | |||
| 1478 | const s64 size{rp.Pop<s64>()}; | ||
| 1479 | |||
| 1480 | LOG_DEBUG(Service_AM, "called, size={}", size); | ||
| 1481 | |||
| 1482 | if (size <= 0) { | ||
| 1483 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 1484 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1485 | rb.Push(ResultUnknown); | ||
| 1486 | return; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | std::vector<u8> buffer(size); | ||
| 1490 | |||
| 1491 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1492 | rb.Push(ResultSuccess); | ||
| 1493 | rb.PushIpcInterface<IStorage>(system, std::move(buffer)); | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) { | ||
| 1497 | IPC::RequestParser rp{ctx}; | ||
| 1498 | |||
| 1499 | struct Parameters { | ||
| 1500 | u8 permissions; | ||
| 1501 | s64 size; | ||
| 1502 | }; | ||
| 1503 | |||
| 1504 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1505 | const auto handle{ctx.GetCopyHandle(0)}; | ||
| 1506 | |||
| 1507 | LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions, | ||
| 1508 | parameters.size, handle); | ||
| 1509 | |||
| 1510 | if (parameters.size <= 0) { | ||
| 1511 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 1512 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1513 | rb.Push(ResultUnknown); | ||
| 1514 | return; | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); | ||
| 1518 | |||
| 1519 | if (transfer_mem.IsNull()) { | ||
| 1520 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | ||
| 1521 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1522 | rb.Push(ResultUnknown); | ||
| 1523 | return; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | std::vector<u8> memory(transfer_mem->GetSize()); | ||
| 1527 | ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); | ||
| 1528 | |||
| 1529 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1530 | rb.Push(ResultSuccess); | ||
| 1531 | rb.PushIpcInterface<IStorage>(system, std::move(memory)); | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { | ||
| 1535 | IPC::RequestParser rp{ctx}; | ||
| 1536 | |||
| 1537 | const s64 size{rp.Pop<s64>()}; | ||
| 1538 | const auto handle{ctx.GetCopyHandle(0)}; | ||
| 1539 | |||
| 1540 | LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle); | ||
| 1541 | |||
| 1542 | if (size <= 0) { | ||
| 1543 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 1544 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1545 | rb.Push(ResultUnknown); | ||
| 1546 | return; | ||
| 1547 | } | ||
| 1548 | |||
| 1549 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); | ||
| 1550 | |||
| 1551 | if (transfer_mem.IsNull()) { | ||
| 1552 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | ||
| 1553 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1554 | rb.Push(ResultUnknown); | ||
| 1555 | return; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | std::vector<u8> memory(transfer_mem->GetSize()); | ||
| 1559 | ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); | ||
| 1560 | |||
| 1561 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1562 | rb.Push(ResultSuccess); | ||
| 1563 | rb.PushIpcInterface<IStorage>(system, std::move(memory)); | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) | ||
| 1567 | : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} { | ||
| 1568 | // clang-format off | ||
| 1569 | static const FunctionInfo functions[] = { | ||
| 1570 | {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"}, | ||
| 1571 | {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"}, | ||
| 1572 | {2, nullptr, "PopInteractiveInData"}, | ||
| 1573 | {3, nullptr, "PushInteractiveOutData"}, | ||
| 1574 | {5, nullptr, "GetPopInDataEvent"}, | ||
| 1575 | {6, nullptr, "GetPopInteractiveInDataEvent"}, | ||
| 1576 | {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, | ||
| 1577 | {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, | ||
| 1578 | {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"}, | ||
| 1579 | {13, nullptr, "CanUseApplicationCore"}, | ||
| 1580 | {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"}, | ||
| 1581 | {15, nullptr, "GetMainAppletApplicationControlProperty"}, | ||
| 1582 | {16, nullptr, "GetMainAppletStorageId"}, | ||
| 1583 | {17, nullptr, "GetCallerAppletIdentityInfoStack"}, | ||
| 1584 | {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, | ||
| 1585 | {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"}, | ||
| 1586 | {20, nullptr, "PopExtraStorage"}, | ||
| 1587 | {25, nullptr, "GetPopExtraStorageEvent"}, | ||
| 1588 | {30, nullptr, "UnpopInData"}, | ||
| 1589 | {31, nullptr, "UnpopExtraStorage"}, | ||
| 1590 | {40, nullptr, "GetIndirectLayerProducerHandle"}, | ||
| 1591 | {50, nullptr, "ReportVisibleError"}, | ||
| 1592 | {51, nullptr, "ReportVisibleErrorWithErrorContext"}, | ||
| 1593 | {60, nullptr, "GetMainAppletApplicationDesiredLanguage"}, | ||
| 1594 | {70, nullptr, "GetCurrentApplicationId"}, | ||
| 1595 | {80, nullptr, "RequestExitToSelf"}, | ||
| 1596 | {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, | ||
| 1597 | {100, nullptr, "CreateGameMovieTrimmer"}, | ||
| 1598 | {101, nullptr, "ReserveResourceForMovieOperation"}, | ||
| 1599 | {102, nullptr, "UnreserveResourceForMovieOperation"}, | ||
| 1600 | {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"}, | ||
| 1601 | {120, nullptr, "GetLaunchStorageInfoForDebug"}, | ||
| 1602 | {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, | ||
| 1603 | {140, nullptr, "SetApplicationMemoryReservation"}, | ||
| 1604 | {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"}, | ||
| 1605 | }; | ||
| 1606 | // clang-format on | ||
| 1607 | RegisterHandlers(functions); | ||
| 1608 | |||
| 1609 | switch (system.GetAppletManager().GetCurrentAppletId()) { | ||
| 1610 | case Applets::AppletId::Cabinet: | ||
| 1611 | PushInShowCabinetData(); | ||
| 1612 | break; | ||
| 1613 | case Applets::AppletId::MiiEdit: | ||
| 1614 | PushInShowMiiEditData(); | ||
| 1615 | break; | ||
| 1616 | case Applets::AppletId::PhotoViewer: | ||
| 1617 | PushInShowAlbum(); | ||
| 1618 | break; | ||
| 1619 | case Applets::AppletId::SoftwareKeyboard: | ||
| 1620 | PushInShowSoftwareKeyboard(); | ||
| 1621 | break; | ||
| 1622 | case Applets::AppletId::Controller: | ||
| 1623 | PushInShowController(); | ||
| 1624 | break; | ||
| 1625 | default: | ||
| 1626 | break; | ||
| 1627 | } | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; | ||
| 1631 | void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) { | ||
| 1632 | LOG_INFO(Service_AM, "called"); | ||
| 1633 | |||
| 1634 | if (queue_data.empty()) { | ||
| 1635 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1636 | rb.Push(ResultNoDataInChannel); | ||
| 1637 | return; | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | auto data = queue_data.front(); | ||
| 1641 | queue_data.pop_front(); | ||
| 1642 | |||
| 1643 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1644 | rb.Push(ResultSuccess); | ||
| 1645 | rb.PushIpcInterface<IStorage>(system, std::move(data)); | ||
| 1646 | } | ||
| 1647 | |||
| 1648 | void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) { | ||
| 1649 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1650 | |||
| 1651 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1652 | rb.Push(ResultSuccess); | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) { | ||
| 1656 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1657 | |||
| 1658 | system.Exit(); | ||
| 1659 | |||
| 1660 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1661 | rb.Push(ResultSuccess); | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) { | ||
| 1665 | struct LibraryAppletInfo { | ||
| 1666 | Applets::AppletId applet_id; | ||
| 1667 | Applets::LibraryAppletMode library_applet_mode; | ||
| 1668 | }; | ||
| 1669 | |||
| 1670 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1671 | |||
| 1672 | const LibraryAppletInfo applet_info{ | ||
| 1673 | .applet_id = system.GetAppletManager().GetCurrentAppletId(), | ||
| 1674 | .library_applet_mode = Applets::LibraryAppletMode::AllForeground, | ||
| 1675 | }; | ||
| 1676 | |||
| 1677 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1678 | rb.Push(ResultSuccess); | ||
| 1679 | rb.PushRaw(applet_info); | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) { | ||
| 1683 | struct AppletIdentityInfo { | ||
| 1684 | Applets::AppletId applet_id; | ||
| 1685 | INSERT_PADDING_BYTES(0x4); | ||
| 1686 | u64 application_id; | ||
| 1687 | }; | ||
| 1688 | static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); | ||
| 1689 | |||
| 1690 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1691 | |||
| 1692 | const AppletIdentityInfo applet_info{ | ||
| 1693 | .applet_id = Applets::AppletId::QLaunch, | ||
| 1694 | .application_id = 0x0100000000001000ull, | ||
| 1695 | }; | ||
| 1696 | |||
| 1697 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 1698 | rb.Push(ResultSuccess); | ||
| 1699 | rb.PushRaw(applet_info); | ||
| 1700 | } | ||
| 1701 | |||
| 1702 | void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { | ||
| 1703 | struct AppletIdentityInfo { | ||
| 1704 | Applets::AppletId applet_id; | ||
| 1705 | INSERT_PADDING_BYTES(0x4); | ||
| 1706 | u64 application_id; | ||
| 1707 | }; | ||
| 1708 | static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); | ||
| 1709 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1710 | |||
| 1711 | const AppletIdentityInfo applet_info{ | ||
| 1712 | .applet_id = Applets::AppletId::QLaunch, | ||
| 1713 | .application_id = 0x0100000000001000ull, | ||
| 1714 | }; | ||
| 1715 | |||
| 1716 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 1717 | rb.Push(ResultSuccess); | ||
| 1718 | rb.PushRaw(applet_info); | ||
| 1719 | } | ||
| 1720 | |||
| 1721 | void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) { | ||
| 1722 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1723 | |||
| 1724 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1725 | rb.Push(ResultSuccess); | ||
| 1726 | rb.Push<u32>(0); | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) { | ||
| 1730 | const Service::Account::ProfileManager manager{}; | ||
| 1731 | bool is_empty{true}; | ||
| 1732 | s32 user_count{-1}; | ||
| 1733 | |||
| 1734 | LOG_INFO(Service_AM, "called"); | ||
| 1735 | |||
| 1736 | if (manager.GetUserCount() > 0) { | ||
| 1737 | is_empty = false; | ||
| 1738 | user_count = static_cast<s32>(manager.GetUserCount()); | ||
| 1739 | ctx.WriteBuffer(manager.GetAllUsers()); | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1743 | rb.Push(ResultSuccess); | ||
| 1744 | rb.Push<u8>(is_empty); | ||
| 1745 | rb.Push(user_count); | ||
| 1746 | } | ||
| 1747 | |||
| 1748 | void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) { | ||
| 1749 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1750 | |||
| 1751 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1752 | rb.Push(ResultSuccess); | ||
| 1753 | rb.Push<u8>(0); | ||
| 1754 | } | ||
| 1755 | |||
| 1756 | void ILibraryAppletSelfAccessor::PushInShowAlbum() { | ||
| 1757 | const Applets::CommonArguments arguments{ | ||
| 1758 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 1759 | .size = Applets::CommonArgumentSize::Version3, | ||
| 1760 | .library_version = 1, | ||
| 1761 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 1762 | .play_startup_sound = true, | ||
| 1763 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 1764 | }; | ||
| 1765 | |||
| 1766 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 1767 | std::vector<u8> settings_data{2}; | ||
| 1768 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 1769 | queue_data.emplace_back(std::move(argument_data)); | ||
| 1770 | queue_data.emplace_back(std::move(settings_data)); | ||
| 1771 | } | ||
| 1772 | |||
| 1773 | void ILibraryAppletSelfAccessor::PushInShowController() { | ||
| 1774 | const Applets::CommonArguments common_args = { | ||
| 1775 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 1776 | .size = Applets::CommonArgumentSize::Version3, | ||
| 1777 | .library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8), | ||
| 1778 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 1779 | .play_startup_sound = true, | ||
| 1780 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 1781 | }; | ||
| 1782 | |||
| 1783 | Applets::ControllerSupportArgNew user_args = { | ||
| 1784 | .header = {.player_count_min = 1, | ||
| 1785 | .player_count_max = 4, | ||
| 1786 | .enable_take_over_connection = true, | ||
| 1787 | .enable_left_justify = false, | ||
| 1788 | .enable_permit_joy_dual = true, | ||
| 1789 | .enable_single_mode = false, | ||
| 1790 | .enable_identification_color = false}, | ||
| 1791 | .identification_colors = {}, | ||
| 1792 | .enable_explain_text = false, | ||
| 1793 | .explain_text = {}, | ||
| 1794 | }; | ||
| 1795 | |||
| 1796 | Applets::ControllerSupportArgPrivate private_args = { | ||
| 1797 | .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate), | ||
| 1798 | .arg_size = sizeof(Applets::ControllerSupportArgNew), | ||
| 1799 | .is_home_menu = true, | ||
| 1800 | .flag_1 = true, | ||
| 1801 | .mode = Applets::ControllerSupportMode::ShowControllerSupport, | ||
| 1802 | .caller = Applets::ControllerSupportCaller:: | ||
| 1803 | Application, // switchbrew: Always zero except with | ||
| 1804 | // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem, | ||
| 1805 | // which sets this to the input param | ||
| 1806 | .style_set = Core::HID::NpadStyleSet::None, | ||
| 1807 | .joy_hold_type = 0, | ||
| 1808 | }; | ||
| 1809 | std::vector<u8> common_args_data(sizeof(common_args)); | ||
| 1810 | std::vector<u8> private_args_data(sizeof(private_args)); | ||
| 1811 | std::vector<u8> user_args_data(sizeof(user_args)); | ||
| 1812 | |||
| 1813 | std::memcpy(common_args_data.data(), &common_args, sizeof(common_args)); | ||
| 1814 | std::memcpy(private_args_data.data(), &private_args, sizeof(private_args)); | ||
| 1815 | std::memcpy(user_args_data.data(), &user_args, sizeof(user_args)); | ||
| 1816 | |||
| 1817 | queue_data.emplace_back(std::move(common_args_data)); | ||
| 1818 | queue_data.emplace_back(std::move(private_args_data)); | ||
| 1819 | queue_data.emplace_back(std::move(user_args_data)); | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | void ILibraryAppletSelfAccessor::PushInShowCabinetData() { | ||
| 1823 | const Applets::CommonArguments arguments{ | ||
| 1824 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 1825 | .size = Applets::CommonArgumentSize::Version3, | ||
| 1826 | .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1), | ||
| 1827 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 1828 | .play_startup_sound = true, | ||
| 1829 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 1830 | }; | ||
| 1831 | |||
| 1832 | const Applets::StartParamForAmiiboSettings amiibo_settings{ | ||
| 1833 | .param_1 = 0, | ||
| 1834 | .applet_mode = system.GetAppletManager().GetCabinetMode(), | ||
| 1835 | .flags = Applets::CabinetFlags::None, | ||
| 1836 | .amiibo_settings_1 = 0, | ||
| 1837 | .device_handle = 0, | ||
| 1838 | .tag_info{}, | ||
| 1839 | .register_info{}, | ||
| 1840 | .amiibo_settings_3{}, | ||
| 1841 | }; | ||
| 1842 | |||
| 1843 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 1844 | std::vector<u8> settings_data(sizeof(amiibo_settings)); | ||
| 1845 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 1846 | std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings)); | ||
| 1847 | queue_data.emplace_back(std::move(argument_data)); | ||
| 1848 | queue_data.emplace_back(std::move(settings_data)); | ||
| 1849 | } | ||
| 1850 | |||
| 1851 | void ILibraryAppletSelfAccessor::PushInShowMiiEditData() { | ||
| 1852 | struct MiiEditV3 { | ||
| 1853 | Applets::MiiEditAppletInputCommon common; | ||
| 1854 | Applets::MiiEditAppletInputV3 input; | ||
| 1855 | }; | ||
| 1856 | static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size."); | ||
| 1857 | |||
| 1858 | MiiEditV3 mii_arguments{ | ||
| 1859 | .common = | ||
| 1860 | { | ||
| 1861 | .version = Applets::MiiEditAppletVersion::Version3, | ||
| 1862 | .applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit, | ||
| 1863 | }, | ||
| 1864 | .input{}, | ||
| 1865 | }; | ||
| 1866 | |||
| 1867 | std::vector<u8> argument_data(sizeof(mii_arguments)); | ||
| 1868 | std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments)); | ||
| 1869 | |||
| 1870 | queue_data.emplace_back(std::move(argument_data)); | ||
| 1871 | } | ||
| 1872 | |||
| 1873 | void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() { | ||
| 1874 | const Applets::CommonArguments arguments{ | ||
| 1875 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 1876 | .size = Applets::CommonArgumentSize::Version3, | ||
| 1877 | .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301), | ||
| 1878 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 1879 | .play_startup_sound = true, | ||
| 1880 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 1881 | }; | ||
| 1882 | |||
| 1883 | std::vector<char16_t> initial_string(0); | ||
| 1884 | |||
| 1885 | const Applets::SwkbdConfigCommon swkbd_config{ | ||
| 1886 | .type = Applets::SwkbdType::Qwerty, | ||
| 1887 | .ok_text{}, | ||
| 1888 | .left_optional_symbol_key{}, | ||
| 1889 | .right_optional_symbol_key{}, | ||
| 1890 | .use_prediction = false, | ||
| 1891 | .key_disable_flags{}, | ||
| 1892 | .initial_cursor_position = Applets::SwkbdInitialCursorPosition::Start, | ||
| 1893 | .header_text{}, | ||
| 1894 | .sub_text{}, | ||
| 1895 | .guide_text{}, | ||
| 1896 | .max_text_length = 500, | ||
| 1897 | .min_text_length = 0, | ||
| 1898 | .password_mode = Applets::SwkbdPasswordMode::Disabled, | ||
| 1899 | .text_draw_type = Applets::SwkbdTextDrawType::Box, | ||
| 1900 | .enable_return_button = true, | ||
| 1901 | .use_utf8 = false, | ||
| 1902 | .use_blur_background = true, | ||
| 1903 | .initial_string_offset{}, | ||
| 1904 | .initial_string_length = static_cast<u32>(initial_string.size()), | ||
| 1905 | .user_dictionary_offset{}, | ||
| 1906 | .user_dictionary_entries{}, | ||
| 1907 | .use_text_check = false, | ||
| 1908 | }; | ||
| 1909 | |||
| 1910 | Applets::SwkbdConfigNew swkbd_config_new{}; | ||
| 1911 | |||
| 1912 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 1913 | std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new)); | ||
| 1914 | std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t)); | ||
| 1915 | |||
| 1916 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 1917 | std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config)); | ||
| 1918 | std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new, | ||
| 1919 | sizeof(Applets::SwkbdConfigNew)); | ||
| 1920 | std::memcpy(work_buffer.data(), initial_string.data(), | ||
| 1921 | swkbd_config.initial_string_length * sizeof(char16_t)); | ||
| 1922 | |||
| 1923 | queue_data.emplace_back(std::move(argument_data)); | ||
| 1924 | queue_data.emplace_back(std::move(swkbd_data)); | ||
| 1925 | queue_data.emplace_back(std::move(work_buffer)); | ||
| 1926 | } | ||
| 1927 | |||
| 1928 | IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_) | ||
| 1929 | : ServiceFramework{system_, "IAppletCommonFunctions"} { | ||
| 1930 | // clang-format off | ||
| 1931 | static const FunctionInfo functions[] = { | ||
| 1932 | {0, nullptr, "SetTerminateResult"}, | ||
| 1933 | {10, nullptr, "ReadThemeStorage"}, | ||
| 1934 | {11, nullptr, "WriteThemeStorage"}, | ||
| 1935 | {20, nullptr, "PushToAppletBoundChannel"}, | ||
| 1936 | {21, nullptr, "TryPopFromAppletBoundChannel"}, | ||
| 1937 | {40, nullptr, "GetDisplayLogicalResolution"}, | ||
| 1938 | {42, nullptr, "SetDisplayMagnification"}, | ||
| 1939 | {50, nullptr, "SetHomeButtonDoubleClickEnabled"}, | ||
| 1940 | {51, nullptr, "GetHomeButtonDoubleClickEnabled"}, | ||
| 1941 | {52, nullptr, "IsHomeButtonShortPressedBlocked"}, | ||
| 1942 | {60, nullptr, "IsVrModeCurtainRequired"}, | ||
| 1943 | {61, nullptr, "IsSleepRequiredByHighTemperature"}, | ||
| 1944 | {62, nullptr, "IsSleepRequiredByLowBattery"}, | ||
| 1945 | {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"}, | ||
| 1946 | {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"}, | ||
| 1947 | {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"}, | ||
| 1948 | {90, nullptr, "OpenNamedChannelAsParent"}, | ||
| 1949 | {91, nullptr, "OpenNamedChannelAsChild"}, | ||
| 1950 | {100, nullptr, "SetApplicationCoreUsageMode"}, | ||
| 1951 | }; | ||
| 1952 | // clang-format on | ||
| 1953 | |||
| 1954 | RegisterHandlers(functions); | ||
| 1955 | } | ||
| 1956 | |||
| 1957 | IAppletCommonFunctions::~IAppletCommonFunctions() = default; | ||
| 1958 | |||
| 1959 | void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) { | ||
| 1960 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1961 | |||
| 1962 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1963 | rb.Push(ResultSuccess); | ||
| 1964 | } | ||
| 1965 | |||
| 1966 | IApplicationFunctions::IApplicationFunctions(Core::System& system_) | ||
| 1967 | : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system, | ||
| 1968 | "IApplicationFunctions"} { | ||
| 1969 | // clang-format off | ||
| 1970 | static const FunctionInfo functions[] = { | ||
| 1971 | {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, | ||
| 1972 | {10, nullptr, "CreateApplicationAndPushAndRequestToStart"}, | ||
| 1973 | {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"}, | ||
| 1974 | {12, nullptr, "CreateApplicationAndRequestToStart"}, | ||
| 1975 | {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"}, | ||
| 1976 | {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"}, | ||
| 1977 | {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"}, | ||
| 1978 | {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"}, | ||
| 1979 | {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"}, | ||
| 1980 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, | ||
| 1981 | {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"}, | ||
| 1982 | {24, nullptr, "GetLaunchStorageInfoForDebug"}, | ||
| 1983 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, | ||
| 1984 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, | ||
| 1985 | {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"}, | ||
| 1986 | {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"}, | ||
| 1987 | {29, nullptr, "GetCacheStorageMax"}, | ||
| 1988 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, | ||
| 1989 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, | ||
| 1990 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, | ||
| 1991 | {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"}, | ||
| 1992 | {34, nullptr, "SelectApplicationLicense"}, | ||
| 1993 | {35, nullptr, "GetDeviceSaveDataSizeMax"}, | ||
| 1994 | {36, nullptr, "GetLimitedApplicationLicense"}, | ||
| 1995 | {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"}, | ||
| 1996 | {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, | ||
| 1997 | {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, | ||
| 1998 | {60, nullptr, "SetMediaPlaybackStateForApplication"}, | ||
| 1999 | {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"}, | ||
| 2000 | {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"}, | ||
| 2001 | {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, | ||
| 2002 | {68, nullptr, "RequestFlushGamePlayingMovieForDebug"}, | ||
| 2003 | {70, nullptr, "RequestToShutdown"}, | ||
| 2004 | {71, nullptr, "RequestToReboot"}, | ||
| 2005 | {72, nullptr, "RequestToSleep"}, | ||
| 2006 | {80, nullptr, "ExitAndRequestToShowThanksMessage"}, | ||
| 2007 | {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"}, | ||
| 2008 | {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"}, | ||
| 2009 | {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"}, | ||
| 2010 | {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"}, | ||
| 2011 | {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"}, | ||
| 2012 | {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"}, | ||
| 2013 | {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"}, | ||
| 2014 | {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"}, | ||
| 2015 | {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"}, | ||
| 2016 | {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, | ||
| 2017 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, | ||
| 2018 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, | ||
| 2019 | {131, nullptr, "SetDelayTimeToAbortOnGpuError"}, | ||
| 2020 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, | ||
| 2021 | {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, | ||
| 2022 | {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"}, | ||
| 2023 | {151, nullptr, "TryPopFromNotificationStorageChannel"}, | ||
| 2024 | {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"}, | ||
| 2025 | {170, nullptr, "SetHdcpAuthenticationActivated"}, | ||
| 2026 | {180, nullptr, "GetLaunchRequiredVersion"}, | ||
| 2027 | {181, nullptr, "UpgradeLaunchRequiredVersion"}, | ||
| 2028 | {190, nullptr, "SendServerMaintenanceOverlayNotification"}, | ||
| 2029 | {200, nullptr, "GetLastApplicationExitReason"}, | ||
| 2030 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, | ||
| 2031 | {1000, nullptr, "CreateMovieMaker"}, | ||
| 2032 | {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"}, | ||
| 2033 | }; | ||
| 2034 | // clang-format on | ||
| 2035 | |||
| 2036 | RegisterHandlers(functions); | ||
| 2037 | |||
| 2038 | gpu_error_detected_event = | ||
| 2039 | service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent"); | ||
| 2040 | friend_invitation_storage_channel_event = | ||
| 2041 | service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent"); | ||
| 2042 | notification_storage_channel_event = | ||
| 2043 | service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent"); | ||
| 2044 | health_warning_disappeared_system_event = | ||
| 2045 | service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent"); | ||
| 2046 | } | ||
| 2047 | |||
| 2048 | IApplicationFunctions::~IApplicationFunctions() { | ||
| 2049 | service_context.CloseEvent(gpu_error_detected_event); | ||
| 2050 | service_context.CloseEvent(friend_invitation_storage_channel_event); | ||
| 2051 | service_context.CloseEvent(notification_storage_channel_event); | ||
| 2052 | service_context.CloseEvent(health_warning_disappeared_system_event); | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) { | ||
| 2056 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2057 | |||
| 2058 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2059 | rb.Push(ResultSuccess); | ||
| 2060 | } | ||
| 2061 | |||
| 2062 | void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) { | ||
| 2063 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2064 | |||
| 2065 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2066 | rb.Push(ResultSuccess); | ||
| 2067 | } | ||
| 2068 | |||
| 2069 | void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) { | ||
| 2070 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2071 | |||
| 2072 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2073 | rb.Push(ResultSuccess); | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) { | ||
| 2077 | IPC::RequestParser rp{ctx}; | ||
| 2078 | const auto is_visible = rp.Pop<bool>(); | ||
| 2079 | |||
| 2080 | LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible); | ||
| 2081 | |||
| 2082 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2083 | rb.Push(ResultSuccess); | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { | ||
| 2087 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2088 | |||
| 2089 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2090 | rb.Push(ResultSuccess); | ||
| 2091 | } | ||
| 2092 | |||
| 2093 | void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { | ||
| 2094 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2095 | |||
| 2096 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2097 | rb.Push(ResultSuccess); | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) { | ||
| 2101 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2102 | |||
| 2103 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2104 | rb.Push(ResultSuccess); | ||
| 2105 | } | ||
| 2106 | |||
| 2107 | void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) { | ||
| 2108 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2109 | |||
| 2110 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2111 | rb.Push(ResultSuccess); | ||
| 2112 | } | ||
| 2113 | |||
| 2114 | void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) { | ||
| 2115 | IPC::RequestParser rp{ctx}; | ||
| 2116 | const auto kind = rp.PopEnum<LaunchParameterKind>(); | ||
| 2117 | |||
| 2118 | LOG_INFO(Service_AM, "called, kind={:08X}", kind); | ||
| 2119 | |||
| 2120 | if (kind == LaunchParameterKind::UserChannel) { | ||
| 2121 | auto channel = system.GetUserChannel(); | ||
| 2122 | if (channel.empty()) { | ||
| 2123 | LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!"); | ||
| 2124 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2125 | rb.Push(AM::ResultNoDataInChannel); | ||
| 2126 | return; | ||
| 2127 | } | ||
| 2128 | |||
| 2129 | auto data = channel.back(); | ||
| 2130 | channel.pop_back(); | ||
| 2131 | |||
| 2132 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 2133 | rb.Push(ResultSuccess); | ||
| 2134 | rb.PushIpcInterface<IStorage>(system, std::move(data)); | ||
| 2135 | } else if (kind == LaunchParameterKind::AccountPreselectedUser && | ||
| 2136 | !launch_popped_account_preselect) { | ||
| 2137 | // TODO: Verify this is hw-accurate | ||
| 2138 | LaunchParameterAccountPreselectedUser params{}; | ||
| 2139 | |||
| 2140 | params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC; | ||
| 2141 | params.is_account_selected = 1; | ||
| 2142 | |||
| 2143 | Account::ProfileManager profile_manager{}; | ||
| 2144 | const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user)); | ||
| 2145 | ASSERT(uuid.has_value() && uuid->IsValid()); | ||
| 2146 | params.current_user = *uuid; | ||
| 2147 | |||
| 2148 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 2149 | rb.Push(ResultSuccess); | ||
| 2150 | |||
| 2151 | std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); | ||
| 2152 | std::memcpy(buffer.data(), ¶ms, buffer.size()); | ||
| 2153 | |||
| 2154 | rb.PushIpcInterface<IStorage>(system, std::move(buffer)); | ||
| 2155 | launch_popped_account_preselect = true; | ||
| 2156 | } else { | ||
| 2157 | LOG_ERROR(Service_AM, "Unknown launch parameter kind."); | ||
| 2158 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2159 | rb.Push(AM::ResultNoDataInChannel); | ||
| 2160 | } | ||
| 2161 | } | ||
| 2162 | |||
| 2163 | void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { | ||
| 2164 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2165 | |||
| 2166 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2167 | rb.Push(ResultSuccess); | ||
| 2168 | } | ||
| 2169 | |||
| 2170 | void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) { | ||
| 2171 | IPC::RequestParser rp{ctx}; | ||
| 2172 | u128 user_id = rp.PopRaw<u128>(); | ||
| 2173 | |||
| 2174 | LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); | ||
| 2175 | |||
| 2176 | FileSys::SaveDataAttribute attribute{}; | ||
| 2177 | attribute.title_id = system.GetApplicationProcessProgramID(); | ||
| 2178 | attribute.user_id = user_id; | ||
| 2179 | attribute.type = FileSys::SaveDataType::SaveData; | ||
| 2180 | |||
| 2181 | FileSys::VirtualDir save_data{}; | ||
| 2182 | const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData( | ||
| 2183 | &save_data, FileSys::SaveDataSpaceId::NandUser, attribute); | ||
| 2184 | |||
| 2185 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 2186 | rb.Push(res); | ||
| 2187 | rb.Push<u64>(0); | ||
| 2188 | } | ||
| 2189 | |||
| 2190 | void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) { | ||
| 2191 | // Takes an input u32 Result, no output. | ||
| 2192 | // For example, in some cases official apps use this with error 0x2A2 then | ||
| 2193 | // uses svcBreak. | ||
| 2194 | |||
| 2195 | IPC::RequestParser rp{ctx}; | ||
| 2196 | u32 result = rp.Pop<u32>(); | ||
| 2197 | LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result); | ||
| 2198 | |||
| 2199 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2200 | rb.Push(ResultSuccess); | ||
| 2201 | } | ||
| 2202 | |||
| 2203 | void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) { | ||
| 2204 | LOG_DEBUG(Service_AM, "called"); | ||
| 2205 | |||
| 2206 | std::array<u8, 0x10> version_string{}; | ||
| 2207 | |||
| 2208 | const auto res = [this] { | ||
| 2209 | const auto title_id = system.GetApplicationProcessProgramID(); | ||
| 2210 | |||
| 2211 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | ||
| 2212 | system.GetContentProvider()}; | ||
| 2213 | auto metadata = pm.GetControlMetadata(); | ||
| 2214 | if (metadata.first != nullptr) { | ||
| 2215 | return metadata; | ||
| 2216 | } | ||
| 2217 | |||
| 2218 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | ||
| 2219 | system.GetFileSystemController(), | ||
| 2220 | system.GetContentProvider()}; | ||
| 2221 | return pm_update.GetControlMetadata(); | ||
| 2222 | }(); | ||
| 2223 | |||
| 2224 | if (res.first != nullptr) { | ||
| 2225 | const auto& version = res.first->GetVersionString(); | ||
| 2226 | std::copy(version.begin(), version.end(), version_string.begin()); | ||
| 2227 | } else { | ||
| 2228 | static constexpr char default_version[]{"1.0.0"}; | ||
| 2229 | std::memcpy(version_string.data(), default_version, sizeof(default_version)); | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2233 | rb.Push(ResultSuccess); | ||
| 2234 | rb.PushRaw(version_string); | ||
| 2235 | } | ||
| 2236 | |||
| 2237 | void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { | ||
| 2238 | // TODO(bunnei): This should be configurable | ||
| 2239 | LOG_DEBUG(Service_AM, "called"); | ||
| 2240 | |||
| 2241 | // Get supported languages from NACP, if possible | ||
| 2242 | // Default to 0 (all languages supported) | ||
| 2243 | u32 supported_languages = 0; | ||
| 2244 | |||
| 2245 | const auto res = [this] { | ||
| 2246 | const auto title_id = system.GetApplicationProcessProgramID(); | ||
| 2247 | |||
| 2248 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | ||
| 2249 | system.GetContentProvider()}; | ||
| 2250 | auto metadata = pm.GetControlMetadata(); | ||
| 2251 | if (metadata.first != nullptr) { | ||
| 2252 | return metadata; | ||
| 2253 | } | ||
| 2254 | |||
| 2255 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | ||
| 2256 | system.GetFileSystemController(), | ||
| 2257 | system.GetContentProvider()}; | ||
| 2258 | return pm_update.GetControlMetadata(); | ||
| 2259 | }(); | ||
| 2260 | |||
| 2261 | if (res.first != nullptr) { | ||
| 2262 | supported_languages = res.first->GetSupportedLanguages(); | ||
| 2263 | } | ||
| 2264 | |||
| 2265 | // Call IApplicationManagerInterface implementation. | ||
| 2266 | auto& service_manager = system.ServiceManager(); | ||
| 2267 | auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); | ||
| 2268 | auto app_man = ns_am2->GetApplicationManagerInterface(); | ||
| 2269 | |||
| 2270 | // Get desired application language | ||
| 2271 | u8 desired_language{}; | ||
| 2272 | const auto res_lang = | ||
| 2273 | app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); | ||
| 2274 | if (res_lang != ResultSuccess) { | ||
| 2275 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2276 | rb.Push(res_lang); | ||
| 2277 | return; | ||
| 2278 | } | ||
| 2279 | |||
| 2280 | // Convert to settings language code. | ||
| 2281 | u64 language_code{}; | ||
| 2282 | const auto res_code = | ||
| 2283 | app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); | ||
| 2284 | if (res_code != ResultSuccess) { | ||
| 2285 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2286 | rb.Push(res_code); | ||
| 2287 | return; | ||
| 2288 | } | ||
| 2289 | |||
| 2290 | LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); | ||
| 2291 | |||
| 2292 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 2293 | rb.Push(ResultSuccess); | ||
| 2294 | rb.Push(language_code); | ||
| 2295 | } | ||
| 2296 | |||
| 2297 | void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { | ||
| 2298 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2299 | |||
| 2300 | constexpr bool gameplay_recording_supported = false; | ||
| 2301 | |||
| 2302 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2303 | rb.Push(ResultSuccess); | ||
| 2304 | rb.Push(gameplay_recording_supported); | ||
| 2305 | } | ||
| 2306 | |||
| 2307 | void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) { | ||
| 2308 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2309 | |||
| 2310 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2311 | rb.Push(ResultSuccess); | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) { | ||
| 2315 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2316 | |||
| 2317 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2318 | rb.Push(ResultSuccess); | ||
| 2319 | } | ||
| 2320 | |||
| 2321 | void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) { | ||
| 2322 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2323 | |||
| 2324 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2325 | rb.Push(ResultSuccess); | ||
| 2326 | rb.Push<u8>(0); // Unknown, seems to be ignored by official processes | ||
| 2327 | } | ||
| 2328 | |||
| 2329 | void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) { | ||
| 2330 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2331 | |||
| 2332 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2333 | rb.Push(ResultSuccess); | ||
| 2334 | |||
| 2335 | // Returns a 128-bit UUID | ||
| 2336 | rb.Push<u64>(0); | ||
| 2337 | rb.Push<u64>(0); | ||
| 2338 | } | ||
| 2339 | |||
| 2340 | void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) { | ||
| 2341 | struct Parameters { | ||
| 2342 | FileSys::SaveDataType type; | ||
| 2343 | u128 user_id; | ||
| 2344 | u64 new_normal_size; | ||
| 2345 | u64 new_journal_size; | ||
| 2346 | }; | ||
| 2347 | static_assert(sizeof(Parameters) == 40); | ||
| 2348 | |||
| 2349 | IPC::RequestParser rp{ctx}; | ||
| 2350 | const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>(); | ||
| 2351 | |||
| 2352 | LOG_DEBUG(Service_AM, | ||
| 2353 | "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, " | ||
| 2354 | "new_journal={:016X}", | ||
| 2355 | static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size); | ||
| 2356 | |||
| 2357 | system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize( | ||
| 2358 | type, system.GetApplicationProcessProgramID(), user_id, | ||
| 2359 | {new_normal_size, new_journal_size}); | ||
| 2360 | |||
| 2361 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 2362 | rb.Push(ResultSuccess); | ||
| 2363 | |||
| 2364 | // The following value is used upon failure to help the system recover. | ||
| 2365 | // Since we always succeed, this should be 0. | ||
| 2366 | rb.Push<u64>(0); | ||
| 2367 | } | ||
| 2368 | |||
| 2369 | void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) { | ||
| 2370 | struct Parameters { | ||
| 2371 | FileSys::SaveDataType type; | ||
| 2372 | u128 user_id; | ||
| 2373 | }; | ||
| 2374 | static_assert(sizeof(Parameters) == 24); | ||
| 2375 | |||
| 2376 | IPC::RequestParser rp{ctx}; | ||
| 2377 | const auto [type, user_id] = rp.PopRaw<Parameters>(); | ||
| 2378 | |||
| 2379 | LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1], | ||
| 2380 | user_id[0]); | ||
| 2381 | |||
| 2382 | const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize( | ||
| 2383 | type, system.GetApplicationProcessProgramID(), user_id); | ||
| 2384 | |||
| 2385 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2386 | rb.Push(ResultSuccess); | ||
| 2387 | rb.Push(size.normal); | ||
| 2388 | rb.Push(size.journal); | ||
| 2389 | } | ||
| 2390 | |||
| 2391 | void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) { | ||
| 2392 | struct InputParameters { | ||
| 2393 | u16 index; | ||
| 2394 | s64 size; | ||
| 2395 | s64 journal_size; | ||
| 2396 | }; | ||
| 2397 | static_assert(sizeof(InputParameters) == 24); | ||
| 2398 | |||
| 2399 | struct OutputParameters { | ||
| 2400 | u32 storage_target; | ||
| 2401 | u64 required_size; | ||
| 2402 | }; | ||
| 2403 | static_assert(sizeof(OutputParameters) == 16); | ||
| 2404 | |||
| 2405 | IPC::RequestParser rp{ctx}; | ||
| 2406 | const auto params = rp.PopRaw<InputParameters>(); | ||
| 2407 | |||
| 2408 | LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}", | ||
| 2409 | params.index, params.size, params.journal_size); | ||
| 2410 | |||
| 2411 | const OutputParameters resp{ | ||
| 2412 | .storage_target = 1, | ||
| 2413 | .required_size = 0, | ||
| 2414 | }; | ||
| 2415 | |||
| 2416 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2417 | rb.Push(ResultSuccess); | ||
| 2418 | rb.PushRaw(resp); | ||
| 2419 | } | ||
| 2420 | |||
| 2421 | void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) { | ||
| 2422 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2423 | |||
| 2424 | constexpr u64 size_max_normal = 0xFFFFFFF; | ||
| 2425 | constexpr u64 size_max_journal = 0xFFFFFFF; | ||
| 2426 | |||
| 2427 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2428 | rb.Push(ResultSuccess); | ||
| 2429 | rb.Push(size_max_normal); | ||
| 2430 | rb.Push(size_max_journal); | ||
| 2431 | } | ||
| 2432 | |||
| 2433 | void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) { | ||
| 2434 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2435 | |||
| 2436 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2437 | rb.Push(ResultSuccess); | ||
| 2438 | rb.Push<u32>(0); | ||
| 2439 | } | ||
| 2440 | |||
| 2441 | void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) { | ||
| 2442 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2443 | |||
| 2444 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2445 | rb.Push(ResultSuccess); | ||
| 2446 | rb.Push<u32>(0); | ||
| 2447 | } | ||
| 2448 | |||
| 2449 | void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) { | ||
| 2450 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2451 | |||
| 2452 | IPC::RequestParser rp{ctx}; | ||
| 2453 | [[maybe_unused]] const auto unk_1 = rp.Pop<u32>(); | ||
| 2454 | [[maybe_unused]] const auto unk_2 = rp.Pop<u32>(); | ||
| 2455 | const auto program_index = rp.Pop<u64>(); | ||
| 2456 | |||
| 2457 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2458 | rb.Push(ResultSuccess); | ||
| 2459 | |||
| 2460 | system.ExecuteProgram(program_index); | ||
| 2461 | } | ||
| 2462 | |||
| 2463 | void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) { | ||
| 2464 | LOG_DEBUG(Service_AM, "called"); | ||
| 2465 | |||
| 2466 | system.GetUserChannel().clear(); | ||
| 2467 | |||
| 2468 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2469 | rb.Push(ResultSuccess); | ||
| 2470 | } | ||
| 2471 | |||
| 2472 | void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) { | ||
| 2473 | LOG_DEBUG(Service_AM, "called"); | ||
| 2474 | |||
| 2475 | IPC::RequestParser rp{ctx}; | ||
| 2476 | const auto storage = rp.PopIpcInterface<IStorage>().lock(); | ||
| 2477 | if (storage) { | ||
| 2478 | system.GetUserChannel().push_back(storage->GetData()); | ||
| 2479 | } | ||
| 2480 | |||
| 2481 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2482 | rb.Push(ResultSuccess); | ||
| 2483 | } | ||
| 2484 | |||
| 2485 | void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) { | ||
| 2486 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2487 | |||
| 2488 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2489 | rb.Push(ResultSuccess); | ||
| 2490 | rb.Push<s32>(previous_program_index); | ||
| 2491 | } | ||
| 2492 | |||
| 2493 | void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) { | ||
| 2494 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2495 | |||
| 2496 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2497 | rb.Push(ResultSuccess); | ||
| 2498 | rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent()); | ||
| 2499 | } | ||
| 2500 | |||
| 2501 | void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) { | ||
| 2502 | LOG_DEBUG(Service_AM, "called"); | ||
| 2503 | |||
| 2504 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2505 | rb.Push(ResultSuccess); | ||
| 2506 | rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent()); | ||
| 2507 | } | ||
| 2508 | |||
| 2509 | void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) { | ||
| 2510 | LOG_DEBUG(Service_AM, "(STUBBED) called"); | ||
| 2511 | |||
| 2512 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2513 | rb.Push(AM::ResultNoDataInChannel); | ||
| 2514 | } | ||
| 2515 | |||
| 2516 | void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) { | ||
| 2517 | LOG_DEBUG(Service_AM, "called"); | ||
| 2518 | |||
| 2519 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2520 | rb.Push(ResultSuccess); | ||
| 2521 | rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent()); | ||
| 2522 | } | ||
| 2523 | |||
| 2524 | void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) { | ||
| 2525 | LOG_DEBUG(Service_AM, "called"); | ||
| 2526 | |||
| 2527 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2528 | rb.Push(ResultSuccess); | ||
| 2529 | rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent()); | ||
| 2530 | } | ||
| 2531 | |||
| 2532 | void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) { | ||
| 2533 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2534 | |||
| 2535 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2536 | rb.Push(ResultSuccess); | ||
| 2537 | } | ||
| 2538 | |||
| 2539 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { | 15 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { |
| 2540 | auto message_queue = std::make_shared<AppletMessageQueue>(system); | 16 | auto message_queue = std::make_shared<AppletMessageQueue>(system); |
| 2541 | auto server_manager = std::make_unique<ServerManager>(system); | 17 | auto server_manager = std::make_unique<ServerManager>(system); |
| @@ -2550,155 +26,4 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { | |||
| 2550 | ServerManager::RunServer(std::move(server_manager)); | 26 | ServerManager::RunServer(std::move(server_manager)); |
| 2551 | } | 27 | } |
| 2552 | 28 | ||
| 2553 | IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) | ||
| 2554 | : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system, | ||
| 2555 | "IHomeMenuFunctions"} { | ||
| 2556 | // clang-format off | ||
| 2557 | static const FunctionInfo functions[] = { | ||
| 2558 | {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"}, | ||
| 2559 | {11, nullptr, "LockForeground"}, | ||
| 2560 | {12, nullptr, "UnlockForeground"}, | ||
| 2561 | {20, nullptr, "PopFromGeneralChannel"}, | ||
| 2562 | {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, | ||
| 2563 | {30, nullptr, "GetHomeButtonWriterLockAccessor"}, | ||
| 2564 | {31, nullptr, "GetWriterLockAccessorEx"}, | ||
| 2565 | {40, nullptr, "IsSleepEnabled"}, | ||
| 2566 | {41, nullptr, "IsRebootEnabled"}, | ||
| 2567 | {50, nullptr, "LaunchSystemApplet"}, | ||
| 2568 | {51, nullptr, "LaunchStarter"}, | ||
| 2569 | {100, nullptr, "PopRequestLaunchApplicationForDebug"}, | ||
| 2570 | {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, | ||
| 2571 | {200, nullptr, "LaunchDevMenu"}, | ||
| 2572 | {1000, nullptr, "SetLastApplicationExitReason"}, | ||
| 2573 | }; | ||
| 2574 | // clang-format on | ||
| 2575 | |||
| 2576 | RegisterHandlers(functions); | ||
| 2577 | |||
| 2578 | pop_from_general_channel_event = | ||
| 2579 | service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent"); | ||
| 2580 | } | ||
| 2581 | |||
| 2582 | IHomeMenuFunctions::~IHomeMenuFunctions() { | ||
| 2583 | service_context.CloseEvent(pop_from_general_channel_event); | ||
| 2584 | } | ||
| 2585 | |||
| 2586 | void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) { | ||
| 2587 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2588 | |||
| 2589 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2590 | rb.Push(ResultSuccess); | ||
| 2591 | } | ||
| 2592 | |||
| 2593 | void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) { | ||
| 2594 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2595 | |||
| 2596 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2597 | rb.Push(ResultSuccess); | ||
| 2598 | rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent()); | ||
| 2599 | } | ||
| 2600 | |||
| 2601 | IGlobalStateController::IGlobalStateController(Core::System& system_) | ||
| 2602 | : ServiceFramework{system_, "IGlobalStateController"} { | ||
| 2603 | // clang-format off | ||
| 2604 | static const FunctionInfo functions[] = { | ||
| 2605 | {0, nullptr, "RequestToEnterSleep"}, | ||
| 2606 | {1, nullptr, "EnterSleep"}, | ||
| 2607 | {2, nullptr, "StartSleepSequence"}, | ||
| 2608 | {3, nullptr, "StartShutdownSequence"}, | ||
| 2609 | {4, nullptr, "StartRebootSequence"}, | ||
| 2610 | {9, nullptr, "IsAutoPowerDownRequested"}, | ||
| 2611 | {10, nullptr, "LoadAndApplyIdlePolicySettings"}, | ||
| 2612 | {11, nullptr, "NotifyCecSettingsChanged"}, | ||
| 2613 | {12, nullptr, "SetDefaultHomeButtonLongPressTime"}, | ||
| 2614 | {13, nullptr, "UpdateDefaultDisplayResolution"}, | ||
| 2615 | {14, nullptr, "ShouldSleepOnBoot"}, | ||
| 2616 | {15, nullptr, "GetHdcpAuthenticationFailedEvent"}, | ||
| 2617 | {30, nullptr, "OpenCradleFirmwareUpdater"}, | ||
| 2618 | }; | ||
| 2619 | // clang-format on | ||
| 2620 | |||
| 2621 | RegisterHandlers(functions); | ||
| 2622 | } | ||
| 2623 | |||
| 2624 | IGlobalStateController::~IGlobalStateController() = default; | ||
| 2625 | |||
| 2626 | IApplicationCreator::IApplicationCreator(Core::System& system_) | ||
| 2627 | : ServiceFramework{system_, "IApplicationCreator"} { | ||
| 2628 | // clang-format off | ||
| 2629 | static const FunctionInfo functions[] = { | ||
| 2630 | {0, nullptr, "CreateApplication"}, | ||
| 2631 | {1, nullptr, "PopLaunchRequestedApplication"}, | ||
| 2632 | {10, nullptr, "CreateSystemApplication"}, | ||
| 2633 | {100, nullptr, "PopFloatingApplicationForDevelopment"}, | ||
| 2634 | }; | ||
| 2635 | // clang-format on | ||
| 2636 | |||
| 2637 | RegisterHandlers(functions); | ||
| 2638 | } | ||
| 2639 | |||
| 2640 | IApplicationCreator::~IApplicationCreator() = default; | ||
| 2641 | |||
| 2642 | IProcessWindingController::IProcessWindingController(Core::System& system_) | ||
| 2643 | : ServiceFramework{system_, "IProcessWindingController"} { | ||
| 2644 | // clang-format off | ||
| 2645 | static const FunctionInfo functions[] = { | ||
| 2646 | {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"}, | ||
| 2647 | {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"}, | ||
| 2648 | {21, nullptr, "PushContext"}, | ||
| 2649 | {22, nullptr, "PopContext"}, | ||
| 2650 | {23, nullptr, "CancelWindingReservation"}, | ||
| 2651 | {30, nullptr, "WindAndDoReserved"}, | ||
| 2652 | {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"}, | ||
| 2653 | {41, nullptr, "ReserveToStartAndWait"}, | ||
| 2654 | }; | ||
| 2655 | // clang-format on | ||
| 2656 | |||
| 2657 | RegisterHandlers(functions); | ||
| 2658 | } | ||
| 2659 | |||
| 2660 | IProcessWindingController::~IProcessWindingController() = default; | ||
| 2661 | |||
| 2662 | void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) { | ||
| 2663 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2664 | |||
| 2665 | struct AppletProcessLaunchReason { | ||
| 2666 | u8 flag; | ||
| 2667 | INSERT_PADDING_BYTES(3); | ||
| 2668 | }; | ||
| 2669 | static_assert(sizeof(AppletProcessLaunchReason) == 0x4, | ||
| 2670 | "AppletProcessLaunchReason is an invalid size"); | ||
| 2671 | |||
| 2672 | AppletProcessLaunchReason reason{ | ||
| 2673 | .flag = 0, | ||
| 2674 | }; | ||
| 2675 | |||
| 2676 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2677 | rb.Push(ResultSuccess); | ||
| 2678 | rb.PushRaw(reason); | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { | ||
| 2682 | const auto applet_id = system.GetAppletManager().GetCurrentAppletId(); | ||
| 2683 | const auto applet_mode = Applets::LibraryAppletMode::AllForeground; | ||
| 2684 | |||
| 2685 | LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id, | ||
| 2686 | applet_mode); | ||
| 2687 | |||
| 2688 | const auto& applet_manager{system.GetAppletManager()}; | ||
| 2689 | const auto applet = applet_manager.GetApplet(applet_id, applet_mode); | ||
| 2690 | |||
| 2691 | if (applet == nullptr) { | ||
| 2692 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); | ||
| 2693 | |||
| 2694 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2695 | rb.Push(ResultUnknown); | ||
| 2696 | return; | ||
| 2697 | } | ||
| 2698 | |||
| 2699 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 2700 | rb.Push(ResultSuccess); | ||
| 2701 | rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); | ||
| 2702 | } | ||
| 2703 | |||
| 2704 | } // namespace Service::AM | 29 | } // namespace Service::AM |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 905a71b9f..4a2d797bd 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -1,20 +1,11 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <chrono> | 6 | namespace Core { |
| 7 | #include <memory> | 7 | class System; |
| 8 | #include <queue> | 8 | } |
| 9 | |||
| 10 | #include "core/hle/service/kernel_helpers.h" | ||
| 11 | #include "core/hle/service/service.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | class KernelCore; | ||
| 15 | class KReadableEvent; | ||
| 16 | class KTransferMemory; | ||
| 17 | } // namespace Kernel | ||
| 18 | 9 | ||
| 19 | namespace Service::Nvnflinger { | 10 | namespace Service::Nvnflinger { |
| 20 | class Nvnflinger; | 11 | class Nvnflinger; |
| @@ -22,443 +13,6 @@ class Nvnflinger; | |||
| 22 | 13 | ||
| 23 | namespace Service::AM { | 14 | namespace Service::AM { |
| 24 | 15 | ||
| 25 | class AppletMessageQueue { | ||
| 26 | public: | ||
| 27 | // This is nn::am::AppletMessage | ||
| 28 | enum class AppletMessage : u32 { | ||
| 29 | None = 0, | ||
| 30 | ChangeIntoForeground = 1, | ||
| 31 | ChangeIntoBackground = 2, | ||
| 32 | Exit = 4, | ||
| 33 | ApplicationExited = 6, | ||
| 34 | FocusStateChanged = 15, | ||
| 35 | Resume = 16, | ||
| 36 | DetectShortPressingHomeButton = 20, | ||
| 37 | DetectLongPressingHomeButton = 21, | ||
| 38 | DetectShortPressingPowerButton = 22, | ||
| 39 | DetectMiddlePressingPowerButton = 23, | ||
| 40 | DetectLongPressingPowerButton = 24, | ||
| 41 | RequestToPrepareSleep = 25, | ||
| 42 | FinishedSleepSequence = 26, | ||
| 43 | SleepRequiredByHighTemperature = 27, | ||
| 44 | SleepRequiredByLowBattery = 28, | ||
| 45 | AutoPowerDown = 29, | ||
| 46 | OperationModeChanged = 30, | ||
| 47 | PerformanceModeChanged = 31, | ||
| 48 | DetectReceivingCecSystemStandby = 32, | ||
| 49 | SdCardRemoved = 33, | ||
| 50 | LaunchApplicationRequested = 50, | ||
| 51 | RequestToDisplay = 51, | ||
| 52 | ShowApplicationLogo = 55, | ||
| 53 | HideApplicationLogo = 56, | ||
| 54 | ForceHideApplicationLogo = 57, | ||
| 55 | FloatingApplicationDetected = 60, | ||
| 56 | DetectShortPressingCaptureButton = 90, | ||
| 57 | AlbumScreenShotTaken = 92, | ||
| 58 | AlbumRecordingSaved = 93, | ||
| 59 | }; | ||
| 60 | |||
| 61 | explicit AppletMessageQueue(Core::System& system); | ||
| 62 | ~AppletMessageQueue(); | ||
| 63 | |||
| 64 | Kernel::KReadableEvent& GetMessageReceiveEvent(); | ||
| 65 | Kernel::KReadableEvent& GetOperationModeChangedEvent(); | ||
| 66 | void PushMessage(AppletMessage msg); | ||
| 67 | AppletMessage PopMessage(); | ||
| 68 | std::size_t GetMessageCount() const; | ||
| 69 | void RequestExit(); | ||
| 70 | void RequestResume(); | ||
| 71 | void FocusStateChanged(); | ||
| 72 | void OperationModeChanged(); | ||
| 73 | |||
| 74 | private: | ||
| 75 | KernelHelpers::ServiceContext service_context; | ||
| 76 | |||
| 77 | Kernel::KEvent* on_new_message; | ||
| 78 | Kernel::KEvent* on_operation_mode_changed; | ||
| 79 | |||
| 80 | std::queue<AppletMessage> messages; | ||
| 81 | }; | ||
| 82 | |||
| 83 | class IWindowController final : public ServiceFramework<IWindowController> { | ||
| 84 | public: | ||
| 85 | explicit IWindowController(Core::System& system_); | ||
| 86 | ~IWindowController() override; | ||
| 87 | |||
| 88 | private: | ||
| 89 | void GetAppletResourceUserId(HLERequestContext& ctx); | ||
| 90 | void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx); | ||
| 91 | void AcquireForegroundRights(HLERequestContext& ctx); | ||
| 92 | }; | ||
| 93 | |||
| 94 | class IAudioController final : public ServiceFramework<IAudioController> { | ||
| 95 | public: | ||
| 96 | explicit IAudioController(Core::System& system_); | ||
| 97 | ~IAudioController() override; | ||
| 98 | |||
| 99 | private: | ||
| 100 | void SetExpectedMasterVolume(HLERequestContext& ctx); | ||
| 101 | void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx); | ||
| 102 | void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx); | ||
| 103 | void ChangeMainAppletMasterVolume(HLERequestContext& ctx); | ||
| 104 | void SetTransparentAudioRate(HLERequestContext& ctx); | ||
| 105 | |||
| 106 | static constexpr float min_allowed_volume = 0.0f; | ||
| 107 | static constexpr float max_allowed_volume = 1.0f; | ||
| 108 | |||
| 109 | float main_applet_volume{0.25f}; | ||
| 110 | float library_applet_volume{max_allowed_volume}; | ||
| 111 | float transparent_volume_rate{min_allowed_volume}; | ||
| 112 | |||
| 113 | // Volume transition fade time in nanoseconds. | ||
| 114 | // e.g. If the main applet volume was 0% and was changed to 50% | ||
| 115 | // with a fade of 50ns, then over the course of 50ns, | ||
| 116 | // the volume will gradually fade up to 50% | ||
| 117 | std::chrono::nanoseconds fade_time_ns{0}; | ||
| 118 | }; | ||
| 119 | |||
| 120 | class IDisplayController final : public ServiceFramework<IDisplayController> { | ||
| 121 | public: | ||
| 122 | explicit IDisplayController(Core::System& system_); | ||
| 123 | ~IDisplayController() override; | ||
| 124 | |||
| 125 | private: | ||
| 126 | void GetCallerAppletCaptureImageEx(HLERequestContext& ctx); | ||
| 127 | void TakeScreenShotOfOwnLayer(HLERequestContext& ctx); | ||
| 128 | void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 129 | void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 130 | void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 131 | void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 132 | }; | ||
| 133 | |||
| 134 | class IDebugFunctions final : public ServiceFramework<IDebugFunctions> { | ||
| 135 | public: | ||
| 136 | explicit IDebugFunctions(Core::System& system_); | ||
| 137 | ~IDebugFunctions() override; | ||
| 138 | }; | ||
| 139 | |||
| 140 | class ISelfController final : public ServiceFramework<ISelfController> { | ||
| 141 | public: | ||
| 142 | explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); | ||
| 143 | ~ISelfController() override; | ||
| 144 | |||
| 145 | private: | ||
| 146 | void Exit(HLERequestContext& ctx); | ||
| 147 | void LockExit(HLERequestContext& ctx); | ||
| 148 | void UnlockExit(HLERequestContext& ctx); | ||
| 149 | void EnterFatalSection(HLERequestContext& ctx); | ||
| 150 | void LeaveFatalSection(HLERequestContext& ctx); | ||
| 151 | void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx); | ||
| 152 | void SetScreenShotPermission(HLERequestContext& ctx); | ||
| 153 | void SetOperationModeChangedNotification(HLERequestContext& ctx); | ||
| 154 | void SetPerformanceModeChangedNotification(HLERequestContext& ctx); | ||
| 155 | void SetFocusHandlingMode(HLERequestContext& ctx); | ||
| 156 | void SetRestartMessageEnabled(HLERequestContext& ctx); | ||
| 157 | void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); | ||
| 158 | void SetAlbumImageOrientation(HLERequestContext& ctx); | ||
| 159 | void IsSystemBufferSharingEnabled(HLERequestContext& ctx); | ||
| 160 | void GetSystemSharedBufferHandle(HLERequestContext& ctx); | ||
| 161 | void GetSystemSharedLayerHandle(HLERequestContext& ctx); | ||
| 162 | void CreateManagedDisplayLayer(HLERequestContext& ctx); | ||
| 163 | void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); | ||
| 164 | void SetHandlesRequestToDisplay(HLERequestContext& ctx); | ||
| 165 | void ApproveToDisplay(HLERequestContext& ctx); | ||
| 166 | void SetIdleTimeDetectionExtension(HLERequestContext& ctx); | ||
| 167 | void GetIdleTimeDetectionExtension(HLERequestContext& ctx); | ||
| 168 | void ReportUserIsActive(HLERequestContext& ctx); | ||
| 169 | void SetAutoSleepDisabled(HLERequestContext& ctx); | ||
| 170 | void IsAutoSleepDisabled(HLERequestContext& ctx); | ||
| 171 | void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx); | ||
| 172 | void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx); | ||
| 173 | void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx); | ||
| 174 | void SaveCurrentScreenshot(HLERequestContext& ctx); | ||
| 175 | void SetRecordVolumeMuted(HLERequestContext& ctx); | ||
| 176 | |||
| 177 | Result EnsureBufferSharingEnabled(); | ||
| 178 | |||
| 179 | enum class ScreenshotPermission : u32 { | ||
| 180 | Inherit = 0, | ||
| 181 | Enable = 1, | ||
| 182 | Disable = 2, | ||
| 183 | }; | ||
| 184 | |||
| 185 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 186 | |||
| 187 | KernelHelpers::ServiceContext service_context; | ||
| 188 | |||
| 189 | Kernel::KEvent* launchable_event; | ||
| 190 | Kernel::KEvent* accumulated_suspended_tick_changed_event; | ||
| 191 | |||
| 192 | u32 idle_time_detection_extension = 0; | ||
| 193 | u64 num_fatal_sections_entered = 0; | ||
| 194 | u64 system_shared_buffer_id = 0; | ||
| 195 | u64 system_shared_layer_id = 0; | ||
| 196 | bool is_auto_sleep_disabled = false; | ||
| 197 | bool buffer_sharing_enabled = false; | ||
| 198 | ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit; | ||
| 199 | }; | ||
| 200 | |||
| 201 | class ILockAccessor final : public ServiceFramework<ILockAccessor> { | ||
| 202 | public: | ||
| 203 | explicit ILockAccessor(Core::System& system_); | ||
| 204 | ~ILockAccessor() override; | ||
| 205 | |||
| 206 | private: | ||
| 207 | void TryLock(HLERequestContext& ctx); | ||
| 208 | void Unlock(HLERequestContext& ctx); | ||
| 209 | void GetEvent(HLERequestContext& ctx); | ||
| 210 | void IsLocked(HLERequestContext& ctx); | ||
| 211 | |||
| 212 | bool is_locked{}; | ||
| 213 | |||
| 214 | Kernel::KEvent* lock_event; | ||
| 215 | KernelHelpers::ServiceContext service_context; | ||
| 216 | }; | ||
| 217 | |||
| 218 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | ||
| 219 | public: | ||
| 220 | explicit ICommonStateGetter(Core::System& system_, | ||
| 221 | std::shared_ptr<AppletMessageQueue> msg_queue_); | ||
| 222 | ~ICommonStateGetter() override; | ||
| 223 | |||
| 224 | private: | ||
| 225 | // This is nn::oe::FocusState | ||
| 226 | enum class FocusState : u8 { | ||
| 227 | InFocus = 1, | ||
| 228 | NotInFocus = 2, | ||
| 229 | Background = 3, | ||
| 230 | }; | ||
| 231 | |||
| 232 | // This is nn::oe::OperationMode | ||
| 233 | enum class OperationMode : u8 { | ||
| 234 | Handheld = 0, | ||
| 235 | Docked = 1, | ||
| 236 | }; | ||
| 237 | |||
| 238 | // This is nn::am::service::SystemButtonType | ||
| 239 | enum class SystemButtonType { | ||
| 240 | None, | ||
| 241 | HomeButtonShortPressing, | ||
| 242 | HomeButtonLongPressing, | ||
| 243 | PowerButtonShortPressing, | ||
| 244 | PowerButtonLongPressing, | ||
| 245 | ShutdownSystem, | ||
| 246 | CaptureButtonShortPressing, | ||
| 247 | CaptureButtonLongPressing, | ||
| 248 | }; | ||
| 249 | |||
| 250 | enum class SysPlatformRegion : s32 { | ||
| 251 | Global = 1, | ||
| 252 | Terra = 2, | ||
| 253 | }; | ||
| 254 | |||
| 255 | void GetEventHandle(HLERequestContext& ctx); | ||
| 256 | void ReceiveMessage(HLERequestContext& ctx); | ||
| 257 | void GetCurrentFocusState(HLERequestContext& ctx); | ||
| 258 | void RequestToAcquireSleepLock(HLERequestContext& ctx); | ||
| 259 | void GetAcquiredSleepLockEvent(HLERequestContext& ctx); | ||
| 260 | void GetReaderLockAccessorEx(HLERequestContext& ctx); | ||
| 261 | void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx); | ||
| 262 | void GetOperationMode(HLERequestContext& ctx); | ||
| 263 | void GetPerformanceMode(HLERequestContext& ctx); | ||
| 264 | void GetBootMode(HLERequestContext& ctx); | ||
| 265 | void IsVrModeEnabled(HLERequestContext& ctx); | ||
| 266 | void SetVrModeEnabled(HLERequestContext& ctx); | ||
| 267 | void SetLcdBacklighOffEnabled(HLERequestContext& ctx); | ||
| 268 | void BeginVrModeEx(HLERequestContext& ctx); | ||
| 269 | void EndVrModeEx(HLERequestContext& ctx); | ||
| 270 | void GetDefaultDisplayResolution(HLERequestContext& ctx); | ||
| 271 | void SetCpuBoostMode(HLERequestContext& ctx); | ||
| 272 | void GetBuiltInDisplayType(HLERequestContext& ctx); | ||
| 273 | void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx); | ||
| 274 | void GetSettingsPlatformRegion(HLERequestContext& ctx); | ||
| 275 | void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx); | ||
| 276 | |||
| 277 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 278 | bool vr_mode_state{}; | ||
| 279 | Kernel::KEvent* sleep_lock_event; | ||
| 280 | KernelHelpers::ServiceContext service_context; | ||
| 281 | }; | ||
| 282 | |||
| 283 | class IStorageImpl { | ||
| 284 | public: | ||
| 285 | virtual ~IStorageImpl(); | ||
| 286 | virtual std::vector<u8>& GetData() = 0; | ||
| 287 | virtual const std::vector<u8>& GetData() const = 0; | ||
| 288 | virtual std::size_t GetSize() const = 0; | ||
| 289 | }; | ||
| 290 | |||
| 291 | class IStorage final : public ServiceFramework<IStorage> { | ||
| 292 | public: | ||
| 293 | explicit IStorage(Core::System& system_, std::vector<u8>&& buffer); | ||
| 294 | ~IStorage() override; | ||
| 295 | |||
| 296 | std::vector<u8>& GetData() { | ||
| 297 | return impl->GetData(); | ||
| 298 | } | ||
| 299 | |||
| 300 | const std::vector<u8>& GetData() const { | ||
| 301 | return impl->GetData(); | ||
| 302 | } | ||
| 303 | |||
| 304 | std::size_t GetSize() const { | ||
| 305 | return impl->GetSize(); | ||
| 306 | } | ||
| 307 | |||
| 308 | private: | ||
| 309 | void Register(); | ||
| 310 | void Open(HLERequestContext& ctx); | ||
| 311 | |||
| 312 | std::shared_ptr<IStorageImpl> impl; | ||
| 313 | }; | ||
| 314 | |||
| 315 | class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { | ||
| 316 | public: | ||
| 317 | explicit IStorageAccessor(Core::System& system_, IStorage& backing_); | ||
| 318 | ~IStorageAccessor() override; | ||
| 319 | |||
| 320 | private: | ||
| 321 | void GetSize(HLERequestContext& ctx); | ||
| 322 | void Write(HLERequestContext& ctx); | ||
| 323 | void Read(HLERequestContext& ctx); | ||
| 324 | |||
| 325 | IStorage& backing; | ||
| 326 | }; | ||
| 327 | |||
| 328 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { | ||
| 329 | public: | ||
| 330 | explicit ILibraryAppletCreator(Core::System& system_); | ||
| 331 | ~ILibraryAppletCreator() override; | ||
| 332 | |||
| 333 | private: | ||
| 334 | void CreateLibraryApplet(HLERequestContext& ctx); | ||
| 335 | void CreateStorage(HLERequestContext& ctx); | ||
| 336 | void CreateTransferMemoryStorage(HLERequestContext& ctx); | ||
| 337 | void CreateHandleStorage(HLERequestContext& ctx); | ||
| 338 | }; | ||
| 339 | |||
| 340 | class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> { | ||
| 341 | public: | ||
| 342 | explicit ILibraryAppletSelfAccessor(Core::System& system_); | ||
| 343 | ~ILibraryAppletSelfAccessor() override; | ||
| 344 | |||
| 345 | private: | ||
| 346 | void PopInData(HLERequestContext& ctx); | ||
| 347 | void PushOutData(HLERequestContext& ctx); | ||
| 348 | void GetLibraryAppletInfo(HLERequestContext& ctx); | ||
| 349 | void GetMainAppletIdentityInfo(HLERequestContext& ctx); | ||
| 350 | void ExitProcessAndReturn(HLERequestContext& ctx); | ||
| 351 | void GetCallerAppletIdentityInfo(HLERequestContext& ctx); | ||
| 352 | void GetDesirableKeyboardLayout(HLERequestContext& ctx); | ||
| 353 | void GetMainAppletAvailableUsers(HLERequestContext& ctx); | ||
| 354 | void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx); | ||
| 355 | |||
| 356 | void PushInShowAlbum(); | ||
| 357 | void PushInShowCabinetData(); | ||
| 358 | void PushInShowMiiEditData(); | ||
| 359 | void PushInShowSoftwareKeyboard(); | ||
| 360 | void PushInShowController(); | ||
| 361 | |||
| 362 | std::deque<std::vector<u8>> queue_data; | ||
| 363 | }; | ||
| 364 | |||
| 365 | class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> { | ||
| 366 | public: | ||
| 367 | explicit IAppletCommonFunctions(Core::System& system_); | ||
| 368 | ~IAppletCommonFunctions() override; | ||
| 369 | |||
| 370 | private: | ||
| 371 | void SetCpuBoostRequestPriority(HLERequestContext& ctx); | ||
| 372 | }; | ||
| 373 | |||
| 374 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | ||
| 375 | public: | ||
| 376 | explicit IApplicationFunctions(Core::System& system_); | ||
| 377 | ~IApplicationFunctions() override; | ||
| 378 | |||
| 379 | private: | ||
| 380 | void PopLaunchParameter(HLERequestContext& ctx); | ||
| 381 | void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx); | ||
| 382 | void EnsureSaveData(HLERequestContext& ctx); | ||
| 383 | void SetTerminateResult(HLERequestContext& ctx); | ||
| 384 | void GetDisplayVersion(HLERequestContext& ctx); | ||
| 385 | void GetDesiredLanguage(HLERequestContext& ctx); | ||
| 386 | void IsGamePlayRecordingSupported(HLERequestContext& ctx); | ||
| 387 | void InitializeGamePlayRecording(HLERequestContext& ctx); | ||
| 388 | void SetGamePlayRecordingState(HLERequestContext& ctx); | ||
| 389 | void NotifyRunning(HLERequestContext& ctx); | ||
| 390 | void GetPseudoDeviceId(HLERequestContext& ctx); | ||
| 391 | void ExtendSaveData(HLERequestContext& ctx); | ||
| 392 | void GetSaveDataSize(HLERequestContext& ctx); | ||
| 393 | void CreateCacheStorage(HLERequestContext& ctx); | ||
| 394 | void GetSaveDataSizeMax(HLERequestContext& ctx); | ||
| 395 | void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); | ||
| 396 | void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); | ||
| 397 | void BeginBlockingHomeButton(HLERequestContext& ctx); | ||
| 398 | void EndBlockingHomeButton(HLERequestContext& ctx); | ||
| 399 | void EnableApplicationCrashReport(HLERequestContext& ctx); | ||
| 400 | void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx); | ||
| 401 | void SetApplicationCopyrightImage(HLERequestContext& ctx); | ||
| 402 | void SetApplicationCopyrightVisibility(HLERequestContext& ctx); | ||
| 403 | void QueryApplicationPlayStatistics(HLERequestContext& ctx); | ||
| 404 | void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx); | ||
| 405 | void ExecuteProgram(HLERequestContext& ctx); | ||
| 406 | void ClearUserChannel(HLERequestContext& ctx); | ||
| 407 | void UnpopToUserChannel(HLERequestContext& ctx); | ||
| 408 | void GetPreviousProgramIndex(HLERequestContext& ctx); | ||
| 409 | void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx); | ||
| 410 | void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx); | ||
| 411 | void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx); | ||
| 412 | void GetNotificationStorageChannelEvent(HLERequestContext& ctx); | ||
| 413 | void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx); | ||
| 414 | void PrepareForJit(HLERequestContext& ctx); | ||
| 415 | |||
| 416 | KernelHelpers::ServiceContext service_context; | ||
| 417 | |||
| 418 | bool launch_popped_account_preselect = false; | ||
| 419 | s32 previous_program_index{-1}; | ||
| 420 | Kernel::KEvent* gpu_error_detected_event; | ||
| 421 | Kernel::KEvent* friend_invitation_storage_channel_event; | ||
| 422 | Kernel::KEvent* notification_storage_channel_event; | ||
| 423 | Kernel::KEvent* health_warning_disappeared_system_event; | ||
| 424 | }; | ||
| 425 | |||
| 426 | class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { | ||
| 427 | public: | ||
| 428 | explicit IHomeMenuFunctions(Core::System& system_); | ||
| 429 | ~IHomeMenuFunctions() override; | ||
| 430 | |||
| 431 | private: | ||
| 432 | void RequestToGetForeground(HLERequestContext& ctx); | ||
| 433 | void GetPopFromGeneralChannelEvent(HLERequestContext& ctx); | ||
| 434 | |||
| 435 | KernelHelpers::ServiceContext service_context; | ||
| 436 | |||
| 437 | Kernel::KEvent* pop_from_general_channel_event; | ||
| 438 | }; | ||
| 439 | |||
| 440 | class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { | ||
| 441 | public: | ||
| 442 | explicit IGlobalStateController(Core::System& system_); | ||
| 443 | ~IGlobalStateController() override; | ||
| 444 | }; | ||
| 445 | |||
| 446 | class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { | ||
| 447 | public: | ||
| 448 | explicit IApplicationCreator(Core::System& system_); | ||
| 449 | ~IApplicationCreator() override; | ||
| 450 | }; | ||
| 451 | |||
| 452 | class IProcessWindingController final : public ServiceFramework<IProcessWindingController> { | ||
| 453 | public: | ||
| 454 | explicit IProcessWindingController(Core::System& system_); | ||
| 455 | ~IProcessWindingController() override; | ||
| 456 | |||
| 457 | private: | ||
| 458 | void GetLaunchReason(HLERequestContext& ctx); | ||
| 459 | void OpenCallingLibraryApplet(HLERequestContext& ctx); | ||
| 460 | }; | ||
| 461 | |||
| 462 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); | 16 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); |
| 463 | 17 | ||
| 464 | } // namespace Service::AM | 18 | } // namespace Service::AM |
diff --git a/src/core/hle/service/am/am_results.h b/src/core/hle/service/am/am_results.h new file mode 100644 index 000000000..528b334ad --- /dev/null +++ b/src/core/hle/service/am/am_results.h | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/result.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2}; | ||
| 11 | constexpr Result ResultNoMessages{ErrorModule::AM, 3}; | ||
| 12 | constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; | ||
| 13 | |||
| 14 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index e30e6478a..bd9e5f505 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp | |||
| @@ -1,263 +1,13 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/hle/service/am/am.h" | ||
| 7 | #include "core/hle/service/am/applet_ae.h" | 4 | #include "core/hle/service/am/applet_ae.h" |
| 5 | #include "core/hle/service/am/library_applet_proxy.h" | ||
| 6 | #include "core/hle/service/am/system_applet_proxy.h" | ||
| 8 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 9 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 10 | 8 | ||
| 11 | namespace Service::AM { | 9 | namespace Service::AM { |
| 12 | 10 | ||
| 13 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | ||
| 14 | public: | ||
| 15 | explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 16 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 17 | Core::System& system_) | ||
| 18 | : ServiceFramework{system_, "ILibraryAppletProxy"}, | ||
| 19 | nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} { | ||
| 20 | // clang-format off | ||
| 21 | static const FunctionInfo functions[] = { | ||
| 22 | {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 23 | {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"}, | ||
| 24 | {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"}, | ||
| 25 | {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"}, | ||
| 26 | {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, | ||
| 27 | {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, | ||
| 28 | {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 29 | {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"}, | ||
| 30 | {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, | ||
| 31 | {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, | ||
| 32 | {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, | ||
| 33 | {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 34 | }; | ||
| 35 | // clang-format on | ||
| 36 | |||
| 37 | RegisterHandlers(functions); | ||
| 38 | } | ||
| 39 | |||
| 40 | private: | ||
| 41 | void GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 42 | LOG_DEBUG(Service_AM, "called"); | ||
| 43 | |||
| 44 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 45 | rb.Push(ResultSuccess); | ||
| 46 | rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); | ||
| 47 | } | ||
| 48 | |||
| 49 | void GetSelfController(HLERequestContext& ctx) { | ||
| 50 | LOG_DEBUG(Service_AM, "called"); | ||
| 51 | |||
| 52 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 53 | rb.Push(ResultSuccess); | ||
| 54 | rb.PushIpcInterface<ISelfController>(system, nvnflinger); | ||
| 55 | } | ||
| 56 | |||
| 57 | void GetWindowController(HLERequestContext& ctx) { | ||
| 58 | LOG_DEBUG(Service_AM, "called"); | ||
| 59 | |||
| 60 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 61 | rb.Push(ResultSuccess); | ||
| 62 | rb.PushIpcInterface<IWindowController>(system); | ||
| 63 | } | ||
| 64 | |||
| 65 | void GetAudioController(HLERequestContext& ctx) { | ||
| 66 | LOG_DEBUG(Service_AM, "called"); | ||
| 67 | |||
| 68 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 69 | rb.Push(ResultSuccess); | ||
| 70 | rb.PushIpcInterface<IAudioController>(system); | ||
| 71 | } | ||
| 72 | |||
| 73 | void GetDisplayController(HLERequestContext& ctx) { | ||
| 74 | LOG_DEBUG(Service_AM, "called"); | ||
| 75 | |||
| 76 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 77 | rb.Push(ResultSuccess); | ||
| 78 | rb.PushIpcInterface<IDisplayController>(system); | ||
| 79 | } | ||
| 80 | |||
| 81 | void GetProcessWindingController(HLERequestContext& ctx) { | ||
| 82 | LOG_DEBUG(Service_AM, "called"); | ||
| 83 | |||
| 84 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 85 | rb.Push(ResultSuccess); | ||
| 86 | rb.PushIpcInterface<IProcessWindingController>(system); | ||
| 87 | } | ||
| 88 | |||
| 89 | void GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 90 | LOG_DEBUG(Service_AM, "called"); | ||
| 91 | |||
| 92 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 93 | rb.Push(ResultSuccess); | ||
| 94 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | ||
| 95 | } | ||
| 96 | |||
| 97 | void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { | ||
| 98 | LOG_DEBUG(Service_AM, "called"); | ||
| 99 | |||
| 100 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 101 | rb.Push(ResultSuccess); | ||
| 102 | rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system); | ||
| 103 | } | ||
| 104 | |||
| 105 | void GetAppletCommonFunctions(HLERequestContext& ctx) { | ||
| 106 | LOG_DEBUG(Service_AM, "called"); | ||
| 107 | |||
| 108 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 109 | rb.Push(ResultSuccess); | ||
| 110 | rb.PushIpcInterface<IAppletCommonFunctions>(system); | ||
| 111 | } | ||
| 112 | |||
| 113 | void GetHomeMenuFunctions(HLERequestContext& ctx) { | ||
| 114 | LOG_DEBUG(Service_AM, "called"); | ||
| 115 | |||
| 116 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 117 | rb.Push(ResultSuccess); | ||
| 118 | rb.PushIpcInterface<IHomeMenuFunctions>(system); | ||
| 119 | } | ||
| 120 | |||
| 121 | void GetGlobalStateController(HLERequestContext& ctx) { | ||
| 122 | LOG_DEBUG(Service_AM, "called"); | ||
| 123 | |||
| 124 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 125 | rb.Push(ResultSuccess); | ||
| 126 | rb.PushIpcInterface<IGlobalStateController>(system); | ||
| 127 | } | ||
| 128 | |||
| 129 | void GetDebugFunctions(HLERequestContext& ctx) { | ||
| 130 | LOG_DEBUG(Service_AM, "called"); | ||
| 131 | |||
| 132 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 133 | rb.Push(ResultSuccess); | ||
| 134 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 135 | } | ||
| 136 | |||
| 137 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 138 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 139 | }; | ||
| 140 | |||
| 141 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { | ||
| 142 | public: | ||
| 143 | explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 144 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 145 | Core::System& system_) | ||
| 146 | : ServiceFramework{system_, "ISystemAppletProxy"}, | ||
| 147 | nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} { | ||
| 148 | // clang-format off | ||
| 149 | static const FunctionInfo functions[] = { | ||
| 150 | {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 151 | {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"}, | ||
| 152 | {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"}, | ||
| 153 | {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"}, | ||
| 154 | {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"}, | ||
| 155 | {10, nullptr, "GetProcessWindingController"}, | ||
| 156 | {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 157 | {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, | ||
| 158 | {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, | ||
| 159 | {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"}, | ||
| 160 | {23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, | ||
| 161 | {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 162 | }; | ||
| 163 | // clang-format on | ||
| 164 | |||
| 165 | RegisterHandlers(functions); | ||
| 166 | } | ||
| 167 | |||
| 168 | private: | ||
| 169 | void GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 170 | LOG_DEBUG(Service_AM, "called"); | ||
| 171 | |||
| 172 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 173 | rb.Push(ResultSuccess); | ||
| 174 | rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); | ||
| 175 | } | ||
| 176 | |||
| 177 | void GetSelfController(HLERequestContext& ctx) { | ||
| 178 | LOG_DEBUG(Service_AM, "called"); | ||
| 179 | |||
| 180 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 181 | rb.Push(ResultSuccess); | ||
| 182 | rb.PushIpcInterface<ISelfController>(system, nvnflinger); | ||
| 183 | } | ||
| 184 | |||
| 185 | void GetWindowController(HLERequestContext& ctx) { | ||
| 186 | LOG_DEBUG(Service_AM, "called"); | ||
| 187 | |||
| 188 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 189 | rb.Push(ResultSuccess); | ||
| 190 | rb.PushIpcInterface<IWindowController>(system); | ||
| 191 | } | ||
| 192 | |||
| 193 | void GetAudioController(HLERequestContext& ctx) { | ||
| 194 | LOG_DEBUG(Service_AM, "called"); | ||
| 195 | |||
| 196 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 197 | rb.Push(ResultSuccess); | ||
| 198 | rb.PushIpcInterface<IAudioController>(system); | ||
| 199 | } | ||
| 200 | |||
| 201 | void GetDisplayController(HLERequestContext& ctx) { | ||
| 202 | LOG_DEBUG(Service_AM, "called"); | ||
| 203 | |||
| 204 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 205 | rb.Push(ResultSuccess); | ||
| 206 | rb.PushIpcInterface<IDisplayController>(system); | ||
| 207 | } | ||
| 208 | |||
| 209 | void GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 210 | LOG_DEBUG(Service_AM, "called"); | ||
| 211 | |||
| 212 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 213 | rb.Push(ResultSuccess); | ||
| 214 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | ||
| 215 | } | ||
| 216 | |||
| 217 | void GetHomeMenuFunctions(HLERequestContext& ctx) { | ||
| 218 | LOG_DEBUG(Service_AM, "called"); | ||
| 219 | |||
| 220 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 221 | rb.Push(ResultSuccess); | ||
| 222 | rb.PushIpcInterface<IHomeMenuFunctions>(system); | ||
| 223 | } | ||
| 224 | |||
| 225 | void GetGlobalStateController(HLERequestContext& ctx) { | ||
| 226 | LOG_DEBUG(Service_AM, "called"); | ||
| 227 | |||
| 228 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 229 | rb.Push(ResultSuccess); | ||
| 230 | rb.PushIpcInterface<IGlobalStateController>(system); | ||
| 231 | } | ||
| 232 | |||
| 233 | void GetApplicationCreator(HLERequestContext& ctx) { | ||
| 234 | LOG_DEBUG(Service_AM, "called"); | ||
| 235 | |||
| 236 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 237 | rb.Push(ResultSuccess); | ||
| 238 | rb.PushIpcInterface<IApplicationCreator>(system); | ||
| 239 | } | ||
| 240 | |||
| 241 | void GetAppletCommonFunctions(HLERequestContext& ctx) { | ||
| 242 | LOG_DEBUG(Service_AM, "called"); | ||
| 243 | |||
| 244 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 245 | rb.Push(ResultSuccess); | ||
| 246 | rb.PushIpcInterface<IAppletCommonFunctions>(system); | ||
| 247 | } | ||
| 248 | |||
| 249 | void GetDebugFunctions(HLERequestContext& ctx) { | ||
| 250 | LOG_DEBUG(Service_AM, "called"); | ||
| 251 | |||
| 252 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 253 | rb.Push(ResultSuccess); | ||
| 254 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 255 | } | ||
| 256 | |||
| 257 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 258 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 259 | }; | ||
| 260 | |||
| 261 | void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { | 11 | void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { |
| 262 | LOG_DEBUG(Service_AM, "called"); | 12 | LOG_DEBUG(Service_AM, "called"); |
| 263 | 13 | ||
| @@ -284,8 +34,8 @@ void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) { | |||
| 284 | 34 | ||
| 285 | AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, | 35 | AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, |
| 286 | std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) | 36 | std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) |
| 287 | : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_}, msg_queue{ | 37 | : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_}, |
| 288 | std::move(msg_queue_)} { | 38 | msg_queue{std::move(msg_queue_)} { |
| 289 | // clang-format off | 39 | // clang-format off |
| 290 | static const FunctionInfo functions[] = { | 40 | static const FunctionInfo functions[] = { |
| 291 | {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, | 41 | {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, |
diff --git a/src/core/hle/service/am/applet_common_functions.cpp b/src/core/hle/service/am/applet_common_functions.cpp new file mode 100644 index 000000000..81c01a48b --- /dev/null +++ b/src/core/hle/service/am/applet_common_functions.cpp | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet_common_functions.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IAppletCommonFunctions"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, nullptr, "SetTerminateResult"}, | ||
| 14 | {10, nullptr, "ReadThemeStorage"}, | ||
| 15 | {11, nullptr, "WriteThemeStorage"}, | ||
| 16 | {20, nullptr, "PushToAppletBoundChannel"}, | ||
| 17 | {21, nullptr, "TryPopFromAppletBoundChannel"}, | ||
| 18 | {40, nullptr, "GetDisplayLogicalResolution"}, | ||
| 19 | {42, nullptr, "SetDisplayMagnification"}, | ||
| 20 | {50, nullptr, "SetHomeButtonDoubleClickEnabled"}, | ||
| 21 | {51, nullptr, "GetHomeButtonDoubleClickEnabled"}, | ||
| 22 | {52, nullptr, "IsHomeButtonShortPressedBlocked"}, | ||
| 23 | {60, nullptr, "IsVrModeCurtainRequired"}, | ||
| 24 | {61, nullptr, "IsSleepRequiredByHighTemperature"}, | ||
| 25 | {62, nullptr, "IsSleepRequiredByLowBattery"}, | ||
| 26 | {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"}, | ||
| 27 | {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"}, | ||
| 28 | {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"}, | ||
| 29 | {90, nullptr, "OpenNamedChannelAsParent"}, | ||
| 30 | {91, nullptr, "OpenNamedChannelAsChild"}, | ||
| 31 | {100, nullptr, "SetApplicationCoreUsageMode"}, | ||
| 32 | }; | ||
| 33 | // clang-format on | ||
| 34 | |||
| 35 | RegisterHandlers(functions); | ||
| 36 | } | ||
| 37 | |||
| 38 | IAppletCommonFunctions::~IAppletCommonFunctions() = default; | ||
| 39 | |||
| 40 | void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) { | ||
| 41 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 42 | |||
| 43 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 44 | rb.Push(ResultSuccess); | ||
| 45 | } | ||
| 46 | |||
| 47 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_common_functions.h b/src/core/hle/service/am/applet_common_functions.h new file mode 100644 index 000000000..be87b3820 --- /dev/null +++ b/src/core/hle/service/am/applet_common_functions.h | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> { | ||
| 11 | public: | ||
| 12 | explicit IAppletCommonFunctions(Core::System& system_); | ||
| 13 | ~IAppletCommonFunctions() override; | ||
| 14 | |||
| 15 | private: | ||
| 16 | void SetCpuBoostRequestPriority(HLERequestContext& ctx); | ||
| 17 | }; | ||
| 18 | |||
| 19 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_message_queue.cpp b/src/core/hle/service/am/applet_message_queue.cpp new file mode 100644 index 000000000..e4931031d --- /dev/null +++ b/src/core/hle/service/am/applet_message_queue.cpp | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | AppletMessageQueue::AppletMessageQueue(Core::System& system) | ||
| 10 | : service_context{system, "AppletMessageQueue"} { | ||
| 11 | on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived"); | ||
| 12 | on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged"); | ||
| 13 | } | ||
| 14 | |||
| 15 | AppletMessageQueue::~AppletMessageQueue() { | ||
| 16 | service_context.CloseEvent(on_new_message); | ||
| 17 | service_context.CloseEvent(on_operation_mode_changed); | ||
| 18 | } | ||
| 19 | |||
| 20 | Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() { | ||
| 21 | return on_new_message->GetReadableEvent(); | ||
| 22 | } | ||
| 23 | |||
| 24 | Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() { | ||
| 25 | return on_operation_mode_changed->GetReadableEvent(); | ||
| 26 | } | ||
| 27 | |||
| 28 | void AppletMessageQueue::PushMessage(AppletMessage msg) { | ||
| 29 | messages.push(msg); | ||
| 30 | on_new_message->Signal(); | ||
| 31 | } | ||
| 32 | |||
| 33 | AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { | ||
| 34 | if (messages.empty()) { | ||
| 35 | on_new_message->Clear(); | ||
| 36 | return AppletMessage::None; | ||
| 37 | } | ||
| 38 | auto msg = messages.front(); | ||
| 39 | messages.pop(); | ||
| 40 | if (messages.empty()) { | ||
| 41 | on_new_message->Clear(); | ||
| 42 | } | ||
| 43 | return msg; | ||
| 44 | } | ||
| 45 | |||
| 46 | std::size_t AppletMessageQueue::GetMessageCount() const { | ||
| 47 | return messages.size(); | ||
| 48 | } | ||
| 49 | |||
| 50 | void AppletMessageQueue::RequestExit() { | ||
| 51 | PushMessage(AppletMessage::Exit); | ||
| 52 | } | ||
| 53 | |||
| 54 | void AppletMessageQueue::RequestResume() { | ||
| 55 | PushMessage(AppletMessage::Resume); | ||
| 56 | } | ||
| 57 | |||
| 58 | void AppletMessageQueue::FocusStateChanged() { | ||
| 59 | PushMessage(AppletMessage::FocusStateChanged); | ||
| 60 | } | ||
| 61 | |||
| 62 | void AppletMessageQueue::OperationModeChanged() { | ||
| 63 | PushMessage(AppletMessage::OperationModeChanged); | ||
| 64 | PushMessage(AppletMessage::PerformanceModeChanged); | ||
| 65 | on_operation_mode_changed->Signal(); | ||
| 66 | } | ||
| 67 | |||
| 68 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_message_queue.h b/src/core/hle/service/am/applet_message_queue.h new file mode 100644 index 000000000..60145aae9 --- /dev/null +++ b/src/core/hle/service/am/applet_message_queue.h | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <queue> | ||
| 7 | |||
| 8 | #include "core/hle/service/kernel_helpers.h" | ||
| 9 | #include "core/hle/service/service.h" | ||
| 10 | |||
| 11 | namespace Kernel { | ||
| 12 | class KReadableEvent; | ||
| 13 | } // namespace Kernel | ||
| 14 | |||
| 15 | namespace Service::AM { | ||
| 16 | |||
| 17 | class AppletMessageQueue { | ||
| 18 | public: | ||
| 19 | // This is nn::am::AppletMessage | ||
| 20 | enum class AppletMessage : u32 { | ||
| 21 | None = 0, | ||
| 22 | ChangeIntoForeground = 1, | ||
| 23 | ChangeIntoBackground = 2, | ||
| 24 | Exit = 4, | ||
| 25 | ApplicationExited = 6, | ||
| 26 | FocusStateChanged = 15, | ||
| 27 | Resume = 16, | ||
| 28 | DetectShortPressingHomeButton = 20, | ||
| 29 | DetectLongPressingHomeButton = 21, | ||
| 30 | DetectShortPressingPowerButton = 22, | ||
| 31 | DetectMiddlePressingPowerButton = 23, | ||
| 32 | DetectLongPressingPowerButton = 24, | ||
| 33 | RequestToPrepareSleep = 25, | ||
| 34 | FinishedSleepSequence = 26, | ||
| 35 | SleepRequiredByHighTemperature = 27, | ||
| 36 | SleepRequiredByLowBattery = 28, | ||
| 37 | AutoPowerDown = 29, | ||
| 38 | OperationModeChanged = 30, | ||
| 39 | PerformanceModeChanged = 31, | ||
| 40 | DetectReceivingCecSystemStandby = 32, | ||
| 41 | SdCardRemoved = 33, | ||
| 42 | LaunchApplicationRequested = 50, | ||
| 43 | RequestToDisplay = 51, | ||
| 44 | ShowApplicationLogo = 55, | ||
| 45 | HideApplicationLogo = 56, | ||
| 46 | ForceHideApplicationLogo = 57, | ||
| 47 | FloatingApplicationDetected = 60, | ||
| 48 | DetectShortPressingCaptureButton = 90, | ||
| 49 | AlbumScreenShotTaken = 92, | ||
| 50 | AlbumRecordingSaved = 93, | ||
| 51 | }; | ||
| 52 | |||
| 53 | explicit AppletMessageQueue(Core::System& system); | ||
| 54 | ~AppletMessageQueue(); | ||
| 55 | |||
| 56 | Kernel::KReadableEvent& GetMessageReceiveEvent(); | ||
| 57 | Kernel::KReadableEvent& GetOperationModeChangedEvent(); | ||
| 58 | void PushMessage(AppletMessage msg); | ||
| 59 | AppletMessage PopMessage(); | ||
| 60 | std::size_t GetMessageCount() const; | ||
| 61 | void RequestExit(); | ||
| 62 | void RequestResume(); | ||
| 63 | void FocusStateChanged(); | ||
| 64 | void OperationModeChanged(); | ||
| 65 | |||
| 66 | private: | ||
| 67 | KernelHelpers::ServiceContext service_context; | ||
| 68 | |||
| 69 | Kernel::KEvent* on_new_message; | ||
| 70 | Kernel::KEvent* on_operation_mode_changed; | ||
| 71 | |||
| 72 | std::queue<AppletMessage> messages; | ||
| 73 | }; | ||
| 74 | |||
| 75 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index d6c565d85..f373d1136 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp | |||
| @@ -1,107 +1,13 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | ||
| 5 | #include "core/hle/service/am/am.h" | 4 | #include "core/hle/service/am/am.h" |
| 6 | #include "core/hle/service/am/applet_oe.h" | 5 | #include "core/hle/service/am/applet_oe.h" |
| 6 | #include "core/hle/service/am/application_proxy.h" | ||
| 7 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 8 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 9 | 8 | ||
| 10 | namespace Service::AM { | 9 | namespace Service::AM { |
| 11 | 10 | ||
| 12 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | ||
| 13 | public: | ||
| 14 | explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 15 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 16 | Core::System& system_) | ||
| 17 | : ServiceFramework{system_, "IApplicationProxy"}, | ||
| 18 | nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} { | ||
| 19 | // clang-format off | ||
| 20 | static const FunctionInfo functions[] = { | ||
| 21 | {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 22 | {1, &IApplicationProxy::GetSelfController, "GetSelfController"}, | ||
| 23 | {2, &IApplicationProxy::GetWindowController, "GetWindowController"}, | ||
| 24 | {3, &IApplicationProxy::GetAudioController, "GetAudioController"}, | ||
| 25 | {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"}, | ||
| 26 | {10, nullptr, "GetProcessWindingController"}, | ||
| 27 | {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 28 | {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"}, | ||
| 29 | {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 30 | }; | ||
| 31 | // clang-format on | ||
| 32 | |||
| 33 | RegisterHandlers(functions); | ||
| 34 | } | ||
| 35 | |||
| 36 | private: | ||
| 37 | void GetAudioController(HLERequestContext& ctx) { | ||
| 38 | LOG_DEBUG(Service_AM, "called"); | ||
| 39 | |||
| 40 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 41 | rb.Push(ResultSuccess); | ||
| 42 | rb.PushIpcInterface<IAudioController>(system); | ||
| 43 | } | ||
| 44 | |||
| 45 | void GetDisplayController(HLERequestContext& ctx) { | ||
| 46 | LOG_DEBUG(Service_AM, "called"); | ||
| 47 | |||
| 48 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 49 | rb.Push(ResultSuccess); | ||
| 50 | rb.PushIpcInterface<IDisplayController>(system); | ||
| 51 | } | ||
| 52 | |||
| 53 | void GetDebugFunctions(HLERequestContext& ctx) { | ||
| 54 | LOG_DEBUG(Service_AM, "called"); | ||
| 55 | |||
| 56 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 57 | rb.Push(ResultSuccess); | ||
| 58 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 59 | } | ||
| 60 | |||
| 61 | void GetWindowController(HLERequestContext& ctx) { | ||
| 62 | LOG_DEBUG(Service_AM, "called"); | ||
| 63 | |||
| 64 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 65 | rb.Push(ResultSuccess); | ||
| 66 | rb.PushIpcInterface<IWindowController>(system); | ||
| 67 | } | ||
| 68 | |||
| 69 | void GetSelfController(HLERequestContext& ctx) { | ||
| 70 | LOG_DEBUG(Service_AM, "called"); | ||
| 71 | |||
| 72 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 73 | rb.Push(ResultSuccess); | ||
| 74 | rb.PushIpcInterface<ISelfController>(system, nvnflinger); | ||
| 75 | } | ||
| 76 | |||
| 77 | void GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 78 | LOG_DEBUG(Service_AM, "called"); | ||
| 79 | |||
| 80 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 81 | rb.Push(ResultSuccess); | ||
| 82 | rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); | ||
| 83 | } | ||
| 84 | |||
| 85 | void GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 86 | LOG_DEBUG(Service_AM, "called"); | ||
| 87 | |||
| 88 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 89 | rb.Push(ResultSuccess); | ||
| 90 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | ||
| 91 | } | ||
| 92 | |||
| 93 | void GetApplicationFunctions(HLERequestContext& ctx) { | ||
| 94 | LOG_DEBUG(Service_AM, "called"); | ||
| 95 | |||
| 96 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 97 | rb.Push(ResultSuccess); | ||
| 98 | rb.PushIpcInterface<IApplicationFunctions>(system); | ||
| 99 | } | ||
| 100 | |||
| 101 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 102 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 103 | }; | ||
| 104 | |||
| 105 | void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { | 11 | void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { |
| 106 | LOG_DEBUG(Service_AM, "called"); | 12 | LOG_DEBUG(Service_AM, "called"); |
| 107 | 13 | ||
| @@ -112,8 +18,8 @@ void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { | |||
| 112 | 18 | ||
| 113 | AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, | 19 | AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, |
| 114 | std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) | 20 | std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) |
| 115 | : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_}, msg_queue{ | 21 | : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_}, |
| 116 | std::move(msg_queue_)} { | 22 | msg_queue{std::move(msg_queue_)} { |
| 117 | static const FunctionInfo functions[] = { | 23 | static const FunctionInfo functions[] = { |
| 118 | {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, | 24 | {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, |
| 119 | }; | 25 | }; |
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index c2ff444a6..1b756fbd7 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "core/hle/kernel/k_readable_event.h" | 9 | #include "core/hle/kernel/k_readable_event.h" |
| 10 | #include "core/hle/service/am/am.h" | 10 | #include "core/hle/service/am/am.h" |
| 11 | #include "core/hle/service/am/applets/applet_cabinet.h" | 11 | #include "core/hle/service/am/applets/applet_cabinet.h" |
| 12 | #include "core/hle/service/am/storage.h" | ||
| 12 | #include "core/hle/service/mii/mii_manager.h" | 13 | #include "core/hle/service/mii/mii_manager.h" |
| 13 | #include "core/hle/service/nfc/common/device.h" | 14 | #include "core/hle/service/nfc/common/device.h" |
| 14 | #include "hid_core/hid_core.h" | 15 | #include "hid_core/hid_core.h" |
| @@ -17,9 +18,8 @@ namespace Service::AM::Applets { | |||
| 17 | 18 | ||
| 18 | Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_, | 19 | Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_, |
| 19 | const Core::Frontend::CabinetApplet& frontend_) | 20 | const Core::Frontend::CabinetApplet& frontend_) |
| 20 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_}, service_context{ | 21 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_}, |
| 21 | system_, | 22 | service_context{system_, "CabinetApplet"} { |
| 22 | "CabinetApplet"} { | ||
| 23 | 23 | ||
| 24 | availability_change_event = | 24 | availability_change_event = |
| 25 | service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent"); | 25 | service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent"); |
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp index 0e4d9cc39..bc8de6b60 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/applets/applet_controller.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 13 | #include "core/hle/service/am/am.h" | 13 | #include "core/hle/service/am/am.h" |
| 14 | #include "core/hle/service/am/applets/applet_controller.h" | 14 | #include "core/hle/service/am/applets/applet_controller.h" |
| 15 | #include "core/hle/service/am/storage.h" | ||
| 15 | #include "hid_core/frontend/emulated_controller.h" | 16 | #include "hid_core/frontend/emulated_controller.h" |
| 16 | #include "hid_core/hid_core.h" | 17 | #include "hid_core/hid_core.h" |
| 17 | #include "hid_core/hid_types.h" | 18 | #include "hid_core/hid_types.h" |
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp index 084bc138c..96126832c 100644 --- a/src/core/hle/service/am/applets/applet_error.cpp +++ b/src/core/hle/service/am/applets/applet_error.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "core/frontend/applets/error.h" | 10 | #include "core/frontend/applets/error.h" |
| 11 | #include "core/hle/service/am/am.h" | 11 | #include "core/hle/service/am/am.h" |
| 12 | #include "core/hle/service/am/applets/applet_error.h" | 12 | #include "core/hle/service/am/applets/applet_error.h" |
| 13 | #include "core/hle/service/am/storage.h" | ||
| 13 | #include "core/reporter.h" | 14 | #include "core/reporter.h" |
| 14 | 15 | ||
| 15 | namespace Service::AM::Applets { | 16 | namespace Service::AM::Applets { |
diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp index c0032f652..c010c78e2 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.cpp +++ b/src/core/hle/service/am/applets/applet_general_backend.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "core/hle/result.h" | 9 | #include "core/hle/result.h" |
| 10 | #include "core/hle/service/am/am.h" | 10 | #include "core/hle/service/am/am.h" |
| 11 | #include "core/hle/service/am/applets/applet_general_backend.h" | 11 | #include "core/hle/service/am/applets/applet_general_backend.h" |
| 12 | #include "core/hle/service/am/storage.h" | ||
| 12 | #include "core/reporter.h" | 13 | #include "core/reporter.h" |
| 13 | 14 | ||
| 14 | namespace Service::AM::Applets { | 15 | namespace Service::AM::Applets { |
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp index e83e931c5..1576b45c4 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.cpp +++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "core/frontend/applets/mii_edit.h" | 7 | #include "core/frontend/applets/mii_edit.h" |
| 8 | #include "core/hle/service/am/am.h" | 8 | #include "core/hle/service/am/am.h" |
| 9 | #include "core/hle/service/am/applets/applet_mii_edit.h" | 9 | #include "core/hle/service/am/applets/applet_mii_edit.h" |
| 10 | #include "core/hle/service/am/storage.h" | ||
| 10 | #include "core/hle/service/mii/mii.h" | 11 | #include "core/hle/service/mii/mii.h" |
| 11 | #include "core/hle/service/mii/mii_manager.h" | 12 | #include "core/hle/service/mii/mii_manager.h" |
| 12 | #include "core/hle/service/sm/sm.h" | 13 | #include "core/hle/service/sm/sm.h" |
diff --git a/src/core/hle/service/am/applets/applet_profile_select.cpp b/src/core/hle/service/am/applets/applet_profile_select.cpp index 89cb323e9..f32db6842 100644 --- a/src/core/hle/service/am/applets/applet_profile_select.cpp +++ b/src/core/hle/service/am/applets/applet_profile_select.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "core/hle/service/acc/errors.h" | 10 | #include "core/hle/service/acc/errors.h" |
| 11 | #include "core/hle/service/am/am.h" | 11 | #include "core/hle/service/am/am.h" |
| 12 | #include "core/hle/service/am/applets/applet_profile_select.h" | 12 | #include "core/hle/service/am/applets/applet_profile_select.h" |
| 13 | #include "core/hle/service/am/storage.h" | ||
| 13 | 14 | ||
| 14 | namespace Service::AM::Applets { | 15 | namespace Service::AM::Applets { |
| 15 | 16 | ||
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp index 4145bb84f..a6a07cef3 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp +++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "core/frontend/applets/software_keyboard.h" | 6 | #include "core/frontend/applets/software_keyboard.h" |
| 7 | #include "core/hle/service/am/am.h" | 7 | #include "core/hle/service/am/am.h" |
| 8 | #include "core/hle/service/am/applets/applet_software_keyboard.h" | 8 | #include "core/hle/service/am/applets/applet_software_keyboard.h" |
| 9 | #include "core/hle/service/am/storage.h" | ||
| 9 | 10 | ||
| 10 | namespace Service::AM::Applets { | 11 | namespace Service::AM::Applets { |
| 11 | 12 | ||
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp index 19057ad7b..871737b3e 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.cpp +++ b/src/core/hle/service/am/applets/applet_web_browser.cpp | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "core/hle/result.h" | 20 | #include "core/hle/result.h" |
| 21 | #include "core/hle/service/am/am.h" | 21 | #include "core/hle/service/am/am.h" |
| 22 | #include "core/hle/service/am/applets/applet_web_browser.h" | 22 | #include "core/hle/service/am/applets/applet_web_browser.h" |
| 23 | #include "core/hle/service/am/storage.h" | ||
| 23 | #include "core/hle/service/filesystem/filesystem.h" | 24 | #include "core/hle/service/filesystem/filesystem.h" |
| 24 | #include "core/hle/service/ns/iplatform_service_manager.h" | 25 | #include "core/hle/service/ns/iplatform_service_manager.h" |
| 25 | #include "core/loader/loader.h" | 26 | #include "core/loader/loader.h" |
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 89d5434af..6a47f4b7a 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "core/hle/kernel/k_event.h" | 16 | #include "core/hle/kernel/k_event.h" |
| 17 | #include "core/hle/service/am/am.h" | 17 | #include "core/hle/service/am/am.h" |
| 18 | #include "core/hle/service/am/applet_ae.h" | 18 | #include "core/hle/service/am/applet_ae.h" |
| 19 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 19 | #include "core/hle/service/am/applet_oe.h" | 20 | #include "core/hle/service/am/applet_oe.h" |
| 20 | #include "core/hle/service/am/applets/applet_cabinet.h" | 21 | #include "core/hle/service/am/applets/applet_cabinet.h" |
| 21 | #include "core/hle/service/am/applets/applet_controller.h" | 22 | #include "core/hle/service/am/applets/applet_controller.h" |
| @@ -26,13 +27,14 @@ | |||
| 26 | #include "core/hle/service/am/applets/applet_software_keyboard.h" | 27 | #include "core/hle/service/am/applets/applet_software_keyboard.h" |
| 27 | #include "core/hle/service/am/applets/applet_web_browser.h" | 28 | #include "core/hle/service/am/applets/applet_web_browser.h" |
| 28 | #include "core/hle/service/am/applets/applets.h" | 29 | #include "core/hle/service/am/applets/applets.h" |
| 30 | #include "core/hle/service/am/storage.h" | ||
| 29 | #include "core/hle/service/sm/sm.h" | 31 | #include "core/hle/service/sm/sm.h" |
| 30 | 32 | ||
| 31 | namespace Service::AM::Applets { | 33 | namespace Service::AM::Applets { |
| 32 | 34 | ||
| 33 | AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_) | 35 | AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_) |
| 34 | : system{system_}, applet_mode{applet_mode_}, service_context{system, | 36 | : system{system_}, applet_mode{applet_mode_}, |
| 35 | "ILibraryAppletAccessor"} { | 37 | service_context{system, "ILibraryAppletAccessor"} { |
| 36 | state_changed_event = service_context.CreateEvent("ILibraryAppletAccessor:StateChangedEvent"); | 38 | state_changed_event = service_context.CreateEvent("ILibraryAppletAccessor:StateChangedEvent"); |
| 37 | pop_out_data_event = service_context.CreateEvent("ILibraryAppletAccessor:PopDataOutEvent"); | 39 | pop_out_data_event = service_context.CreateEvent("ILibraryAppletAccessor:PopDataOutEvent"); |
| 38 | pop_interactive_out_data_event = | 40 | pop_interactive_out_data_event = |
diff --git a/src/core/hle/service/am/application_creator.cpp b/src/core/hle/service/am/application_creator.cpp new file mode 100644 index 000000000..79ea045a3 --- /dev/null +++ b/src/core/hle/service/am/application_creator.cpp | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/application_creator.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IApplicationCreator::IApplicationCreator(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IApplicationCreator"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, nullptr, "CreateApplication"}, | ||
| 14 | {1, nullptr, "PopLaunchRequestedApplication"}, | ||
| 15 | {10, nullptr, "CreateSystemApplication"}, | ||
| 16 | {100, nullptr, "PopFloatingApplicationForDevelopment"}, | ||
| 17 | }; | ||
| 18 | // clang-format on | ||
| 19 | |||
| 20 | RegisterHandlers(functions); | ||
| 21 | } | ||
| 22 | |||
| 23 | IApplicationCreator::~IApplicationCreator() = default; | ||
| 24 | |||
| 25 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_creator.h b/src/core/hle/service/am/application_creator.h new file mode 100644 index 000000000..375a3c476 --- /dev/null +++ b/src/core/hle/service/am/application_creator.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { | ||
| 11 | public: | ||
| 12 | explicit IApplicationCreator(Core::System& system_); | ||
| 13 | ~IApplicationCreator() override; | ||
| 14 | }; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_functions.cpp b/src/core/hle/service/am/application_functions.cpp new file mode 100644 index 000000000..fef45c732 --- /dev/null +++ b/src/core/hle/service/am/application_functions.cpp | |||
| @@ -0,0 +1,610 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "common/uuid.h" | ||
| 6 | #include "core/file_sys/control_metadata.h" | ||
| 7 | #include "core/file_sys/patch_manager.h" | ||
| 8 | #include "core/file_sys/registered_cache.h" | ||
| 9 | #include "core/file_sys/savedata_factory.h" | ||
| 10 | #include "core/hle/service/acc/profile_manager.h" | ||
| 11 | #include "core/hle/service/am/am_results.h" | ||
| 12 | #include "core/hle/service/am/application_functions.h" | ||
| 13 | #include "core/hle/service/am/storage.h" | ||
| 14 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 15 | #include "core/hle/service/filesystem/save_data_controller.h" | ||
| 16 | #include "core/hle/service/ipc_helpers.h" | ||
| 17 | #include "core/hle/service/ns/ns.h" | ||
| 18 | #include "core/hle/service/sm/sm.h" | ||
| 19 | |||
| 20 | namespace Service::AM { | ||
| 21 | |||
| 22 | enum class LaunchParameterKind : u32 { | ||
| 23 | UserChannel = 1, | ||
| 24 | AccountPreselectedUser = 2, | ||
| 25 | }; | ||
| 26 | |||
| 27 | constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA; | ||
| 28 | |||
| 29 | struct LaunchParameterAccountPreselectedUser { | ||
| 30 | u32_le magic; | ||
| 31 | u32_le is_account_selected; | ||
| 32 | Common::UUID current_user; | ||
| 33 | INSERT_PADDING_BYTES(0x70); | ||
| 34 | }; | ||
| 35 | static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); | ||
| 36 | |||
| 37 | IApplicationFunctions::IApplicationFunctions(Core::System& system_) | ||
| 38 | : ServiceFramework{system_, "IApplicationFunctions"}, | ||
| 39 | service_context{system, "IApplicationFunctions"} { | ||
| 40 | // clang-format off | ||
| 41 | static const FunctionInfo functions[] = { | ||
| 42 | {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, | ||
| 43 | {10, nullptr, "CreateApplicationAndPushAndRequestToStart"}, | ||
| 44 | {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"}, | ||
| 45 | {12, nullptr, "CreateApplicationAndRequestToStart"}, | ||
| 46 | {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"}, | ||
| 47 | {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"}, | ||
| 48 | {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"}, | ||
| 49 | {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"}, | ||
| 50 | {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"}, | ||
| 51 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, | ||
| 52 | {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"}, | ||
| 53 | {24, nullptr, "GetLaunchStorageInfoForDebug"}, | ||
| 54 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, | ||
| 55 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, | ||
| 56 | {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"}, | ||
| 57 | {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"}, | ||
| 58 | {29, nullptr, "GetCacheStorageMax"}, | ||
| 59 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, | ||
| 60 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, | ||
| 61 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, | ||
| 62 | {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"}, | ||
| 63 | {34, nullptr, "SelectApplicationLicense"}, | ||
| 64 | {35, nullptr, "GetDeviceSaveDataSizeMax"}, | ||
| 65 | {36, nullptr, "GetLimitedApplicationLicense"}, | ||
| 66 | {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"}, | ||
| 67 | {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, | ||
| 68 | {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, | ||
| 69 | {60, nullptr, "SetMediaPlaybackStateForApplication"}, | ||
| 70 | {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"}, | ||
| 71 | {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"}, | ||
| 72 | {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, | ||
| 73 | {68, nullptr, "RequestFlushGamePlayingMovieForDebug"}, | ||
| 74 | {70, nullptr, "RequestToShutdown"}, | ||
| 75 | {71, nullptr, "RequestToReboot"}, | ||
| 76 | {72, nullptr, "RequestToSleep"}, | ||
| 77 | {80, nullptr, "ExitAndRequestToShowThanksMessage"}, | ||
| 78 | {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"}, | ||
| 79 | {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"}, | ||
| 80 | {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"}, | ||
| 81 | {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"}, | ||
| 82 | {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"}, | ||
| 83 | {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"}, | ||
| 84 | {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"}, | ||
| 85 | {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"}, | ||
| 86 | {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"}, | ||
| 87 | {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, | ||
| 88 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, | ||
| 89 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, | ||
| 90 | {131, nullptr, "SetDelayTimeToAbortOnGpuError"}, | ||
| 91 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, | ||
| 92 | {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, | ||
| 93 | {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"}, | ||
| 94 | {151, nullptr, "TryPopFromNotificationStorageChannel"}, | ||
| 95 | {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"}, | ||
| 96 | {170, nullptr, "SetHdcpAuthenticationActivated"}, | ||
| 97 | {180, nullptr, "GetLaunchRequiredVersion"}, | ||
| 98 | {181, nullptr, "UpgradeLaunchRequiredVersion"}, | ||
| 99 | {190, nullptr, "SendServerMaintenanceOverlayNotification"}, | ||
| 100 | {200, nullptr, "GetLastApplicationExitReason"}, | ||
| 101 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, | ||
| 102 | {1000, nullptr, "CreateMovieMaker"}, | ||
| 103 | {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"}, | ||
| 104 | }; | ||
| 105 | // clang-format on | ||
| 106 | |||
| 107 | RegisterHandlers(functions); | ||
| 108 | |||
| 109 | gpu_error_detected_event = | ||
| 110 | service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent"); | ||
| 111 | friend_invitation_storage_channel_event = | ||
| 112 | service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent"); | ||
| 113 | notification_storage_channel_event = | ||
| 114 | service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent"); | ||
| 115 | health_warning_disappeared_system_event = | ||
| 116 | service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent"); | ||
| 117 | } | ||
| 118 | |||
| 119 | IApplicationFunctions::~IApplicationFunctions() { | ||
| 120 | service_context.CloseEvent(gpu_error_detected_event); | ||
| 121 | service_context.CloseEvent(friend_invitation_storage_channel_event); | ||
| 122 | service_context.CloseEvent(notification_storage_channel_event); | ||
| 123 | service_context.CloseEvent(health_warning_disappeared_system_event); | ||
| 124 | } | ||
| 125 | |||
| 126 | void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) { | ||
| 127 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 128 | |||
| 129 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 130 | rb.Push(ResultSuccess); | ||
| 131 | } | ||
| 132 | |||
| 133 | void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) { | ||
| 134 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 135 | |||
| 136 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 137 | rb.Push(ResultSuccess); | ||
| 138 | } | ||
| 139 | |||
| 140 | void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) { | ||
| 141 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 142 | |||
| 143 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 144 | rb.Push(ResultSuccess); | ||
| 145 | } | ||
| 146 | |||
| 147 | void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) { | ||
| 148 | IPC::RequestParser rp{ctx}; | ||
| 149 | const auto is_visible = rp.Pop<bool>(); | ||
| 150 | |||
| 151 | LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible); | ||
| 152 | |||
| 153 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 154 | rb.Push(ResultSuccess); | ||
| 155 | } | ||
| 156 | |||
| 157 | void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { | ||
| 158 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 159 | |||
| 160 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 161 | rb.Push(ResultSuccess); | ||
| 162 | } | ||
| 163 | |||
| 164 | void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { | ||
| 165 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 166 | |||
| 167 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 168 | rb.Push(ResultSuccess); | ||
| 169 | } | ||
| 170 | |||
| 171 | void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) { | ||
| 172 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 173 | |||
| 174 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 175 | rb.Push(ResultSuccess); | ||
| 176 | } | ||
| 177 | |||
| 178 | void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) { | ||
| 179 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 180 | |||
| 181 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 182 | rb.Push(ResultSuccess); | ||
| 183 | } | ||
| 184 | |||
| 185 | void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) { | ||
| 186 | IPC::RequestParser rp{ctx}; | ||
| 187 | const auto kind = rp.PopEnum<LaunchParameterKind>(); | ||
| 188 | |||
| 189 | LOG_INFO(Service_AM, "called, kind={:08X}", kind); | ||
| 190 | |||
| 191 | if (kind == LaunchParameterKind::UserChannel) { | ||
| 192 | auto channel = system.GetUserChannel(); | ||
| 193 | if (channel.empty()) { | ||
| 194 | LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!"); | ||
| 195 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 196 | rb.Push(AM::ResultNoDataInChannel); | ||
| 197 | return; | ||
| 198 | } | ||
| 199 | |||
| 200 | auto data = channel.back(); | ||
| 201 | channel.pop_back(); | ||
| 202 | |||
| 203 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 204 | rb.Push(ResultSuccess); | ||
| 205 | rb.PushIpcInterface<IStorage>(system, std::move(data)); | ||
| 206 | } else if (kind == LaunchParameterKind::AccountPreselectedUser && | ||
| 207 | !launch_popped_account_preselect) { | ||
| 208 | // TODO: Verify this is hw-accurate | ||
| 209 | LaunchParameterAccountPreselectedUser params{}; | ||
| 210 | |||
| 211 | params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC; | ||
| 212 | params.is_account_selected = 1; | ||
| 213 | |||
| 214 | Account::ProfileManager profile_manager{}; | ||
| 215 | const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user)); | ||
| 216 | ASSERT(uuid.has_value() && uuid->IsValid()); | ||
| 217 | params.current_user = *uuid; | ||
| 218 | |||
| 219 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 220 | rb.Push(ResultSuccess); | ||
| 221 | |||
| 222 | std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); | ||
| 223 | std::memcpy(buffer.data(), ¶ms, buffer.size()); | ||
| 224 | |||
| 225 | rb.PushIpcInterface<IStorage>(system, std::move(buffer)); | ||
| 226 | launch_popped_account_preselect = true; | ||
| 227 | } else { | ||
| 228 | LOG_ERROR(Service_AM, "Unknown launch parameter kind."); | ||
| 229 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 230 | rb.Push(AM::ResultNoDataInChannel); | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { | ||
| 235 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 236 | |||
| 237 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 238 | rb.Push(ResultSuccess); | ||
| 239 | } | ||
| 240 | |||
| 241 | void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) { | ||
| 242 | IPC::RequestParser rp{ctx}; | ||
| 243 | u128 user_id = rp.PopRaw<u128>(); | ||
| 244 | |||
| 245 | LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); | ||
| 246 | |||
| 247 | FileSys::SaveDataAttribute attribute{}; | ||
| 248 | attribute.title_id = system.GetApplicationProcessProgramID(); | ||
| 249 | attribute.user_id = user_id; | ||
| 250 | attribute.type = FileSys::SaveDataType::SaveData; | ||
| 251 | |||
| 252 | FileSys::VirtualDir save_data{}; | ||
| 253 | const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData( | ||
| 254 | &save_data, FileSys::SaveDataSpaceId::NandUser, attribute); | ||
| 255 | |||
| 256 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 257 | rb.Push(res); | ||
| 258 | rb.Push<u64>(0); | ||
| 259 | } | ||
| 260 | |||
| 261 | void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) { | ||
| 262 | // Takes an input u32 Result, no output. | ||
| 263 | // For example, in some cases official apps use this with error 0x2A2 then | ||
| 264 | // uses svcBreak. | ||
| 265 | |||
| 266 | IPC::RequestParser rp{ctx}; | ||
| 267 | u32 result = rp.Pop<u32>(); | ||
| 268 | LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result); | ||
| 269 | |||
| 270 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 271 | rb.Push(ResultSuccess); | ||
| 272 | } | ||
| 273 | |||
| 274 | void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) { | ||
| 275 | LOG_DEBUG(Service_AM, "called"); | ||
| 276 | |||
| 277 | std::array<u8, 0x10> version_string{}; | ||
| 278 | |||
| 279 | const auto res = [this] { | ||
| 280 | const auto title_id = system.GetApplicationProcessProgramID(); | ||
| 281 | |||
| 282 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | ||
| 283 | system.GetContentProvider()}; | ||
| 284 | auto metadata = pm.GetControlMetadata(); | ||
| 285 | if (metadata.first != nullptr) { | ||
| 286 | return metadata; | ||
| 287 | } | ||
| 288 | |||
| 289 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | ||
| 290 | system.GetFileSystemController(), | ||
| 291 | system.GetContentProvider()}; | ||
| 292 | return pm_update.GetControlMetadata(); | ||
| 293 | }(); | ||
| 294 | |||
| 295 | if (res.first != nullptr) { | ||
| 296 | const auto& version = res.first->GetVersionString(); | ||
| 297 | std::copy(version.begin(), version.end(), version_string.begin()); | ||
| 298 | } else { | ||
| 299 | static constexpr char default_version[]{"1.0.0"}; | ||
| 300 | std::memcpy(version_string.data(), default_version, sizeof(default_version)); | ||
| 301 | } | ||
| 302 | |||
| 303 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 304 | rb.Push(ResultSuccess); | ||
| 305 | rb.PushRaw(version_string); | ||
| 306 | } | ||
| 307 | |||
| 308 | void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { | ||
| 309 | // TODO(bunnei): This should be configurable | ||
| 310 | LOG_DEBUG(Service_AM, "called"); | ||
| 311 | |||
| 312 | // Get supported languages from NACP, if possible | ||
| 313 | // Default to 0 (all languages supported) | ||
| 314 | u32 supported_languages = 0; | ||
| 315 | |||
| 316 | const auto res = [this] { | ||
| 317 | const auto title_id = system.GetApplicationProcessProgramID(); | ||
| 318 | |||
| 319 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | ||
| 320 | system.GetContentProvider()}; | ||
| 321 | auto metadata = pm.GetControlMetadata(); | ||
| 322 | if (metadata.first != nullptr) { | ||
| 323 | return metadata; | ||
| 324 | } | ||
| 325 | |||
| 326 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | ||
| 327 | system.GetFileSystemController(), | ||
| 328 | system.GetContentProvider()}; | ||
| 329 | return pm_update.GetControlMetadata(); | ||
| 330 | }(); | ||
| 331 | |||
| 332 | if (res.first != nullptr) { | ||
| 333 | supported_languages = res.first->GetSupportedLanguages(); | ||
| 334 | } | ||
| 335 | |||
| 336 | // Call IApplicationManagerInterface implementation. | ||
| 337 | auto& service_manager = system.ServiceManager(); | ||
| 338 | auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); | ||
| 339 | auto app_man = ns_am2->GetApplicationManagerInterface(); | ||
| 340 | |||
| 341 | // Get desired application language | ||
| 342 | u8 desired_language{}; | ||
| 343 | const auto res_lang = | ||
| 344 | app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); | ||
| 345 | if (res_lang != ResultSuccess) { | ||
| 346 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 347 | rb.Push(res_lang); | ||
| 348 | return; | ||
| 349 | } | ||
| 350 | |||
| 351 | // Convert to settings language code. | ||
| 352 | u64 language_code{}; | ||
| 353 | const auto res_code = | ||
| 354 | app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); | ||
| 355 | if (res_code != ResultSuccess) { | ||
| 356 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 357 | rb.Push(res_code); | ||
| 358 | return; | ||
| 359 | } | ||
| 360 | |||
| 361 | LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); | ||
| 362 | |||
| 363 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 364 | rb.Push(ResultSuccess); | ||
| 365 | rb.Push(language_code); | ||
| 366 | } | ||
| 367 | |||
| 368 | void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { | ||
| 369 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 370 | |||
| 371 | constexpr bool gameplay_recording_supported = false; | ||
| 372 | |||
| 373 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 374 | rb.Push(ResultSuccess); | ||
| 375 | rb.Push(gameplay_recording_supported); | ||
| 376 | } | ||
| 377 | |||
| 378 | void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) { | ||
| 379 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 380 | |||
| 381 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 382 | rb.Push(ResultSuccess); | ||
| 383 | } | ||
| 384 | |||
| 385 | void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) { | ||
| 386 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 387 | |||
| 388 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 389 | rb.Push(ResultSuccess); | ||
| 390 | } | ||
| 391 | |||
| 392 | void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) { | ||
| 393 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 394 | |||
| 395 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 396 | rb.Push(ResultSuccess); | ||
| 397 | rb.Push<u8>(0); // Unknown, seems to be ignored by official processes | ||
| 398 | } | ||
| 399 | |||
| 400 | void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) { | ||
| 401 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 402 | |||
| 403 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 404 | rb.Push(ResultSuccess); | ||
| 405 | |||
| 406 | // Returns a 128-bit UUID | ||
| 407 | rb.Push<u64>(0); | ||
| 408 | rb.Push<u64>(0); | ||
| 409 | } | ||
| 410 | |||
| 411 | void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) { | ||
| 412 | struct Parameters { | ||
| 413 | FileSys::SaveDataType type; | ||
| 414 | u128 user_id; | ||
| 415 | u64 new_normal_size; | ||
| 416 | u64 new_journal_size; | ||
| 417 | }; | ||
| 418 | static_assert(sizeof(Parameters) == 40); | ||
| 419 | |||
| 420 | IPC::RequestParser rp{ctx}; | ||
| 421 | const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>(); | ||
| 422 | |||
| 423 | LOG_DEBUG(Service_AM, | ||
| 424 | "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, " | ||
| 425 | "new_journal={:016X}", | ||
| 426 | static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size); | ||
| 427 | |||
| 428 | system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize( | ||
| 429 | type, system.GetApplicationProcessProgramID(), user_id, | ||
| 430 | {new_normal_size, new_journal_size}); | ||
| 431 | |||
| 432 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 433 | rb.Push(ResultSuccess); | ||
| 434 | |||
| 435 | // The following value is used upon failure to help the system recover. | ||
| 436 | // Since we always succeed, this should be 0. | ||
| 437 | rb.Push<u64>(0); | ||
| 438 | } | ||
| 439 | |||
| 440 | void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) { | ||
| 441 | struct Parameters { | ||
| 442 | FileSys::SaveDataType type; | ||
| 443 | u128 user_id; | ||
| 444 | }; | ||
| 445 | static_assert(sizeof(Parameters) == 24); | ||
| 446 | |||
| 447 | IPC::RequestParser rp{ctx}; | ||
| 448 | const auto [type, user_id] = rp.PopRaw<Parameters>(); | ||
| 449 | |||
| 450 | LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1], | ||
| 451 | user_id[0]); | ||
| 452 | |||
| 453 | const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize( | ||
| 454 | type, system.GetApplicationProcessProgramID(), user_id); | ||
| 455 | |||
| 456 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 457 | rb.Push(ResultSuccess); | ||
| 458 | rb.Push(size.normal); | ||
| 459 | rb.Push(size.journal); | ||
| 460 | } | ||
| 461 | |||
| 462 | void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) { | ||
| 463 | struct InputParameters { | ||
| 464 | u16 index; | ||
| 465 | s64 size; | ||
| 466 | s64 journal_size; | ||
| 467 | }; | ||
| 468 | static_assert(sizeof(InputParameters) == 24); | ||
| 469 | |||
| 470 | struct OutputParameters { | ||
| 471 | u32 storage_target; | ||
| 472 | u64 required_size; | ||
| 473 | }; | ||
| 474 | static_assert(sizeof(OutputParameters) == 16); | ||
| 475 | |||
| 476 | IPC::RequestParser rp{ctx}; | ||
| 477 | const auto params = rp.PopRaw<InputParameters>(); | ||
| 478 | |||
| 479 | LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}", | ||
| 480 | params.index, params.size, params.journal_size); | ||
| 481 | |||
| 482 | const OutputParameters resp{ | ||
| 483 | .storage_target = 1, | ||
| 484 | .required_size = 0, | ||
| 485 | }; | ||
| 486 | |||
| 487 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 488 | rb.Push(ResultSuccess); | ||
| 489 | rb.PushRaw(resp); | ||
| 490 | } | ||
| 491 | |||
| 492 | void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) { | ||
| 493 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 494 | |||
| 495 | constexpr u64 size_max_normal = 0xFFFFFFF; | ||
| 496 | constexpr u64 size_max_journal = 0xFFFFFFF; | ||
| 497 | |||
| 498 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 499 | rb.Push(ResultSuccess); | ||
| 500 | rb.Push(size_max_normal); | ||
| 501 | rb.Push(size_max_journal); | ||
| 502 | } | ||
| 503 | |||
| 504 | void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) { | ||
| 505 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 506 | |||
| 507 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 508 | rb.Push(ResultSuccess); | ||
| 509 | rb.Push<u32>(0); | ||
| 510 | } | ||
| 511 | |||
| 512 | void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) { | ||
| 513 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 514 | |||
| 515 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 516 | rb.Push(ResultSuccess); | ||
| 517 | rb.Push<u32>(0); | ||
| 518 | } | ||
| 519 | |||
| 520 | void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) { | ||
| 521 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 522 | |||
| 523 | IPC::RequestParser rp{ctx}; | ||
| 524 | [[maybe_unused]] const auto unk_1 = rp.Pop<u32>(); | ||
| 525 | [[maybe_unused]] const auto unk_2 = rp.Pop<u32>(); | ||
| 526 | const auto program_index = rp.Pop<u64>(); | ||
| 527 | |||
| 528 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 529 | rb.Push(ResultSuccess); | ||
| 530 | |||
| 531 | system.ExecuteProgram(program_index); | ||
| 532 | } | ||
| 533 | |||
| 534 | void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) { | ||
| 535 | LOG_DEBUG(Service_AM, "called"); | ||
| 536 | |||
| 537 | system.GetUserChannel().clear(); | ||
| 538 | |||
| 539 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 540 | rb.Push(ResultSuccess); | ||
| 541 | } | ||
| 542 | |||
| 543 | void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) { | ||
| 544 | LOG_DEBUG(Service_AM, "called"); | ||
| 545 | |||
| 546 | IPC::RequestParser rp{ctx}; | ||
| 547 | const auto storage = rp.PopIpcInterface<IStorage>().lock(); | ||
| 548 | if (storage) { | ||
| 549 | system.GetUserChannel().push_back(storage->GetData()); | ||
| 550 | } | ||
| 551 | |||
| 552 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 553 | rb.Push(ResultSuccess); | ||
| 554 | } | ||
| 555 | |||
| 556 | void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) { | ||
| 557 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 558 | |||
| 559 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 560 | rb.Push(ResultSuccess); | ||
| 561 | rb.Push<s32>(previous_program_index); | ||
| 562 | } | ||
| 563 | |||
| 564 | void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) { | ||
| 565 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 566 | |||
| 567 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 568 | rb.Push(ResultSuccess); | ||
| 569 | rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent()); | ||
| 570 | } | ||
| 571 | |||
| 572 | void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) { | ||
| 573 | LOG_DEBUG(Service_AM, "called"); | ||
| 574 | |||
| 575 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 576 | rb.Push(ResultSuccess); | ||
| 577 | rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent()); | ||
| 578 | } | ||
| 579 | |||
| 580 | void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) { | ||
| 581 | LOG_DEBUG(Service_AM, "(STUBBED) called"); | ||
| 582 | |||
| 583 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 584 | rb.Push(AM::ResultNoDataInChannel); | ||
| 585 | } | ||
| 586 | |||
| 587 | void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) { | ||
| 588 | LOG_DEBUG(Service_AM, "called"); | ||
| 589 | |||
| 590 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 591 | rb.Push(ResultSuccess); | ||
| 592 | rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent()); | ||
| 593 | } | ||
| 594 | |||
| 595 | void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) { | ||
| 596 | LOG_DEBUG(Service_AM, "called"); | ||
| 597 | |||
| 598 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 599 | rb.Push(ResultSuccess); | ||
| 600 | rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent()); | ||
| 601 | } | ||
| 602 | |||
| 603 | void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) { | ||
| 604 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 605 | |||
| 606 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 607 | rb.Push(ResultSuccess); | ||
| 608 | } | ||
| 609 | |||
| 610 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_functions.h b/src/core/hle/service/am/application_functions.h new file mode 100644 index 000000000..22aab1c8f --- /dev/null +++ b/src/core/hle/service/am/application_functions.h | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | ||
| 12 | public: | ||
| 13 | explicit IApplicationFunctions(Core::System& system_); | ||
| 14 | ~IApplicationFunctions() override; | ||
| 15 | |||
| 16 | private: | ||
| 17 | void PopLaunchParameter(HLERequestContext& ctx); | ||
| 18 | void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx); | ||
| 19 | void EnsureSaveData(HLERequestContext& ctx); | ||
| 20 | void SetTerminateResult(HLERequestContext& ctx); | ||
| 21 | void GetDisplayVersion(HLERequestContext& ctx); | ||
| 22 | void GetDesiredLanguage(HLERequestContext& ctx); | ||
| 23 | void IsGamePlayRecordingSupported(HLERequestContext& ctx); | ||
| 24 | void InitializeGamePlayRecording(HLERequestContext& ctx); | ||
| 25 | void SetGamePlayRecordingState(HLERequestContext& ctx); | ||
| 26 | void NotifyRunning(HLERequestContext& ctx); | ||
| 27 | void GetPseudoDeviceId(HLERequestContext& ctx); | ||
| 28 | void ExtendSaveData(HLERequestContext& ctx); | ||
| 29 | void GetSaveDataSize(HLERequestContext& ctx); | ||
| 30 | void CreateCacheStorage(HLERequestContext& ctx); | ||
| 31 | void GetSaveDataSizeMax(HLERequestContext& ctx); | ||
| 32 | void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); | ||
| 33 | void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); | ||
| 34 | void BeginBlockingHomeButton(HLERequestContext& ctx); | ||
| 35 | void EndBlockingHomeButton(HLERequestContext& ctx); | ||
| 36 | void EnableApplicationCrashReport(HLERequestContext& ctx); | ||
| 37 | void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx); | ||
| 38 | void SetApplicationCopyrightImage(HLERequestContext& ctx); | ||
| 39 | void SetApplicationCopyrightVisibility(HLERequestContext& ctx); | ||
| 40 | void QueryApplicationPlayStatistics(HLERequestContext& ctx); | ||
| 41 | void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx); | ||
| 42 | void ExecuteProgram(HLERequestContext& ctx); | ||
| 43 | void ClearUserChannel(HLERequestContext& ctx); | ||
| 44 | void UnpopToUserChannel(HLERequestContext& ctx); | ||
| 45 | void GetPreviousProgramIndex(HLERequestContext& ctx); | ||
| 46 | void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx); | ||
| 47 | void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx); | ||
| 48 | void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx); | ||
| 49 | void GetNotificationStorageChannelEvent(HLERequestContext& ctx); | ||
| 50 | void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx); | ||
| 51 | void PrepareForJit(HLERequestContext& ctx); | ||
| 52 | |||
| 53 | KernelHelpers::ServiceContext service_context; | ||
| 54 | |||
| 55 | bool launch_popped_account_preselect = false; | ||
| 56 | s32 previous_program_index{-1}; | ||
| 57 | Kernel::KEvent* gpu_error_detected_event; | ||
| 58 | Kernel::KEvent* friend_invitation_storage_channel_event; | ||
| 59 | Kernel::KEvent* notification_storage_channel_event; | ||
| 60 | Kernel::KEvent* health_warning_disappeared_system_event; | ||
| 61 | }; | ||
| 62 | |||
| 63 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_proxy.cpp b/src/core/hle/service/am/application_proxy.cpp new file mode 100644 index 000000000..e9cd0aa71 --- /dev/null +++ b/src/core/hle/service/am/application_proxy.cpp | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet_common_functions.h" | ||
| 5 | #include "core/hle/service/am/application_functions.h" | ||
| 6 | #include "core/hle/service/am/application_proxy.h" | ||
| 7 | #include "core/hle/service/am/audio_controller.h" | ||
| 8 | #include "core/hle/service/am/common_state_getter.h" | ||
| 9 | #include "core/hle/service/am/debug_functions.h" | ||
| 10 | #include "core/hle/service/am/display_controller.h" | ||
| 11 | #include "core/hle/service/am/library_applet_creator.h" | ||
| 12 | #include "core/hle/service/am/library_applet_self_accessor.h" | ||
| 13 | #include "core/hle/service/am/process_winding_controller.h" | ||
| 14 | #include "core/hle/service/am/self_controller.h" | ||
| 15 | #include "core/hle/service/am/window_controller.h" | ||
| 16 | #include "core/hle/service/ipc_helpers.h" | ||
| 17 | |||
| 18 | namespace Service::AM { | ||
| 19 | |||
| 20 | IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 21 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 22 | Core::System& system_) | ||
| 23 | : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, | ||
| 24 | msg_queue{std::move(msg_queue_)} { | ||
| 25 | // clang-format off | ||
| 26 | static const FunctionInfo functions[] = { | ||
| 27 | {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 28 | {1, &IApplicationProxy::GetSelfController, "GetSelfController"}, | ||
| 29 | {2, &IApplicationProxy::GetWindowController, "GetWindowController"}, | ||
| 30 | {3, &IApplicationProxy::GetAudioController, "GetAudioController"}, | ||
| 31 | {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"}, | ||
| 32 | {10, &IApplicationProxy::GetProcessWindingController, "GetProcessWindingController"}, | ||
| 33 | {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 34 | {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"}, | ||
| 35 | {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 36 | }; | ||
| 37 | // clang-format on | ||
| 38 | |||
| 39 | RegisterHandlers(functions); | ||
| 40 | } | ||
| 41 | |||
| 42 | void IApplicationProxy::GetAudioController(HLERequestContext& ctx) { | ||
| 43 | LOG_DEBUG(Service_AM, "called"); | ||
| 44 | |||
| 45 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 46 | rb.Push(ResultSuccess); | ||
| 47 | rb.PushIpcInterface<IAudioController>(system); | ||
| 48 | } | ||
| 49 | |||
| 50 | void IApplicationProxy::GetDisplayController(HLERequestContext& ctx) { | ||
| 51 | LOG_DEBUG(Service_AM, "called"); | ||
| 52 | |||
| 53 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 54 | rb.Push(ResultSuccess); | ||
| 55 | rb.PushIpcInterface<IDisplayController>(system); | ||
| 56 | } | ||
| 57 | |||
| 58 | void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) { | ||
| 59 | LOG_DEBUG(Service_AM, "called"); | ||
| 60 | |||
| 61 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 62 | rb.Push(ResultSuccess); | ||
| 63 | rb.PushIpcInterface<IProcessWindingController>(system); | ||
| 64 | } | ||
| 65 | |||
| 66 | void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) { | ||
| 67 | LOG_DEBUG(Service_AM, "called"); | ||
| 68 | |||
| 69 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 70 | rb.Push(ResultSuccess); | ||
| 71 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 72 | } | ||
| 73 | |||
| 74 | void IApplicationProxy::GetWindowController(HLERequestContext& ctx) { | ||
| 75 | LOG_DEBUG(Service_AM, "called"); | ||
| 76 | |||
| 77 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 78 | rb.Push(ResultSuccess); | ||
| 79 | rb.PushIpcInterface<IWindowController>(system); | ||
| 80 | } | ||
| 81 | |||
| 82 | void IApplicationProxy::GetSelfController(HLERequestContext& ctx) { | ||
| 83 | LOG_DEBUG(Service_AM, "called"); | ||
| 84 | |||
| 85 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 86 | rb.Push(ResultSuccess); | ||
| 87 | rb.PushIpcInterface<ISelfController>(system, nvnflinger); | ||
| 88 | } | ||
| 89 | |||
| 90 | void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 91 | LOG_DEBUG(Service_AM, "called"); | ||
| 92 | |||
| 93 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 94 | rb.Push(ResultSuccess); | ||
| 95 | rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); | ||
| 96 | } | ||
| 97 | |||
| 98 | void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 99 | LOG_DEBUG(Service_AM, "called"); | ||
| 100 | |||
| 101 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 102 | rb.Push(ResultSuccess); | ||
| 103 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | ||
| 104 | } | ||
| 105 | |||
| 106 | void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) { | ||
| 107 | LOG_DEBUG(Service_AM, "called"); | ||
| 108 | |||
| 109 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 110 | rb.Push(ResultSuccess); | ||
| 111 | rb.PushIpcInterface<IApplicationFunctions>(system); | ||
| 112 | } | ||
| 113 | |||
| 114 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_proxy.h b/src/core/hle/service/am/application_proxy.h new file mode 100644 index 000000000..4f620242b --- /dev/null +++ b/src/core/hle/service/am/application_proxy.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | ||
| 12 | public: | ||
| 13 | explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 14 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 15 | Core::System& system_); | ||
| 16 | |||
| 17 | private: | ||
| 18 | void GetAudioController(HLERequestContext& ctx); | ||
| 19 | void GetDisplayController(HLERequestContext& ctx); | ||
| 20 | void GetProcessWindingController(HLERequestContext& ctx); | ||
| 21 | void GetDebugFunctions(HLERequestContext& ctx); | ||
| 22 | void GetWindowController(HLERequestContext& ctx); | ||
| 23 | void GetSelfController(HLERequestContext& ctx); | ||
| 24 | void GetCommonStateGetter(HLERequestContext& ctx); | ||
| 25 | void GetLibraryAppletCreator(HLERequestContext& ctx); | ||
| 26 | void GetApplicationFunctions(HLERequestContext& ctx); | ||
| 27 | |||
| 28 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 29 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 30 | }; | ||
| 31 | |||
| 32 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/audio_controller.cpp b/src/core/hle/service/am/audio_controller.cpp new file mode 100644 index 000000000..ae75db174 --- /dev/null +++ b/src/core/hle/service/am/audio_controller.cpp | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/audio_controller.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IAudioController::IAudioController(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IAudioController"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"}, | ||
| 14 | {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"}, | ||
| 15 | {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"}, | ||
| 16 | {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"}, | ||
| 17 | {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"}, | ||
| 18 | }; | ||
| 19 | // clang-format on | ||
| 20 | |||
| 21 | RegisterHandlers(functions); | ||
| 22 | } | ||
| 23 | |||
| 24 | IAudioController::~IAudioController() = default; | ||
| 25 | |||
| 26 | void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 27 | IPC::RequestParser rp{ctx}; | ||
| 28 | const float main_applet_volume_tmp = rp.Pop<float>(); | ||
| 29 | const float library_applet_volume_tmp = rp.Pop<float>(); | ||
| 30 | |||
| 31 | LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}", | ||
| 32 | main_applet_volume_tmp, library_applet_volume_tmp); | ||
| 33 | |||
| 34 | // Ensure the volume values remain within the 0-100% range | ||
| 35 | main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume); | ||
| 36 | library_applet_volume = | ||
| 37 | std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume); | ||
| 38 | |||
| 39 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 40 | rb.Push(ResultSuccess); | ||
| 41 | } | ||
| 42 | |||
| 43 | void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 44 | LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume); | ||
| 45 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 46 | rb.Push(ResultSuccess); | ||
| 47 | rb.Push(main_applet_volume); | ||
| 48 | } | ||
| 49 | |||
| 50 | void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 51 | LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume); | ||
| 52 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 53 | rb.Push(ResultSuccess); | ||
| 54 | rb.Push(library_applet_volume); | ||
| 55 | } | ||
| 56 | |||
| 57 | void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) { | ||
| 58 | struct Parameters { | ||
| 59 | float volume; | ||
| 60 | s64 fade_time_ns; | ||
| 61 | }; | ||
| 62 | static_assert(sizeof(Parameters) == 16); | ||
| 63 | |||
| 64 | IPC::RequestParser rp{ctx}; | ||
| 65 | const auto parameters = rp.PopRaw<Parameters>(); | ||
| 66 | |||
| 67 | LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume, | ||
| 68 | parameters.fade_time_ns); | ||
| 69 | |||
| 70 | main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume); | ||
| 71 | fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns}; | ||
| 72 | |||
| 73 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 74 | rb.Push(ResultSuccess); | ||
| 75 | } | ||
| 76 | |||
| 77 | void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) { | ||
| 78 | IPC::RequestParser rp{ctx}; | ||
| 79 | const float transparent_volume_rate_tmp = rp.Pop<float>(); | ||
| 80 | |||
| 81 | LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp); | ||
| 82 | |||
| 83 | // Clamp volume range to 0-100%. | ||
| 84 | transparent_volume_rate = | ||
| 85 | std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume); | ||
| 86 | |||
| 87 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 88 | rb.Push(ResultSuccess); | ||
| 89 | } | ||
| 90 | |||
| 91 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/audio_controller.h b/src/core/hle/service/am/audio_controller.h new file mode 100644 index 000000000..a47e3bad8 --- /dev/null +++ b/src/core/hle/service/am/audio_controller.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IAudioController final : public ServiceFramework<IAudioController> { | ||
| 11 | public: | ||
| 12 | explicit IAudioController(Core::System& system_); | ||
| 13 | ~IAudioController() override; | ||
| 14 | |||
| 15 | private: | ||
| 16 | void SetExpectedMasterVolume(HLERequestContext& ctx); | ||
| 17 | void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx); | ||
| 18 | void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx); | ||
| 19 | void ChangeMainAppletMasterVolume(HLERequestContext& ctx); | ||
| 20 | void SetTransparentAudioRate(HLERequestContext& ctx); | ||
| 21 | |||
| 22 | static constexpr float min_allowed_volume = 0.0f; | ||
| 23 | static constexpr float max_allowed_volume = 1.0f; | ||
| 24 | |||
| 25 | float main_applet_volume{0.25f}; | ||
| 26 | float library_applet_volume{max_allowed_volume}; | ||
| 27 | float transparent_volume_rate{min_allowed_volume}; | ||
| 28 | |||
| 29 | // Volume transition fade time in nanoseconds. | ||
| 30 | // e.g. If the main applet volume was 0% and was changed to 50% | ||
| 31 | // with a fade of 50ns, then over the course of 50ns, | ||
| 32 | // the volume will gradually fade up to 50% | ||
| 33 | std::chrono::nanoseconds fade_time_ns{0}; | ||
| 34 | }; | ||
| 35 | |||
| 36 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/common_state_getter.cpp b/src/core/hle/service/am/common_state_getter.cpp new file mode 100644 index 000000000..0b54b769d --- /dev/null +++ b/src/core/hle/service/am/common_state_getter.cpp | |||
| @@ -0,0 +1,288 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/hle/service/am/am_results.h" | ||
| 6 | #include "core/hle/service/am/common_state_getter.h" | ||
| 7 | #include "core/hle/service/am/lock_accessor.h" | ||
| 8 | #include "core/hle/service/apm/apm_controller.h" | ||
| 9 | #include "core/hle/service/apm/apm_interface.h" | ||
| 10 | #include "core/hle/service/ipc_helpers.h" | ||
| 11 | #include "core/hle/service/pm/pm.h" | ||
| 12 | #include "core/hle/service/sm/sm.h" | ||
| 13 | #include "core/hle/service/vi/vi.h" | ||
| 14 | |||
| 15 | namespace Service::AM { | ||
| 16 | |||
| 17 | ICommonStateGetter::ICommonStateGetter(Core::System& system_, | ||
| 18 | std::shared_ptr<AppletMessageQueue> msg_queue_) | ||
| 19 | : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)}, | ||
| 20 | service_context{system_, "ICommonStateGetter"} { | ||
| 21 | // clang-format off | ||
| 22 | static const FunctionInfo functions[] = { | ||
| 23 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, | ||
| 24 | {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, | ||
| 25 | {2, nullptr, "GetThisAppletKind"}, | ||
| 26 | {3, nullptr, "AllowToEnterSleep"}, | ||
| 27 | {4, nullptr, "DisallowToEnterSleep"}, | ||
| 28 | {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, | ||
| 29 | {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, | ||
| 30 | {7, nullptr, "GetCradleStatus"}, | ||
| 31 | {8, &ICommonStateGetter::GetBootMode, "GetBootMode"}, | ||
| 32 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, | ||
| 33 | {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"}, | ||
| 34 | {11, nullptr, "ReleaseSleepLock"}, | ||
| 35 | {12, nullptr, "ReleaseSleepLockTransiently"}, | ||
| 36 | {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"}, | ||
| 37 | {14, nullptr, "GetWakeupCount"}, | ||
| 38 | {20, nullptr, "PushToGeneralChannel"}, | ||
| 39 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, | ||
| 40 | {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"}, | ||
| 41 | {32, nullptr, "GetWriterLockAccessorEx"}, | ||
| 42 | {40, nullptr, "GetCradleFwVersion"}, | ||
| 43 | {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"}, | ||
| 44 | {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"}, | ||
| 45 | {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"}, | ||
| 46 | {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"}, | ||
| 47 | {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"}, | ||
| 48 | {55, nullptr, "IsInControllerFirmwareUpdateSection"}, | ||
| 49 | {59, nullptr, "SetVrPositionForDebug"}, | ||
| 50 | {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, | ||
| 51 | {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, | ||
| 52 | {62, nullptr, "GetHdcpAuthenticationState"}, | ||
| 53 | {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"}, | ||
| 54 | {64, nullptr, "SetTvPowerStateMatchingMode"}, | ||
| 55 | {65, nullptr, "GetApplicationIdByContentActionName"}, | ||
| 56 | {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, | ||
| 57 | {67, nullptr, "CancelCpuBoostMode"}, | ||
| 58 | {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"}, | ||
| 59 | {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"}, | ||
| 60 | {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, | ||
| 61 | {91, nullptr, "GetCurrentPerformanceConfiguration"}, | ||
| 62 | {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, | ||
| 63 | {110, nullptr, "OpenMyGpuErrorHandler"}, | ||
| 64 | {120, nullptr, "GetAppletLaunchedHistory"}, | ||
| 65 | {200, nullptr, "GetOperationModeSystemInfo"}, | ||
| 66 | {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"}, | ||
| 67 | {400, nullptr, "ActivateMigrationService"}, | ||
| 68 | {401, nullptr, "DeactivateMigrationService"}, | ||
| 69 | {500, nullptr, "DisableSleepTillShutdown"}, | ||
| 70 | {501, nullptr, "SuppressDisablingSleepTemporarily"}, | ||
| 71 | {502, nullptr, "IsSleepEnabled"}, | ||
| 72 | {503, nullptr, "IsDisablingSleepSuppressed"}, | ||
| 73 | {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, | ||
| 74 | }; | ||
| 75 | // clang-format on | ||
| 76 | |||
| 77 | RegisterHandlers(functions); | ||
| 78 | |||
| 79 | sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent"); | ||
| 80 | |||
| 81 | // Configure applets to be in foreground state | ||
| 82 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); | ||
| 83 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | ||
| 84 | } | ||
| 85 | |||
| 86 | ICommonStateGetter::~ICommonStateGetter() { | ||
| 87 | service_context.CloseEvent(sleep_lock_event); | ||
| 88 | }; | ||
| 89 | |||
| 90 | void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { | ||
| 91 | LOG_DEBUG(Service_AM, "called"); | ||
| 92 | |||
| 93 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 94 | rb.Push(ResultSuccess); | ||
| 95 | rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode | ||
| 96 | } | ||
| 97 | |||
| 98 | void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) { | ||
| 99 | LOG_DEBUG(Service_AM, "called"); | ||
| 100 | |||
| 101 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 102 | rb.Push(ResultSuccess); | ||
| 103 | rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent()); | ||
| 104 | } | ||
| 105 | |||
| 106 | void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) { | ||
| 107 | LOG_DEBUG(Service_AM, "called"); | ||
| 108 | |||
| 109 | const auto message = msg_queue->PopMessage(); | ||
| 110 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 111 | |||
| 112 | if (message == AppletMessageQueue::AppletMessage::None) { | ||
| 113 | LOG_ERROR(Service_AM, "Message queue is empty"); | ||
| 114 | rb.Push(AM::ResultNoMessages); | ||
| 115 | rb.PushEnum<AppletMessageQueue::AppletMessage>(message); | ||
| 116 | return; | ||
| 117 | } | ||
| 118 | |||
| 119 | rb.Push(ResultSuccess); | ||
| 120 | rb.PushEnum<AppletMessageQueue::AppletMessage>(message); | ||
| 121 | } | ||
| 122 | |||
| 123 | void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) { | ||
| 124 | LOG_DEBUG(Service_AM, "(STUBBED) called"); | ||
| 125 | |||
| 126 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 127 | rb.Push(ResultSuccess); | ||
| 128 | rb.Push(static_cast<u8>(FocusState::InFocus)); | ||
| 129 | } | ||
| 130 | |||
| 131 | void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) { | ||
| 132 | const bool use_docked_mode{Settings::IsDockedMode()}; | ||
| 133 | LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); | ||
| 134 | |||
| 135 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 136 | rb.Push(ResultSuccess); | ||
| 137 | rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); | ||
| 138 | } | ||
| 139 | |||
| 140 | void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) { | ||
| 141 | LOG_DEBUG(Service_AM, "called"); | ||
| 142 | |||
| 143 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 144 | rb.Push(ResultSuccess); | ||
| 145 | rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode()); | ||
| 146 | } | ||
| 147 | |||
| 148 | void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) { | ||
| 149 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 150 | |||
| 151 | // Sleep lock is acquired immediately. | ||
| 152 | sleep_lock_event->Signal(); | ||
| 153 | |||
| 154 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 155 | rb.Push(ResultSuccess); | ||
| 156 | } | ||
| 157 | |||
| 158 | void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) { | ||
| 159 | IPC::RequestParser rp{ctx}; | ||
| 160 | const auto unknown = rp.Pop<u32>(); | ||
| 161 | |||
| 162 | LOG_INFO(Service_AM, "called, unknown={}", unknown); | ||
| 163 | |||
| 164 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 165 | |||
| 166 | rb.Push(ResultSuccess); | ||
| 167 | rb.PushIpcInterface<ILockAccessor>(system); | ||
| 168 | } | ||
| 169 | |||
| 170 | void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) { | ||
| 171 | LOG_WARNING(Service_AM, "called"); | ||
| 172 | |||
| 173 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 174 | rb.Push(ResultSuccess); | ||
| 175 | rb.PushCopyObjects(sleep_lock_event->GetReadableEvent()); | ||
| 176 | } | ||
| 177 | |||
| 178 | void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { | ||
| 179 | LOG_DEBUG(Service_AM, "called"); | ||
| 180 | |||
| 181 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 182 | rb.Push(ResultSuccess); | ||
| 183 | rb.Push(vr_mode_state); | ||
| 184 | } | ||
| 185 | |||
| 186 | void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) { | ||
| 187 | IPC::RequestParser rp{ctx}; | ||
| 188 | vr_mode_state = rp.Pop<bool>(); | ||
| 189 | |||
| 190 | LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off"); | ||
| 191 | |||
| 192 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 193 | rb.Push(ResultSuccess); | ||
| 194 | } | ||
| 195 | |||
| 196 | void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) { | ||
| 197 | IPC::RequestParser rp{ctx}; | ||
| 198 | const auto is_lcd_backlight_off_enabled = rp.Pop<bool>(); | ||
| 199 | |||
| 200 | LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}", | ||
| 201 | is_lcd_backlight_off_enabled); | ||
| 202 | |||
| 203 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 204 | rb.Push(ResultSuccess); | ||
| 205 | } | ||
| 206 | |||
| 207 | void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) { | ||
| 208 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 209 | |||
| 210 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 211 | rb.Push(ResultSuccess); | ||
| 212 | } | ||
| 213 | |||
| 214 | void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) { | ||
| 215 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 216 | |||
| 217 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 218 | rb.Push(ResultSuccess); | ||
| 219 | } | ||
| 220 | |||
| 221 | void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) { | ||
| 222 | LOG_DEBUG(Service_AM, "called"); | ||
| 223 | |||
| 224 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 225 | rb.Push(ResultSuccess); | ||
| 226 | rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent()); | ||
| 227 | } | ||
| 228 | |||
| 229 | void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) { | ||
| 230 | LOG_DEBUG(Service_AM, "called"); | ||
| 231 | |||
| 232 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 233 | rb.Push(ResultSuccess); | ||
| 234 | |||
| 235 | if (Settings::IsDockedMode()) { | ||
| 236 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); | ||
| 237 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); | ||
| 238 | } else { | ||
| 239 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); | ||
| 240 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) { | ||
| 245 | LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS"); | ||
| 246 | |||
| 247 | const auto& sm = system.ServiceManager(); | ||
| 248 | const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys"); | ||
| 249 | ASSERT(apm_sys != nullptr); | ||
| 250 | |||
| 251 | apm_sys->SetCpuBoostMode(ctx); | ||
| 252 | } | ||
| 253 | |||
| 254 | void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) { | ||
| 255 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 256 | |||
| 257 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 258 | rb.Push(ResultSuccess); | ||
| 259 | rb.Push(0); | ||
| 260 | } | ||
| 261 | |||
| 262 | void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) { | ||
| 263 | IPC::RequestParser rp{ctx}; | ||
| 264 | const auto system_button{rp.PopEnum<SystemButtonType>()}; | ||
| 265 | |||
| 266 | LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button); | ||
| 267 | |||
| 268 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 269 | rb.Push(ResultSuccess); | ||
| 270 | } | ||
| 271 | |||
| 272 | void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) { | ||
| 273 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 274 | |||
| 275 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 276 | rb.Push(ResultSuccess); | ||
| 277 | rb.PushEnum(SysPlatformRegion::Global); | ||
| 278 | } | ||
| 279 | |||
| 280 | void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled( | ||
| 281 | HLERequestContext& ctx) { | ||
| 282 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 283 | |||
| 284 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 285 | rb.Push(ResultSuccess); | ||
| 286 | } | ||
| 287 | |||
| 288 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/common_state_getter.h b/src/core/hle/service/am/common_state_getter.h new file mode 100644 index 000000000..11d66f10a --- /dev/null +++ b/src/core/hle/service/am/common_state_getter.h | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 10 | |||
| 11 | namespace Service::AM { | ||
| 12 | |||
| 13 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | ||
| 14 | public: | ||
| 15 | explicit ICommonStateGetter(Core::System& system_, | ||
| 16 | std::shared_ptr<AppletMessageQueue> msg_queue_); | ||
| 17 | ~ICommonStateGetter() override; | ||
| 18 | |||
| 19 | private: | ||
| 20 | // This is nn::oe::FocusState | ||
| 21 | enum class FocusState : u8 { | ||
| 22 | InFocus = 1, | ||
| 23 | NotInFocus = 2, | ||
| 24 | Background = 3, | ||
| 25 | }; | ||
| 26 | |||
| 27 | // This is nn::oe::OperationMode | ||
| 28 | enum class OperationMode : u8 { | ||
| 29 | Handheld = 0, | ||
| 30 | Docked = 1, | ||
| 31 | }; | ||
| 32 | |||
| 33 | // This is nn::am::service::SystemButtonType | ||
| 34 | enum class SystemButtonType { | ||
| 35 | None, | ||
| 36 | HomeButtonShortPressing, | ||
| 37 | HomeButtonLongPressing, | ||
| 38 | PowerButtonShortPressing, | ||
| 39 | PowerButtonLongPressing, | ||
| 40 | ShutdownSystem, | ||
| 41 | CaptureButtonShortPressing, | ||
| 42 | CaptureButtonLongPressing, | ||
| 43 | }; | ||
| 44 | |||
| 45 | enum class SysPlatformRegion : s32 { | ||
| 46 | Global = 1, | ||
| 47 | Terra = 2, | ||
| 48 | }; | ||
| 49 | |||
| 50 | void GetEventHandle(HLERequestContext& ctx); | ||
| 51 | void ReceiveMessage(HLERequestContext& ctx); | ||
| 52 | void GetCurrentFocusState(HLERequestContext& ctx); | ||
| 53 | void RequestToAcquireSleepLock(HLERequestContext& ctx); | ||
| 54 | void GetAcquiredSleepLockEvent(HLERequestContext& ctx); | ||
| 55 | void GetReaderLockAccessorEx(HLERequestContext& ctx); | ||
| 56 | void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx); | ||
| 57 | void GetOperationMode(HLERequestContext& ctx); | ||
| 58 | void GetPerformanceMode(HLERequestContext& ctx); | ||
| 59 | void GetBootMode(HLERequestContext& ctx); | ||
| 60 | void IsVrModeEnabled(HLERequestContext& ctx); | ||
| 61 | void SetVrModeEnabled(HLERequestContext& ctx); | ||
| 62 | void SetLcdBacklighOffEnabled(HLERequestContext& ctx); | ||
| 63 | void BeginVrModeEx(HLERequestContext& ctx); | ||
| 64 | void EndVrModeEx(HLERequestContext& ctx); | ||
| 65 | void GetDefaultDisplayResolution(HLERequestContext& ctx); | ||
| 66 | void SetCpuBoostMode(HLERequestContext& ctx); | ||
| 67 | void GetBuiltInDisplayType(HLERequestContext& ctx); | ||
| 68 | void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx); | ||
| 69 | void GetSettingsPlatformRegion(HLERequestContext& ctx); | ||
| 70 | void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx); | ||
| 71 | |||
| 72 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 73 | bool vr_mode_state{}; | ||
| 74 | Kernel::KEvent* sleep_lock_event; | ||
| 75 | KernelHelpers::ServiceContext service_context; | ||
| 76 | }; | ||
| 77 | |||
| 78 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/debug_functions.cpp b/src/core/hle/service/am/debug_functions.cpp new file mode 100644 index 000000000..f80b970f2 --- /dev/null +++ b/src/core/hle/service/am/debug_functions.cpp | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/debug_functions.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IDebugFunctions::IDebugFunctions(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IDebugFunctions"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, | ||
| 14 | {1, nullptr, "OpenMainApplication"}, | ||
| 15 | {10, nullptr, "PerformSystemButtonPressing"}, | ||
| 16 | {20, nullptr, "InvalidateTransitionLayer"}, | ||
| 17 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, | ||
| 18 | {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"}, | ||
| 19 | {40, nullptr, "GetAppletResourceUsageInfo"}, | ||
| 20 | {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"}, | ||
| 21 | {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"}, | ||
| 22 | {100, nullptr, "SetCpuBoostModeForApplet"}, | ||
| 23 | {101, nullptr, "CancelCpuBoostModeForApplet"}, | ||
| 24 | {110, nullptr, "PushToAppletBoundChannelForDebug"}, | ||
| 25 | {111, nullptr, "TryPopFromAppletBoundChannelForDebug"}, | ||
| 26 | {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"}, | ||
| 27 | {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"}, | ||
| 28 | {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"}, | ||
| 29 | {130, nullptr, "FriendInvitationSetApplicationParameter"}, | ||
| 30 | {131, nullptr, "FriendInvitationClearApplicationParameter"}, | ||
| 31 | {132, nullptr, "FriendInvitationPushApplicationParameter"}, | ||
| 32 | {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"}, | ||
| 33 | {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"}, | ||
| 34 | {300, nullptr, "TerminateAllRunningApplicationsForDebug"}, | ||
| 35 | {900, nullptr, "GetGrcProcessLaunchedSystemEvent"}, | ||
| 36 | }; | ||
| 37 | // clang-format on | ||
| 38 | |||
| 39 | RegisterHandlers(functions); | ||
| 40 | } | ||
| 41 | |||
| 42 | IDebugFunctions::~IDebugFunctions() = default; | ||
| 43 | |||
| 44 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/debug_functions.h b/src/core/hle/service/am/debug_functions.h new file mode 100644 index 000000000..d55968743 --- /dev/null +++ b/src/core/hle/service/am/debug_functions.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IDebugFunctions final : public ServiceFramework<IDebugFunctions> { | ||
| 11 | public: | ||
| 12 | explicit IDebugFunctions(Core::System& system_); | ||
| 13 | ~IDebugFunctions() override; | ||
| 14 | }; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/display_controller.cpp b/src/core/hle/service/am/display_controller.cpp new file mode 100644 index 000000000..d4d3d60e7 --- /dev/null +++ b/src/core/hle/service/am/display_controller.cpp | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/display_controller.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IDisplayController::IDisplayController(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IDisplayController"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, nullptr, "GetLastForegroundCaptureImage"}, | ||
| 14 | {1, nullptr, "UpdateLastForegroundCaptureImage"}, | ||
| 15 | {2, nullptr, "GetLastApplicationCaptureImage"}, | ||
| 16 | {3, nullptr, "GetCallerAppletCaptureImage"}, | ||
| 17 | {4, nullptr, "UpdateCallerAppletCaptureImage"}, | ||
| 18 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, | ||
| 19 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, | ||
| 20 | {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"}, | ||
| 21 | {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"}, | ||
| 22 | {9, nullptr, "CopyBetweenCaptureBuffers"}, | ||
| 23 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, | ||
| 24 | {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, | ||
| 25 | {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, | ||
| 26 | {13, nullptr, "ReleaseLastForegroundCaptureBuffer"}, | ||
| 27 | {14, nullptr, "AcquireCallerAppletCaptureBuffer"}, | ||
| 28 | {15, nullptr, "ReleaseCallerAppletCaptureBuffer"}, | ||
| 29 | {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, | ||
| 30 | {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, | ||
| 31 | {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, | ||
| 32 | {20, nullptr, "ClearCaptureBuffer"}, | ||
| 33 | {21, nullptr, "ClearAppletTransitionBuffer"}, | ||
| 34 | {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"}, | ||
| 35 | {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, | ||
| 36 | {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"}, | ||
| 37 | {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"}, | ||
| 38 | {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"}, | ||
| 39 | {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"}, | ||
| 40 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, | ||
| 41 | }; | ||
| 42 | // clang-format on | ||
| 43 | |||
| 44 | RegisterHandlers(functions); | ||
| 45 | } | ||
| 46 | |||
| 47 | IDisplayController::~IDisplayController() = default; | ||
| 48 | |||
| 49 | void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) { | ||
| 50 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 51 | |||
| 52 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 53 | rb.Push(ResultSuccess); | ||
| 54 | rb.Push(1u); | ||
| 55 | rb.Push(1); | ||
| 56 | } | ||
| 57 | |||
| 58 | void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { | ||
| 59 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 60 | |||
| 61 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 62 | rb.Push(ResultSuccess); | ||
| 63 | } | ||
| 64 | |||
| 65 | void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 66 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 67 | |||
| 68 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 69 | rb.Push(ResultSuccess); | ||
| 70 | rb.Push(1U); | ||
| 71 | rb.Push(1); | ||
| 72 | } | ||
| 73 | |||
| 74 | void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 75 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 76 | |||
| 77 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 78 | rb.Push(ResultSuccess); | ||
| 79 | } | ||
| 80 | |||
| 81 | void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 82 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 83 | |||
| 84 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 85 | rb.Push(ResultSuccess); | ||
| 86 | rb.Push(1U); | ||
| 87 | rb.Push(1); | ||
| 88 | } | ||
| 89 | |||
| 90 | void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 91 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 92 | |||
| 93 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 94 | rb.Push(ResultSuccess); | ||
| 95 | } | ||
| 96 | |||
| 97 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/display_controller.h b/src/core/hle/service/am/display_controller.h new file mode 100644 index 000000000..32f819294 --- /dev/null +++ b/src/core/hle/service/am/display_controller.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IDisplayController final : public ServiceFramework<IDisplayController> { | ||
| 11 | public: | ||
| 12 | explicit IDisplayController(Core::System& system_); | ||
| 13 | ~IDisplayController() override; | ||
| 14 | |||
| 15 | private: | ||
| 16 | void GetCallerAppletCaptureImageEx(HLERequestContext& ctx); | ||
| 17 | void TakeScreenShotOfOwnLayer(HLERequestContext& ctx); | ||
| 18 | void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 19 | void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 20 | void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 21 | void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 22 | }; | ||
| 23 | |||
| 24 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/global_state_controller.cpp b/src/core/hle/service/am/global_state_controller.cpp new file mode 100644 index 000000000..ed0eb7108 --- /dev/null +++ b/src/core/hle/service/am/global_state_controller.cpp | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/global_state_controller.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IGlobalStateController::IGlobalStateController(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IGlobalStateController"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, nullptr, "RequestToEnterSleep"}, | ||
| 14 | {1, nullptr, "EnterSleep"}, | ||
| 15 | {2, nullptr, "StartSleepSequence"}, | ||
| 16 | {3, nullptr, "StartShutdownSequence"}, | ||
| 17 | {4, nullptr, "StartRebootSequence"}, | ||
| 18 | {9, nullptr, "IsAutoPowerDownRequested"}, | ||
| 19 | {10, nullptr, "LoadAndApplyIdlePolicySettings"}, | ||
| 20 | {11, nullptr, "NotifyCecSettingsChanged"}, | ||
| 21 | {12, nullptr, "SetDefaultHomeButtonLongPressTime"}, | ||
| 22 | {13, nullptr, "UpdateDefaultDisplayResolution"}, | ||
| 23 | {14, nullptr, "ShouldSleepOnBoot"}, | ||
| 24 | {15, nullptr, "GetHdcpAuthenticationFailedEvent"}, | ||
| 25 | {30, nullptr, "OpenCradleFirmwareUpdater"}, | ||
| 26 | }; | ||
| 27 | // clang-format on | ||
| 28 | |||
| 29 | RegisterHandlers(functions); | ||
| 30 | } | ||
| 31 | |||
| 32 | IGlobalStateController::~IGlobalStateController() = default; | ||
| 33 | |||
| 34 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/global_state_controller.h b/src/core/hle/service/am/global_state_controller.h new file mode 100644 index 000000000..7125464a1 --- /dev/null +++ b/src/core/hle/service/am/global_state_controller.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { | ||
| 11 | public: | ||
| 12 | explicit IGlobalStateController(Core::System& system_); | ||
| 13 | ~IGlobalStateController() override; | ||
| 14 | }; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/home_menu_functions.cpp b/src/core/hle/service/am/home_menu_functions.cpp new file mode 100644 index 000000000..640e9fbb7 --- /dev/null +++ b/src/core/hle/service/am/home_menu_functions.cpp | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/home_menu_functions.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system, | ||
| 11 | "IHomeMenuFunctions"} { | ||
| 12 | // clang-format off | ||
| 13 | static const FunctionInfo functions[] = { | ||
| 14 | {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"}, | ||
| 15 | {11, nullptr, "LockForeground"}, | ||
| 16 | {12, nullptr, "UnlockForeground"}, | ||
| 17 | {20, nullptr, "PopFromGeneralChannel"}, | ||
| 18 | {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, | ||
| 19 | {30, nullptr, "GetHomeButtonWriterLockAccessor"}, | ||
| 20 | {31, nullptr, "GetWriterLockAccessorEx"}, | ||
| 21 | {40, nullptr, "IsSleepEnabled"}, | ||
| 22 | {41, nullptr, "IsRebootEnabled"}, | ||
| 23 | {50, nullptr, "LaunchSystemApplet"}, | ||
| 24 | {51, nullptr, "LaunchStarter"}, | ||
| 25 | {100, nullptr, "PopRequestLaunchApplicationForDebug"}, | ||
| 26 | {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, | ||
| 27 | {200, nullptr, "LaunchDevMenu"}, | ||
| 28 | {1000, nullptr, "SetLastApplicationExitReason"}, | ||
| 29 | }; | ||
| 30 | // clang-format on | ||
| 31 | |||
| 32 | RegisterHandlers(functions); | ||
| 33 | |||
| 34 | pop_from_general_channel_event = | ||
| 35 | service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent"); | ||
| 36 | } | ||
| 37 | |||
| 38 | IHomeMenuFunctions::~IHomeMenuFunctions() { | ||
| 39 | service_context.CloseEvent(pop_from_general_channel_event); | ||
| 40 | } | ||
| 41 | |||
| 42 | void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) { | ||
| 43 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 44 | |||
| 45 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 46 | rb.Push(ResultSuccess); | ||
| 47 | } | ||
| 48 | |||
| 49 | void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) { | ||
| 50 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 51 | |||
| 52 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 53 | rb.Push(ResultSuccess); | ||
| 54 | rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent()); | ||
| 55 | } | ||
| 56 | |||
| 57 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/home_menu_functions.h b/src/core/hle/service/am/home_menu_functions.h new file mode 100644 index 000000000..e082d5d73 --- /dev/null +++ b/src/core/hle/service/am/home_menu_functions.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { | ||
| 12 | public: | ||
| 13 | explicit IHomeMenuFunctions(Core::System& system_); | ||
| 14 | ~IHomeMenuFunctions() override; | ||
| 15 | |||
| 16 | private: | ||
| 17 | void RequestToGetForeground(HLERequestContext& ctx); | ||
| 18 | void GetPopFromGeneralChannelEvent(HLERequestContext& ctx); | ||
| 19 | |||
| 20 | KernelHelpers::ServiceContext service_context; | ||
| 21 | |||
| 22 | Kernel::KEvent* pop_from_general_channel_event; | ||
| 23 | }; | ||
| 24 | |||
| 25 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_accessor.cpp b/src/core/hle/service/am/library_applet_accessor.cpp new file mode 100644 index 000000000..1cccdfcf2 --- /dev/null +++ b/src/core/hle/service/am/library_applet_accessor.cpp | |||
| @@ -0,0 +1,178 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/am_results.h" | ||
| 5 | #include "core/hle/service/am/library_applet_accessor.h" | ||
| 6 | #include "core/hle/service/am/storage.h" | ||
| 7 | #include "core/hle/service/ipc_helpers.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_, | ||
| 12 | std::shared_ptr<Applets::Applet> applet_) | ||
| 13 | : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} { | ||
| 14 | // clang-format off | ||
| 15 | static const FunctionInfo functions[] = { | ||
| 16 | {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, | ||
| 17 | {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, | ||
| 18 | {10, &ILibraryAppletAccessor::Start, "Start"}, | ||
| 19 | {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"}, | ||
| 20 | {25, nullptr, "Terminate"}, | ||
| 21 | {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, | ||
| 22 | {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, | ||
| 23 | {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"}, | ||
| 24 | {100, &ILibraryAppletAccessor::PushInData, "PushInData"}, | ||
| 25 | {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"}, | ||
| 26 | {102, nullptr, "PushExtraStorage"}, | ||
| 27 | {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"}, | ||
| 28 | {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"}, | ||
| 29 | {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"}, | ||
| 30 | {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"}, | ||
| 31 | {110, nullptr, "NeedsToExitProcess"}, | ||
| 32 | {120, nullptr, "GetLibraryAppletInfo"}, | ||
| 33 | {150, nullptr, "RequestForAppletToGetForeground"}, | ||
| 34 | {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"}, | ||
| 35 | }; | ||
| 36 | // clang-format on | ||
| 37 | |||
| 38 | RegisterHandlers(functions); | ||
| 39 | } | ||
| 40 | |||
| 41 | void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) { | ||
| 42 | LOG_DEBUG(Service_AM, "called"); | ||
| 43 | |||
| 44 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 45 | rb.Push(ResultSuccess); | ||
| 46 | rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent()); | ||
| 47 | } | ||
| 48 | |||
| 49 | void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) { | ||
| 50 | LOG_DEBUG(Service_AM, "called"); | ||
| 51 | |||
| 52 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 53 | rb.Push(ResultSuccess); | ||
| 54 | rb.Push<u32>(applet->TransactionComplete()); | ||
| 55 | } | ||
| 56 | |||
| 57 | void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) { | ||
| 58 | LOG_DEBUG(Service_AM, "called"); | ||
| 59 | |||
| 60 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 61 | rb.Push(applet->GetStatus()); | ||
| 62 | } | ||
| 63 | |||
| 64 | void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) { | ||
| 65 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 66 | |||
| 67 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 68 | rb.Push(ResultSuccess); | ||
| 69 | } | ||
| 70 | |||
| 71 | void ILibraryAppletAccessor::Start(HLERequestContext& ctx) { | ||
| 72 | LOG_DEBUG(Service_AM, "called"); | ||
| 73 | |||
| 74 | ASSERT(applet != nullptr); | ||
| 75 | |||
| 76 | applet->Initialize(); | ||
| 77 | applet->Execute(); | ||
| 78 | |||
| 79 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 80 | rb.Push(ResultSuccess); | ||
| 81 | } | ||
| 82 | |||
| 83 | void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) { | ||
| 84 | LOG_DEBUG(Service_AM, "called"); | ||
| 85 | |||
| 86 | ASSERT(applet != nullptr); | ||
| 87 | |||
| 88 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 89 | rb.Push(applet->RequestExit()); | ||
| 90 | } | ||
| 91 | |||
| 92 | void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) { | ||
| 93 | LOG_DEBUG(Service_AM, "called"); | ||
| 94 | |||
| 95 | IPC::RequestParser rp{ctx}; | ||
| 96 | applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>().lock()); | ||
| 97 | |||
| 98 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 99 | rb.Push(ResultSuccess); | ||
| 100 | } | ||
| 101 | |||
| 102 | void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) { | ||
| 103 | LOG_DEBUG(Service_AM, "called"); | ||
| 104 | |||
| 105 | auto storage = applet->GetBroker().PopNormalDataToGame(); | ||
| 106 | if (storage == nullptr) { | ||
| 107 | LOG_DEBUG(Service_AM, | ||
| 108 | "storage is a nullptr. There is no data in the current normal channel"); | ||
| 109 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 110 | rb.Push(AM::ResultNoDataInChannel); | ||
| 111 | return; | ||
| 112 | } | ||
| 113 | |||
| 114 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 115 | rb.Push(ResultSuccess); | ||
| 116 | rb.PushIpcInterface<IStorage>(std::move(storage)); | ||
| 117 | } | ||
| 118 | |||
| 119 | void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) { | ||
| 120 | LOG_DEBUG(Service_AM, "called"); | ||
| 121 | |||
| 122 | IPC::RequestParser rp{ctx}; | ||
| 123 | applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>().lock()); | ||
| 124 | |||
| 125 | ASSERT(applet->IsInitialized()); | ||
| 126 | applet->ExecuteInteractive(); | ||
| 127 | applet->Execute(); | ||
| 128 | |||
| 129 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 130 | rb.Push(ResultSuccess); | ||
| 131 | } | ||
| 132 | |||
| 133 | void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) { | ||
| 134 | LOG_DEBUG(Service_AM, "called"); | ||
| 135 | |||
| 136 | auto storage = applet->GetBroker().PopInteractiveDataToGame(); | ||
| 137 | if (storage == nullptr) { | ||
| 138 | LOG_DEBUG(Service_AM, | ||
| 139 | "storage is a nullptr. There is no data in the current interactive channel"); | ||
| 140 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 141 | rb.Push(AM::ResultNoDataInChannel); | ||
| 142 | return; | ||
| 143 | } | ||
| 144 | |||
| 145 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 146 | rb.Push(ResultSuccess); | ||
| 147 | rb.PushIpcInterface<IStorage>(std::move(storage)); | ||
| 148 | } | ||
| 149 | |||
| 150 | void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) { | ||
| 151 | LOG_DEBUG(Service_AM, "called"); | ||
| 152 | |||
| 153 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 154 | rb.Push(ResultSuccess); | ||
| 155 | rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent()); | ||
| 156 | } | ||
| 157 | |||
| 158 | void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) { | ||
| 159 | LOG_DEBUG(Service_AM, "called"); | ||
| 160 | |||
| 161 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 162 | rb.Push(ResultSuccess); | ||
| 163 | rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent()); | ||
| 164 | } | ||
| 165 | |||
| 166 | void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) { | ||
| 167 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 168 | |||
| 169 | // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is | ||
| 170 | // actually used anywhere | ||
| 171 | constexpr u64 handle = 0xdeadbeef; | ||
| 172 | |||
| 173 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 174 | rb.Push(ResultSuccess); | ||
| 175 | rb.Push(handle); | ||
| 176 | } | ||
| 177 | |||
| 178 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_accessor.h b/src/core/hle/service/am/library_applet_accessor.h new file mode 100644 index 000000000..698467233 --- /dev/null +++ b/src/core/hle/service/am/library_applet_accessor.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/am/applets/applets.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { | ||
| 12 | public: | ||
| 13 | explicit ILibraryAppletAccessor(Core::System& system_, | ||
| 14 | std::shared_ptr<Applets::Applet> applet_); | ||
| 15 | |||
| 16 | private: | ||
| 17 | void GetAppletStateChangedEvent(HLERequestContext& ctx); | ||
| 18 | void IsCompleted(HLERequestContext& ctx); | ||
| 19 | void GetResult(HLERequestContext& ctx); | ||
| 20 | void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx); | ||
| 21 | void Start(HLERequestContext& ctx); | ||
| 22 | void RequestExit(HLERequestContext& ctx); | ||
| 23 | void PushInData(HLERequestContext& ctx); | ||
| 24 | void PopOutData(HLERequestContext& ctx); | ||
| 25 | void PushInteractiveInData(HLERequestContext& ctx); | ||
| 26 | void PopInteractiveOutData(HLERequestContext& ctx); | ||
| 27 | void GetPopOutDataEvent(HLERequestContext& ctx); | ||
| 28 | void GetPopInteractiveOutDataEvent(HLERequestContext& ctx); | ||
| 29 | void GetIndirectLayerConsumerHandle(HLERequestContext& ctx); | ||
| 30 | |||
| 31 | std::shared_ptr<Applets::Applet> applet; | ||
| 32 | }; | ||
| 33 | |||
| 34 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp new file mode 100644 index 000000000..c33f50a40 --- /dev/null +++ b/src/core/hle/service/am/library_applet_creator.cpp | |||
| @@ -0,0 +1,145 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 5 | #include "core/hle/service/am/applets/applets.h" | ||
| 6 | #include "core/hle/service/am/library_applet_accessor.h" | ||
| 7 | #include "core/hle/service/am/library_applet_creator.h" | ||
| 8 | #include "core/hle/service/am/storage.h" | ||
| 9 | #include "core/hle/service/ipc_helpers.h" | ||
| 10 | |||
| 11 | namespace Service::AM { | ||
| 12 | |||
| 13 | ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) | ||
| 14 | : ServiceFramework{system_, "ILibraryAppletCreator"} { | ||
| 15 | static const FunctionInfo functions[] = { | ||
| 16 | {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, | ||
| 17 | {1, nullptr, "TerminateAllLibraryApplets"}, | ||
| 18 | {2, nullptr, "AreAnyLibraryAppletsLeft"}, | ||
| 19 | {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, | ||
| 20 | {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, | ||
| 21 | {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"}, | ||
| 22 | }; | ||
| 23 | RegisterHandlers(functions); | ||
| 24 | } | ||
| 25 | |||
| 26 | ILibraryAppletCreator::~ILibraryAppletCreator() = default; | ||
| 27 | |||
| 28 | void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) { | ||
| 29 | IPC::RequestParser rp{ctx}; | ||
| 30 | |||
| 31 | const auto applet_id = rp.PopRaw<Applets::AppletId>(); | ||
| 32 | const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>(); | ||
| 33 | |||
| 34 | LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, | ||
| 35 | applet_mode); | ||
| 36 | |||
| 37 | const auto& applet_manager{system.GetAppletManager()}; | ||
| 38 | const auto applet = applet_manager.GetApplet(applet_id, applet_mode); | ||
| 39 | |||
| 40 | if (applet == nullptr) { | ||
| 41 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); | ||
| 42 | |||
| 43 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 44 | rb.Push(ResultUnknown); | ||
| 45 | return; | ||
| 46 | } | ||
| 47 | |||
| 48 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 49 | |||
| 50 | rb.Push(ResultSuccess); | ||
| 51 | rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); | ||
| 52 | } | ||
| 53 | |||
| 54 | void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) { | ||
| 55 | IPC::RequestParser rp{ctx}; | ||
| 56 | |||
| 57 | const s64 size{rp.Pop<s64>()}; | ||
| 58 | |||
| 59 | LOG_DEBUG(Service_AM, "called, size={}", size); | ||
| 60 | |||
| 61 | if (size <= 0) { | ||
| 62 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 63 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 64 | rb.Push(ResultUnknown); | ||
| 65 | return; | ||
| 66 | } | ||
| 67 | |||
| 68 | std::vector<u8> buffer(size); | ||
| 69 | |||
| 70 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 71 | rb.Push(ResultSuccess); | ||
| 72 | rb.PushIpcInterface<IStorage>(system, std::move(buffer)); | ||
| 73 | } | ||
| 74 | |||
| 75 | void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) { | ||
| 76 | IPC::RequestParser rp{ctx}; | ||
| 77 | |||
| 78 | struct Parameters { | ||
| 79 | u8 permissions; | ||
| 80 | s64 size; | ||
| 81 | }; | ||
| 82 | |||
| 83 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 84 | const auto handle{ctx.GetCopyHandle(0)}; | ||
| 85 | |||
| 86 | LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions, | ||
| 87 | parameters.size, handle); | ||
| 88 | |||
| 89 | if (parameters.size <= 0) { | ||
| 90 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 91 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 92 | rb.Push(ResultUnknown); | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | |||
| 96 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); | ||
| 97 | |||
| 98 | if (transfer_mem.IsNull()) { | ||
| 99 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | ||
| 100 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 101 | rb.Push(ResultUnknown); | ||
| 102 | return; | ||
| 103 | } | ||
| 104 | |||
| 105 | std::vector<u8> memory(transfer_mem->GetSize()); | ||
| 106 | ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); | ||
| 107 | |||
| 108 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 109 | rb.Push(ResultSuccess); | ||
| 110 | rb.PushIpcInterface<IStorage>(system, std::move(memory)); | ||
| 111 | } | ||
| 112 | |||
| 113 | void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { | ||
| 114 | IPC::RequestParser rp{ctx}; | ||
| 115 | |||
| 116 | const s64 size{rp.Pop<s64>()}; | ||
| 117 | const auto handle{ctx.GetCopyHandle(0)}; | ||
| 118 | |||
| 119 | LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle); | ||
| 120 | |||
| 121 | if (size <= 0) { | ||
| 122 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 123 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 124 | rb.Push(ResultUnknown); | ||
| 125 | return; | ||
| 126 | } | ||
| 127 | |||
| 128 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); | ||
| 129 | |||
| 130 | if (transfer_mem.IsNull()) { | ||
| 131 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | ||
| 132 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 133 | rb.Push(ResultUnknown); | ||
| 134 | return; | ||
| 135 | } | ||
| 136 | |||
| 137 | std::vector<u8> memory(transfer_mem->GetSize()); | ||
| 138 | ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); | ||
| 139 | |||
| 140 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 141 | rb.Push(ResultSuccess); | ||
| 142 | rb.PushIpcInterface<IStorage>(system, std::move(memory)); | ||
| 143 | } | ||
| 144 | |||
| 145 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_creator.h b/src/core/hle/service/am/library_applet_creator.h new file mode 100644 index 000000000..97f236fbc --- /dev/null +++ b/src/core/hle/service/am/library_applet_creator.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { | ||
| 11 | public: | ||
| 12 | explicit ILibraryAppletCreator(Core::System& system_); | ||
| 13 | ~ILibraryAppletCreator() override; | ||
| 14 | |||
| 15 | private: | ||
| 16 | void CreateLibraryApplet(HLERequestContext& ctx); | ||
| 17 | void CreateStorage(HLERequestContext& ctx); | ||
| 18 | void CreateTransferMemoryStorage(HLERequestContext& ctx); | ||
| 19 | void CreateHandleStorage(HLERequestContext& ctx); | ||
| 20 | }; | ||
| 21 | |||
| 22 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_proxy.cpp b/src/core/hle/service/am/library_applet_proxy.cpp new file mode 100644 index 000000000..047fc40f4 --- /dev/null +++ b/src/core/hle/service/am/library_applet_proxy.cpp | |||
| @@ -0,0 +1,142 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet_common_functions.h" | ||
| 5 | #include "core/hle/service/am/audio_controller.h" | ||
| 6 | #include "core/hle/service/am/common_state_getter.h" | ||
| 7 | #include "core/hle/service/am/debug_functions.h" | ||
| 8 | #include "core/hle/service/am/display_controller.h" | ||
| 9 | #include "core/hle/service/am/global_state_controller.h" | ||
| 10 | #include "core/hle/service/am/home_menu_functions.h" | ||
| 11 | #include "core/hle/service/am/library_applet_creator.h" | ||
| 12 | #include "core/hle/service/am/library_applet_proxy.h" | ||
| 13 | #include "core/hle/service/am/library_applet_self_accessor.h" | ||
| 14 | #include "core/hle/service/am/process_winding_controller.h" | ||
| 15 | #include "core/hle/service/am/self_controller.h" | ||
| 16 | #include "core/hle/service/am/window_controller.h" | ||
| 17 | #include "core/hle/service/ipc_helpers.h" | ||
| 18 | |||
| 19 | namespace Service::AM { | ||
| 20 | |||
| 21 | ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 22 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 23 | Core::System& system_) | ||
| 24 | : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, | ||
| 25 | msg_queue{std::move(msg_queue_)} { | ||
| 26 | // clang-format off | ||
| 27 | static const FunctionInfo functions[] = { | ||
| 28 | {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 29 | {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"}, | ||
| 30 | {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"}, | ||
| 31 | {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"}, | ||
| 32 | {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, | ||
| 33 | {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, | ||
| 34 | {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 35 | {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"}, | ||
| 36 | {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, | ||
| 37 | {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, | ||
| 38 | {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, | ||
| 39 | {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 40 | }; | ||
| 41 | // clang-format on | ||
| 42 | |||
| 43 | RegisterHandlers(functions); | ||
| 44 | } | ||
| 45 | |||
| 46 | void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 47 | LOG_DEBUG(Service_AM, "called"); | ||
| 48 | |||
| 49 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 50 | rb.Push(ResultSuccess); | ||
| 51 | rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); | ||
| 52 | } | ||
| 53 | |||
| 54 | void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) { | ||
| 55 | LOG_DEBUG(Service_AM, "called"); | ||
| 56 | |||
| 57 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 58 | rb.Push(ResultSuccess); | ||
| 59 | rb.PushIpcInterface<ISelfController>(system, nvnflinger); | ||
| 60 | } | ||
| 61 | |||
| 62 | void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) { | ||
| 63 | LOG_DEBUG(Service_AM, "called"); | ||
| 64 | |||
| 65 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 66 | rb.Push(ResultSuccess); | ||
| 67 | rb.PushIpcInterface<IWindowController>(system); | ||
| 68 | } | ||
| 69 | |||
| 70 | void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) { | ||
| 71 | LOG_DEBUG(Service_AM, "called"); | ||
| 72 | |||
| 73 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 74 | rb.Push(ResultSuccess); | ||
| 75 | rb.PushIpcInterface<IAudioController>(system); | ||
| 76 | } | ||
| 77 | |||
| 78 | void ILibraryAppletProxy::GetDisplayController(HLERequestContext& ctx) { | ||
| 79 | LOG_DEBUG(Service_AM, "called"); | ||
| 80 | |||
| 81 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 82 | rb.Push(ResultSuccess); | ||
| 83 | rb.PushIpcInterface<IDisplayController>(system); | ||
| 84 | } | ||
| 85 | |||
| 86 | void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) { | ||
| 87 | LOG_DEBUG(Service_AM, "called"); | ||
| 88 | |||
| 89 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 90 | rb.Push(ResultSuccess); | ||
| 91 | rb.PushIpcInterface<IProcessWindingController>(system); | ||
| 92 | } | ||
| 93 | |||
| 94 | void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 95 | LOG_DEBUG(Service_AM, "called"); | ||
| 96 | |||
| 97 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 98 | rb.Push(ResultSuccess); | ||
| 99 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | ||
| 100 | } | ||
| 101 | |||
| 102 | void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { | ||
| 103 | LOG_DEBUG(Service_AM, "called"); | ||
| 104 | |||
| 105 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 106 | rb.Push(ResultSuccess); | ||
| 107 | rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system); | ||
| 108 | } | ||
| 109 | |||
| 110 | void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { | ||
| 111 | LOG_DEBUG(Service_AM, "called"); | ||
| 112 | |||
| 113 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 114 | rb.Push(ResultSuccess); | ||
| 115 | rb.PushIpcInterface<IAppletCommonFunctions>(system); | ||
| 116 | } | ||
| 117 | |||
| 118 | void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { | ||
| 119 | LOG_DEBUG(Service_AM, "called"); | ||
| 120 | |||
| 121 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 122 | rb.Push(ResultSuccess); | ||
| 123 | rb.PushIpcInterface<IHomeMenuFunctions>(system); | ||
| 124 | } | ||
| 125 | |||
| 126 | void ILibraryAppletProxy::GetGlobalStateController(HLERequestContext& ctx) { | ||
| 127 | LOG_DEBUG(Service_AM, "called"); | ||
| 128 | |||
| 129 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 130 | rb.Push(ResultSuccess); | ||
| 131 | rb.PushIpcInterface<IGlobalStateController>(system); | ||
| 132 | } | ||
| 133 | |||
| 134 | void ILibraryAppletProxy::GetDebugFunctions(HLERequestContext& ctx) { | ||
| 135 | LOG_DEBUG(Service_AM, "called"); | ||
| 136 | |||
| 137 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 138 | rb.Push(ResultSuccess); | ||
| 139 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 140 | } | ||
| 141 | |||
| 142 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_proxy.h b/src/core/hle/service/am/library_applet_proxy.h new file mode 100644 index 000000000..cd9e6d02b --- /dev/null +++ b/src/core/hle/service/am/library_applet_proxy.h | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | ||
| 12 | public: | ||
| 13 | explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 14 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 15 | Core::System& system_); | ||
| 16 | |||
| 17 | private: | ||
| 18 | void GetCommonStateGetter(HLERequestContext& ctx); | ||
| 19 | void GetSelfController(HLERequestContext& ctx); | ||
| 20 | void GetWindowController(HLERequestContext& ctx); | ||
| 21 | void GetAudioController(HLERequestContext& ctx); | ||
| 22 | void GetDisplayController(HLERequestContext& ctx); | ||
| 23 | void GetProcessWindingController(HLERequestContext& ctx); | ||
| 24 | void GetLibraryAppletCreator(HLERequestContext& ctx); | ||
| 25 | void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx); | ||
| 26 | void GetAppletCommonFunctions(HLERequestContext& ctx); | ||
| 27 | void GetHomeMenuFunctions(HLERequestContext& ctx); | ||
| 28 | void GetGlobalStateController(HLERequestContext& ctx); | ||
| 29 | void GetDebugFunctions(HLERequestContext& ctx); | ||
| 30 | |||
| 31 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 32 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 33 | }; | ||
| 34 | |||
| 35 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_self_accessor.cpp b/src/core/hle/service/am/library_applet_self_accessor.cpp new file mode 100644 index 000000000..0a12afbbd --- /dev/null +++ b/src/core/hle/service/am/library_applet_self_accessor.cpp | |||
| @@ -0,0 +1,382 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/acc/profile_manager.h" | ||
| 6 | #include "core/hle/service/am/am_results.h" | ||
| 7 | #include "core/hle/service/am/applets/applet_cabinet.h" | ||
| 8 | #include "core/hle/service/am/applets/applet_controller.h" | ||
| 9 | #include "core/hle/service/am/applets/applet_mii_edit_types.h" | ||
| 10 | #include "core/hle/service/am/applets/applet_software_keyboard_types.h" | ||
| 11 | #include "core/hle/service/am/applets/applets.h" | ||
| 12 | #include "core/hle/service/am/library_applet_self_accessor.h" | ||
| 13 | #include "core/hle/service/am/storage.h" | ||
| 14 | #include "core/hle/service/ipc_helpers.h" | ||
| 15 | #include "hid_core/hid_types.h" | ||
| 16 | |||
| 17 | namespace Service::AM { | ||
| 18 | |||
| 19 | ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) | ||
| 20 | : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} { | ||
| 21 | // clang-format off | ||
| 22 | static const FunctionInfo functions[] = { | ||
| 23 | {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"}, | ||
| 24 | {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"}, | ||
| 25 | {2, nullptr, "PopInteractiveInData"}, | ||
| 26 | {3, nullptr, "PushInteractiveOutData"}, | ||
| 27 | {5, nullptr, "GetPopInDataEvent"}, | ||
| 28 | {6, nullptr, "GetPopInteractiveInDataEvent"}, | ||
| 29 | {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, | ||
| 30 | {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, | ||
| 31 | {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"}, | ||
| 32 | {13, nullptr, "CanUseApplicationCore"}, | ||
| 33 | {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"}, | ||
| 34 | {15, nullptr, "GetMainAppletApplicationControlProperty"}, | ||
| 35 | {16, nullptr, "GetMainAppletStorageId"}, | ||
| 36 | {17, nullptr, "GetCallerAppletIdentityInfoStack"}, | ||
| 37 | {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, | ||
| 38 | {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"}, | ||
| 39 | {20, nullptr, "PopExtraStorage"}, | ||
| 40 | {25, nullptr, "GetPopExtraStorageEvent"}, | ||
| 41 | {30, nullptr, "UnpopInData"}, | ||
| 42 | {31, nullptr, "UnpopExtraStorage"}, | ||
| 43 | {40, nullptr, "GetIndirectLayerProducerHandle"}, | ||
| 44 | {50, nullptr, "ReportVisibleError"}, | ||
| 45 | {51, nullptr, "ReportVisibleErrorWithErrorContext"}, | ||
| 46 | {60, nullptr, "GetMainAppletApplicationDesiredLanguage"}, | ||
| 47 | {70, nullptr, "GetCurrentApplicationId"}, | ||
| 48 | {80, nullptr, "RequestExitToSelf"}, | ||
| 49 | {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, | ||
| 50 | {100, nullptr, "CreateGameMovieTrimmer"}, | ||
| 51 | {101, nullptr, "ReserveResourceForMovieOperation"}, | ||
| 52 | {102, nullptr, "UnreserveResourceForMovieOperation"}, | ||
| 53 | {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"}, | ||
| 54 | {120, nullptr, "GetLaunchStorageInfoForDebug"}, | ||
| 55 | {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, | ||
| 56 | {140, nullptr, "SetApplicationMemoryReservation"}, | ||
| 57 | {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"}, | ||
| 58 | }; | ||
| 59 | // clang-format on | ||
| 60 | RegisterHandlers(functions); | ||
| 61 | |||
| 62 | switch (system.GetAppletManager().GetCurrentAppletId()) { | ||
| 63 | case Applets::AppletId::Cabinet: | ||
| 64 | PushInShowCabinetData(); | ||
| 65 | break; | ||
| 66 | case Applets::AppletId::MiiEdit: | ||
| 67 | PushInShowMiiEditData(); | ||
| 68 | break; | ||
| 69 | case Applets::AppletId::PhotoViewer: | ||
| 70 | PushInShowAlbum(); | ||
| 71 | break; | ||
| 72 | case Applets::AppletId::SoftwareKeyboard: | ||
| 73 | PushInShowSoftwareKeyboard(); | ||
| 74 | break; | ||
| 75 | case Applets::AppletId::Controller: | ||
| 76 | PushInShowController(); | ||
| 77 | break; | ||
| 78 | default: | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; | ||
| 84 | |||
| 85 | void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) { | ||
| 86 | LOG_INFO(Service_AM, "called"); | ||
| 87 | |||
| 88 | if (queue_data.empty()) { | ||
| 89 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 90 | rb.Push(AM::ResultNoDataInChannel); | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | auto data = queue_data.front(); | ||
| 95 | queue_data.pop_front(); | ||
| 96 | |||
| 97 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 98 | rb.Push(ResultSuccess); | ||
| 99 | rb.PushIpcInterface<IStorage>(system, std::move(data)); | ||
| 100 | } | ||
| 101 | |||
| 102 | void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) { | ||
| 103 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 104 | |||
| 105 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 106 | rb.Push(ResultSuccess); | ||
| 107 | } | ||
| 108 | |||
| 109 | void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) { | ||
| 110 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 111 | |||
| 112 | system.Exit(); | ||
| 113 | |||
| 114 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 115 | rb.Push(ResultSuccess); | ||
| 116 | } | ||
| 117 | |||
| 118 | void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) { | ||
| 119 | struct LibraryAppletInfo { | ||
| 120 | Applets::AppletId applet_id; | ||
| 121 | Applets::LibraryAppletMode library_applet_mode; | ||
| 122 | }; | ||
| 123 | |||
| 124 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 125 | |||
| 126 | const LibraryAppletInfo applet_info{ | ||
| 127 | .applet_id = system.GetAppletManager().GetCurrentAppletId(), | ||
| 128 | .library_applet_mode = Applets::LibraryAppletMode::AllForeground, | ||
| 129 | }; | ||
| 130 | |||
| 131 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 132 | rb.Push(ResultSuccess); | ||
| 133 | rb.PushRaw(applet_info); | ||
| 134 | } | ||
| 135 | |||
| 136 | void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) { | ||
| 137 | struct AppletIdentityInfo { | ||
| 138 | Applets::AppletId applet_id; | ||
| 139 | INSERT_PADDING_BYTES(0x4); | ||
| 140 | u64 application_id; | ||
| 141 | }; | ||
| 142 | static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); | ||
| 143 | |||
| 144 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 145 | |||
| 146 | const AppletIdentityInfo applet_info{ | ||
| 147 | .applet_id = Applets::AppletId::QLaunch, | ||
| 148 | .application_id = 0x0100000000001000ull, | ||
| 149 | }; | ||
| 150 | |||
| 151 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 152 | rb.Push(ResultSuccess); | ||
| 153 | rb.PushRaw(applet_info); | ||
| 154 | } | ||
| 155 | |||
| 156 | void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { | ||
| 157 | struct AppletIdentityInfo { | ||
| 158 | Applets::AppletId applet_id; | ||
| 159 | INSERT_PADDING_BYTES(0x4); | ||
| 160 | u64 application_id; | ||
| 161 | }; | ||
| 162 | static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); | ||
| 163 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 164 | |||
| 165 | const AppletIdentityInfo applet_info{ | ||
| 166 | .applet_id = Applets::AppletId::QLaunch, | ||
| 167 | .application_id = 0x0100000000001000ull, | ||
| 168 | }; | ||
| 169 | |||
| 170 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 171 | rb.Push(ResultSuccess); | ||
| 172 | rb.PushRaw(applet_info); | ||
| 173 | } | ||
| 174 | |||
| 175 | void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) { | ||
| 176 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 177 | |||
| 178 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 179 | rb.Push(ResultSuccess); | ||
| 180 | rb.Push<u32>(0); | ||
| 181 | } | ||
| 182 | |||
| 183 | void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) { | ||
| 184 | const Service::Account::ProfileManager manager{}; | ||
| 185 | bool is_empty{true}; | ||
| 186 | s32 user_count{-1}; | ||
| 187 | |||
| 188 | LOG_INFO(Service_AM, "called"); | ||
| 189 | |||
| 190 | if (manager.GetUserCount() > 0) { | ||
| 191 | is_empty = false; | ||
| 192 | user_count = static_cast<s32>(manager.GetUserCount()); | ||
| 193 | ctx.WriteBuffer(manager.GetAllUsers()); | ||
| 194 | } | ||
| 195 | |||
| 196 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 197 | rb.Push(ResultSuccess); | ||
| 198 | rb.Push<u8>(is_empty); | ||
| 199 | rb.Push(user_count); | ||
| 200 | } | ||
| 201 | |||
| 202 | void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) { | ||
| 203 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 204 | |||
| 205 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 206 | rb.Push(ResultSuccess); | ||
| 207 | rb.Push<u8>(0); | ||
| 208 | } | ||
| 209 | |||
| 210 | void ILibraryAppletSelfAccessor::PushInShowAlbum() { | ||
| 211 | const Applets::CommonArguments arguments{ | ||
| 212 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 213 | .size = Applets::CommonArgumentSize::Version3, | ||
| 214 | .library_version = 1, | ||
| 215 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 216 | .play_startup_sound = true, | ||
| 217 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 218 | }; | ||
| 219 | |||
| 220 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 221 | std::vector<u8> settings_data{2}; | ||
| 222 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 223 | queue_data.emplace_back(std::move(argument_data)); | ||
| 224 | queue_data.emplace_back(std::move(settings_data)); | ||
| 225 | } | ||
| 226 | |||
| 227 | void ILibraryAppletSelfAccessor::PushInShowController() { | ||
| 228 | const Applets::CommonArguments common_args = { | ||
| 229 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 230 | .size = Applets::CommonArgumentSize::Version3, | ||
| 231 | .library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8), | ||
| 232 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 233 | .play_startup_sound = true, | ||
| 234 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 235 | }; | ||
| 236 | |||
| 237 | Applets::ControllerSupportArgNew user_args = { | ||
| 238 | .header = {.player_count_min = 1, | ||
| 239 | .player_count_max = 4, | ||
| 240 | .enable_take_over_connection = true, | ||
| 241 | .enable_left_justify = false, | ||
| 242 | .enable_permit_joy_dual = true, | ||
| 243 | .enable_single_mode = false, | ||
| 244 | .enable_identification_color = false}, | ||
| 245 | .identification_colors = {}, | ||
| 246 | .enable_explain_text = false, | ||
| 247 | .explain_text = {}, | ||
| 248 | }; | ||
| 249 | |||
| 250 | Applets::ControllerSupportArgPrivate private_args = { | ||
| 251 | .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate), | ||
| 252 | .arg_size = sizeof(Applets::ControllerSupportArgNew), | ||
| 253 | .is_home_menu = true, | ||
| 254 | .flag_1 = true, | ||
| 255 | .mode = Applets::ControllerSupportMode::ShowControllerSupport, | ||
| 256 | .caller = Applets::ControllerSupportCaller:: | ||
| 257 | Application, // switchbrew: Always zero except with | ||
| 258 | // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem, | ||
| 259 | // which sets this to the input param | ||
| 260 | .style_set = Core::HID::NpadStyleSet::None, | ||
| 261 | .joy_hold_type = 0, | ||
| 262 | }; | ||
| 263 | std::vector<u8> common_args_data(sizeof(common_args)); | ||
| 264 | std::vector<u8> private_args_data(sizeof(private_args)); | ||
| 265 | std::vector<u8> user_args_data(sizeof(user_args)); | ||
| 266 | |||
| 267 | std::memcpy(common_args_data.data(), &common_args, sizeof(common_args)); | ||
| 268 | std::memcpy(private_args_data.data(), &private_args, sizeof(private_args)); | ||
| 269 | std::memcpy(user_args_data.data(), &user_args, sizeof(user_args)); | ||
| 270 | |||
| 271 | queue_data.emplace_back(std::move(common_args_data)); | ||
| 272 | queue_data.emplace_back(std::move(private_args_data)); | ||
| 273 | queue_data.emplace_back(std::move(user_args_data)); | ||
| 274 | } | ||
| 275 | |||
| 276 | void ILibraryAppletSelfAccessor::PushInShowCabinetData() { | ||
| 277 | const Applets::CommonArguments arguments{ | ||
| 278 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 279 | .size = Applets::CommonArgumentSize::Version3, | ||
| 280 | .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1), | ||
| 281 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 282 | .play_startup_sound = true, | ||
| 283 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 284 | }; | ||
| 285 | |||
| 286 | const Applets::StartParamForAmiiboSettings amiibo_settings{ | ||
| 287 | .param_1 = 0, | ||
| 288 | .applet_mode = system.GetAppletManager().GetCabinetMode(), | ||
| 289 | .flags = Applets::CabinetFlags::None, | ||
| 290 | .amiibo_settings_1 = 0, | ||
| 291 | .device_handle = 0, | ||
| 292 | .tag_info{}, | ||
| 293 | .register_info{}, | ||
| 294 | .amiibo_settings_3{}, | ||
| 295 | }; | ||
| 296 | |||
| 297 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 298 | std::vector<u8> settings_data(sizeof(amiibo_settings)); | ||
| 299 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 300 | std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings)); | ||
| 301 | queue_data.emplace_back(std::move(argument_data)); | ||
| 302 | queue_data.emplace_back(std::move(settings_data)); | ||
| 303 | } | ||
| 304 | |||
| 305 | void ILibraryAppletSelfAccessor::PushInShowMiiEditData() { | ||
| 306 | struct MiiEditV3 { | ||
| 307 | Applets::MiiEditAppletInputCommon common; | ||
| 308 | Applets::MiiEditAppletInputV3 input; | ||
| 309 | }; | ||
| 310 | static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size."); | ||
| 311 | |||
| 312 | MiiEditV3 mii_arguments{ | ||
| 313 | .common = | ||
| 314 | { | ||
| 315 | .version = Applets::MiiEditAppletVersion::Version3, | ||
| 316 | .applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit, | ||
| 317 | }, | ||
| 318 | .input{}, | ||
| 319 | }; | ||
| 320 | |||
| 321 | std::vector<u8> argument_data(sizeof(mii_arguments)); | ||
| 322 | std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments)); | ||
| 323 | |||
| 324 | queue_data.emplace_back(std::move(argument_data)); | ||
| 325 | } | ||
| 326 | |||
| 327 | void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() { | ||
| 328 | const Applets::CommonArguments arguments{ | ||
| 329 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 330 | .size = Applets::CommonArgumentSize::Version3, | ||
| 331 | .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301), | ||
| 332 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 333 | .play_startup_sound = true, | ||
| 334 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 335 | }; | ||
| 336 | |||
| 337 | std::vector<char16_t> initial_string(0); | ||
| 338 | |||
| 339 | const Applets::SwkbdConfigCommon swkbd_config{ | ||
| 340 | .type = Applets::SwkbdType::Qwerty, | ||
| 341 | .ok_text{}, | ||
| 342 | .left_optional_symbol_key{}, | ||
| 343 | .right_optional_symbol_key{}, | ||
| 344 | .use_prediction = false, | ||
| 345 | .key_disable_flags{}, | ||
| 346 | .initial_cursor_position = Applets::SwkbdInitialCursorPosition::Start, | ||
| 347 | .header_text{}, | ||
| 348 | .sub_text{}, | ||
| 349 | .guide_text{}, | ||
| 350 | .max_text_length = 500, | ||
| 351 | .min_text_length = 0, | ||
| 352 | .password_mode = Applets::SwkbdPasswordMode::Disabled, | ||
| 353 | .text_draw_type = Applets::SwkbdTextDrawType::Box, | ||
| 354 | .enable_return_button = true, | ||
| 355 | .use_utf8 = false, | ||
| 356 | .use_blur_background = true, | ||
| 357 | .initial_string_offset{}, | ||
| 358 | .initial_string_length = static_cast<u32>(initial_string.size()), | ||
| 359 | .user_dictionary_offset{}, | ||
| 360 | .user_dictionary_entries{}, | ||
| 361 | .use_text_check = false, | ||
| 362 | }; | ||
| 363 | |||
| 364 | Applets::SwkbdConfigNew swkbd_config_new{}; | ||
| 365 | |||
| 366 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 367 | std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new)); | ||
| 368 | std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t)); | ||
| 369 | |||
| 370 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 371 | std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config)); | ||
| 372 | std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new, | ||
| 373 | sizeof(Applets::SwkbdConfigNew)); | ||
| 374 | std::memcpy(work_buffer.data(), initial_string.data(), | ||
| 375 | swkbd_config.initial_string_length * sizeof(char16_t)); | ||
| 376 | |||
| 377 | queue_data.emplace_back(std::move(argument_data)); | ||
| 378 | queue_data.emplace_back(std::move(swkbd_data)); | ||
| 379 | queue_data.emplace_back(std::move(work_buffer)); | ||
| 380 | } | ||
| 381 | |||
| 382 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_self_accessor.h b/src/core/hle/service/am/library_applet_self_accessor.h new file mode 100644 index 000000000..45b325b77 --- /dev/null +++ b/src/core/hle/service/am/library_applet_self_accessor.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <deque> | ||
| 7 | #include <vector> | ||
| 8 | |||
| 9 | #include "core/hle/service/service.h" | ||
| 10 | |||
| 11 | namespace Service::AM { | ||
| 12 | |||
| 13 | class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> { | ||
| 14 | public: | ||
| 15 | explicit ILibraryAppletSelfAccessor(Core::System& system_); | ||
| 16 | ~ILibraryAppletSelfAccessor() override; | ||
| 17 | |||
| 18 | private: | ||
| 19 | void PopInData(HLERequestContext& ctx); | ||
| 20 | void PushOutData(HLERequestContext& ctx); | ||
| 21 | void GetLibraryAppletInfo(HLERequestContext& ctx); | ||
| 22 | void GetMainAppletIdentityInfo(HLERequestContext& ctx); | ||
| 23 | void ExitProcessAndReturn(HLERequestContext& ctx); | ||
| 24 | void GetCallerAppletIdentityInfo(HLERequestContext& ctx); | ||
| 25 | void GetDesirableKeyboardLayout(HLERequestContext& ctx); | ||
| 26 | void GetMainAppletAvailableUsers(HLERequestContext& ctx); | ||
| 27 | void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx); | ||
| 28 | |||
| 29 | void PushInShowAlbum(); | ||
| 30 | void PushInShowCabinetData(); | ||
| 31 | void PushInShowMiiEditData(); | ||
| 32 | void PushInShowSoftwareKeyboard(); | ||
| 33 | void PushInShowController(); | ||
| 34 | |||
| 35 | std::deque<std::vector<u8>> queue_data; | ||
| 36 | }; | ||
| 37 | |||
| 38 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/lock_accessor.cpp b/src/core/hle/service/am/lock_accessor.cpp new file mode 100644 index 000000000..d0bd8d95e --- /dev/null +++ b/src/core/hle/service/am/lock_accessor.cpp | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/lock_accessor.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | ILockAccessor::ILockAccessor(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {1, &ILockAccessor::TryLock, "TryLock"}, | ||
| 14 | {2, &ILockAccessor::Unlock, "Unlock"}, | ||
| 15 | {3, &ILockAccessor::GetEvent, "GetEvent"}, | ||
| 16 | {4,&ILockAccessor::IsLocked, "IsLocked"}, | ||
| 17 | }; | ||
| 18 | // clang-format on | ||
| 19 | |||
| 20 | RegisterHandlers(functions); | ||
| 21 | |||
| 22 | lock_event = service_context.CreateEvent("ILockAccessor::LockEvent"); | ||
| 23 | } | ||
| 24 | |||
| 25 | ILockAccessor::~ILockAccessor() { | ||
| 26 | service_context.CloseEvent(lock_event); | ||
| 27 | }; | ||
| 28 | |||
| 29 | void ILockAccessor::TryLock(HLERequestContext& ctx) { | ||
| 30 | IPC::RequestParser rp{ctx}; | ||
| 31 | const auto return_handle = rp.Pop<bool>(); | ||
| 32 | |||
| 33 | LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle); | ||
| 34 | |||
| 35 | // TODO: When return_handle is true this function should return the lock handle | ||
| 36 | |||
| 37 | is_locked = true; | ||
| 38 | |||
| 39 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 40 | rb.Push(ResultSuccess); | ||
| 41 | rb.Push<u8>(is_locked); | ||
| 42 | } | ||
| 43 | |||
| 44 | void ILockAccessor::Unlock(HLERequestContext& ctx) { | ||
| 45 | LOG_INFO(Service_AM, "called"); | ||
| 46 | |||
| 47 | is_locked = false; | ||
| 48 | |||
| 49 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 50 | rb.Push(ResultSuccess); | ||
| 51 | } | ||
| 52 | |||
| 53 | void ILockAccessor::GetEvent(HLERequestContext& ctx) { | ||
| 54 | LOG_INFO(Service_AM, "called"); | ||
| 55 | |||
| 56 | lock_event->Signal(); | ||
| 57 | |||
| 58 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 59 | rb.Push(ResultSuccess); | ||
| 60 | rb.PushCopyObjects(lock_event->GetReadableEvent()); | ||
| 61 | } | ||
| 62 | |||
| 63 | void ILockAccessor::IsLocked(HLERequestContext& ctx) { | ||
| 64 | LOG_INFO(Service_AM, "called"); | ||
| 65 | |||
| 66 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 67 | rb.Push(ResultSuccess); | ||
| 68 | rb.Push<u8>(is_locked); | ||
| 69 | } | ||
| 70 | |||
| 71 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/lock_accessor.h b/src/core/hle/service/am/lock_accessor.h new file mode 100644 index 000000000..626f60e07 --- /dev/null +++ b/src/core/hle/service/am/lock_accessor.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class ILockAccessor final : public ServiceFramework<ILockAccessor> { | ||
| 12 | public: | ||
| 13 | explicit ILockAccessor(Core::System& system_); | ||
| 14 | ~ILockAccessor() override; | ||
| 15 | |||
| 16 | private: | ||
| 17 | void TryLock(HLERequestContext& ctx); | ||
| 18 | void Unlock(HLERequestContext& ctx); | ||
| 19 | void GetEvent(HLERequestContext& ctx); | ||
| 20 | void IsLocked(HLERequestContext& ctx); | ||
| 21 | |||
| 22 | bool is_locked{}; | ||
| 23 | |||
| 24 | Kernel::KEvent* lock_event; | ||
| 25 | KernelHelpers::ServiceContext service_context; | ||
| 26 | }; | ||
| 27 | |||
| 28 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/process_winding_controller.cpp b/src/core/hle/service/am/process_winding_controller.cpp new file mode 100644 index 000000000..7b3ab157f --- /dev/null +++ b/src/core/hle/service/am/process_winding_controller.cpp | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applets/applets.h" | ||
| 5 | #include "core/hle/service/am/library_applet_accessor.h" | ||
| 6 | #include "core/hle/service/am/process_winding_controller.h" | ||
| 7 | #include "core/hle/service/ipc_helpers.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | IProcessWindingController::IProcessWindingController(Core::System& system_) | ||
| 12 | : ServiceFramework{system_, "IProcessWindingController"} { | ||
| 13 | // clang-format off | ||
| 14 | static const FunctionInfo functions[] = { | ||
| 15 | {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"}, | ||
| 16 | {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"}, | ||
| 17 | {21, nullptr, "PushContext"}, | ||
| 18 | {22, nullptr, "PopContext"}, | ||
| 19 | {23, nullptr, "CancelWindingReservation"}, | ||
| 20 | {30, nullptr, "WindAndDoReserved"}, | ||
| 21 | {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"}, | ||
| 22 | {41, nullptr, "ReserveToStartAndWait"}, | ||
| 23 | }; | ||
| 24 | // clang-format on | ||
| 25 | |||
| 26 | RegisterHandlers(functions); | ||
| 27 | } | ||
| 28 | |||
| 29 | IProcessWindingController::~IProcessWindingController() = default; | ||
| 30 | |||
| 31 | void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) { | ||
| 32 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 33 | |||
| 34 | struct AppletProcessLaunchReason { | ||
| 35 | u8 flag; | ||
| 36 | INSERT_PADDING_BYTES(3); | ||
| 37 | }; | ||
| 38 | static_assert(sizeof(AppletProcessLaunchReason) == 0x4, | ||
| 39 | "AppletProcessLaunchReason is an invalid size"); | ||
| 40 | |||
| 41 | AppletProcessLaunchReason reason{ | ||
| 42 | .flag = 0, | ||
| 43 | }; | ||
| 44 | |||
| 45 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 46 | rb.Push(ResultSuccess); | ||
| 47 | rb.PushRaw(reason); | ||
| 48 | } | ||
| 49 | |||
| 50 | void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { | ||
| 51 | const auto applet_id = system.GetAppletManager().GetCurrentAppletId(); | ||
| 52 | const auto applet_mode = Applets::LibraryAppletMode::AllForeground; | ||
| 53 | |||
| 54 | LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id, | ||
| 55 | applet_mode); | ||
| 56 | |||
| 57 | const auto& applet_manager{system.GetAppletManager()}; | ||
| 58 | const auto applet = applet_manager.GetApplet(applet_id, applet_mode); | ||
| 59 | |||
| 60 | if (applet == nullptr) { | ||
| 61 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); | ||
| 62 | |||
| 63 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 64 | rb.Push(ResultUnknown); | ||
| 65 | return; | ||
| 66 | } | ||
| 67 | |||
| 68 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 69 | rb.Push(ResultSuccess); | ||
| 70 | rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); | ||
| 71 | } | ||
| 72 | |||
| 73 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/process_winding_controller.h b/src/core/hle/service/am/process_winding_controller.h new file mode 100644 index 000000000..9b9704201 --- /dev/null +++ b/src/core/hle/service/am/process_winding_controller.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IProcessWindingController final : public ServiceFramework<IProcessWindingController> { | ||
| 11 | public: | ||
| 12 | explicit IProcessWindingController(Core::System& system_); | ||
| 13 | ~IProcessWindingController() override; | ||
| 14 | |||
| 15 | private: | ||
| 16 | void GetLaunchReason(HLERequestContext& ctx); | ||
| 17 | void OpenCallingLibraryApplet(HLERequestContext& ctx); | ||
| 18 | }; | ||
| 19 | |||
| 20 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp new file mode 100644 index 000000000..0f495c871 --- /dev/null +++ b/src/core/hle/service/am/self_controller.cpp | |||
| @@ -0,0 +1,438 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applets/applets.h" | ||
| 5 | #include "core/hle/service/am/self_controller.h" | ||
| 6 | #include "core/hle/service/caps/caps_su.h" | ||
| 7 | #include "core/hle/service/ipc_helpers.h" | ||
| 8 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 9 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 10 | #include "core/hle/service/sm/sm.h" | ||
| 11 | #include "core/hle/service/vi/vi_results.h" | ||
| 12 | |||
| 13 | namespace Service::AM { | ||
| 14 | |||
| 15 | ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) | ||
| 16 | : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, | ||
| 17 | service_context{system, "ISelfController"} { | ||
| 18 | // clang-format off | ||
| 19 | static const FunctionInfo functions[] = { | ||
| 20 | {0, &ISelfController::Exit, "Exit"}, | ||
| 21 | {1, &ISelfController::LockExit, "LockExit"}, | ||
| 22 | {2, &ISelfController::UnlockExit, "UnlockExit"}, | ||
| 23 | {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, | ||
| 24 | {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"}, | ||
| 25 | {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, | ||
| 26 | {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, | ||
| 27 | {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, | ||
| 28 | {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"}, | ||
| 29 | {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, | ||
| 30 | {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, | ||
| 31 | {15, nullptr, "SetScreenShotAppletIdentityInfo"}, | ||
| 32 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, | ||
| 33 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, | ||
| 34 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, | ||
| 35 | {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"}, | ||
| 36 | {20, nullptr, "SetDesirableKeyboardLayout"}, | ||
| 37 | {21, nullptr, "GetScreenShotProgramId"}, | ||
| 38 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, | ||
| 39 | {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"}, | ||
| 40 | {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"}, | ||
| 41 | {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"}, | ||
| 42 | {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"}, | ||
| 43 | {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, | ||
| 44 | {46, nullptr, "SetRecordingLayerCompositionEnabled"}, | ||
| 45 | {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, | ||
| 46 | {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"}, | ||
| 47 | {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, | ||
| 48 | {61, nullptr, "SetMediaPlaybackState"}, | ||
| 49 | {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, | ||
| 50 | {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"}, | ||
| 51 | {64, nullptr, "SetInputDetectionSourceSet"}, | ||
| 52 | {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"}, | ||
| 53 | {66, nullptr, "GetCurrentIlluminance"}, | ||
| 54 | {67, nullptr, "IsIlluminanceAvailable"}, | ||
| 55 | {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"}, | ||
| 56 | {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"}, | ||
| 57 | {70, nullptr, "ReportMultimediaError"}, | ||
| 58 | {71, nullptr, "GetCurrentIlluminanceEx"}, | ||
| 59 | {72, nullptr, "SetInputDetectionPolicy"}, | ||
| 60 | {80, nullptr, "SetWirelessPriorityMode"}, | ||
| 61 | {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"}, | ||
| 62 | {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, | ||
| 63 | {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, | ||
| 64 | {110, nullptr, "SetApplicationAlbumUserData"}, | ||
| 65 | {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"}, | ||
| 66 | {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"}, | ||
| 67 | {1000, nullptr, "GetDebugStorageChannel"}, | ||
| 68 | }; | ||
| 69 | // clang-format on | ||
| 70 | |||
| 71 | RegisterHandlers(functions); | ||
| 72 | |||
| 73 | launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent"); | ||
| 74 | |||
| 75 | // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is | ||
| 76 | // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple | ||
| 77 | // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not | ||
| 78 | // suspended if the event has previously been created by a call to | ||
| 79 | // GetAccumulatedSuspendedTickChangedEvent. | ||
| 80 | |||
| 81 | accumulated_suspended_tick_changed_event = | ||
| 82 | service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent"); | ||
| 83 | accumulated_suspended_tick_changed_event->Signal(); | ||
| 84 | } | ||
| 85 | |||
| 86 | ISelfController::~ISelfController() { | ||
| 87 | service_context.CloseEvent(launchable_event); | ||
| 88 | service_context.CloseEvent(accumulated_suspended_tick_changed_event); | ||
| 89 | } | ||
| 90 | |||
| 91 | void ISelfController::Exit(HLERequestContext& ctx) { | ||
| 92 | LOG_DEBUG(Service_AM, "called"); | ||
| 93 | |||
| 94 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 95 | rb.Push(ResultSuccess); | ||
| 96 | |||
| 97 | system.Exit(); | ||
| 98 | } | ||
| 99 | |||
| 100 | void ISelfController::LockExit(HLERequestContext& ctx) { | ||
| 101 | LOG_DEBUG(Service_AM, "called"); | ||
| 102 | |||
| 103 | system.SetExitLocked(true); | ||
| 104 | |||
| 105 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 106 | rb.Push(ResultSuccess); | ||
| 107 | } | ||
| 108 | |||
| 109 | void ISelfController::UnlockExit(HLERequestContext& ctx) { | ||
| 110 | LOG_DEBUG(Service_AM, "called"); | ||
| 111 | |||
| 112 | system.SetExitLocked(false); | ||
| 113 | |||
| 114 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 115 | rb.Push(ResultSuccess); | ||
| 116 | |||
| 117 | if (system.GetExitRequested()) { | ||
| 118 | system.Exit(); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | void ISelfController::EnterFatalSection(HLERequestContext& ctx) { | ||
| 123 | ++num_fatal_sections_entered; | ||
| 124 | LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); | ||
| 125 | |||
| 126 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 127 | rb.Push(ResultSuccess); | ||
| 128 | } | ||
| 129 | |||
| 130 | void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { | ||
| 131 | LOG_DEBUG(Service_AM, "called."); | ||
| 132 | |||
| 133 | // Entry and exit of fatal sections must be balanced. | ||
| 134 | if (num_fatal_sections_entered == 0) { | ||
| 135 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 136 | rb.Push(Result{ErrorModule::AM, 512}); | ||
| 137 | return; | ||
| 138 | } | ||
| 139 | |||
| 140 | --num_fatal_sections_entered; | ||
| 141 | |||
| 142 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 143 | rb.Push(ResultSuccess); | ||
| 144 | } | ||
| 145 | |||
| 146 | void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { | ||
| 147 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 148 | |||
| 149 | launchable_event->Signal(); | ||
| 150 | |||
| 151 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 152 | rb.Push(ResultSuccess); | ||
| 153 | rb.PushCopyObjects(launchable_event->GetReadableEvent()); | ||
| 154 | } | ||
| 155 | |||
| 156 | void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { | ||
| 157 | IPC::RequestParser rp{ctx}; | ||
| 158 | const auto permission = rp.PopEnum<ScreenshotPermission>(); | ||
| 159 | LOG_DEBUG(Service_AM, "called, permission={}", permission); | ||
| 160 | |||
| 161 | screenshot_permission = permission; | ||
| 162 | |||
| 163 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 164 | rb.Push(ResultSuccess); | ||
| 165 | } | ||
| 166 | |||
| 167 | void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { | ||
| 168 | IPC::RequestParser rp{ctx}; | ||
| 169 | |||
| 170 | bool flag = rp.Pop<bool>(); | ||
| 171 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); | ||
| 172 | |||
| 173 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 174 | rb.Push(ResultSuccess); | ||
| 175 | } | ||
| 176 | |||
| 177 | void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { | ||
| 178 | IPC::RequestParser rp{ctx}; | ||
| 179 | |||
| 180 | bool flag = rp.Pop<bool>(); | ||
| 181 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); | ||
| 182 | |||
| 183 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 184 | rb.Push(ResultSuccess); | ||
| 185 | } | ||
| 186 | |||
| 187 | void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { | ||
| 188 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 189 | // u8, these are bool flags. No output. | ||
| 190 | IPC::RequestParser rp{ctx}; | ||
| 191 | |||
| 192 | struct FocusHandlingModeParams { | ||
| 193 | u8 unknown0; | ||
| 194 | u8 unknown1; | ||
| 195 | u8 unknown2; | ||
| 196 | }; | ||
| 197 | const auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||
| 198 | |||
| 199 | LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}", | ||
| 200 | flags.unknown0, flags.unknown1, flags.unknown2); | ||
| 201 | |||
| 202 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 203 | rb.Push(ResultSuccess); | ||
| 204 | } | ||
| 205 | |||
| 206 | void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { | ||
| 207 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 208 | |||
| 209 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 210 | rb.Push(ResultSuccess); | ||
| 211 | } | ||
| 212 | |||
| 213 | void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { | ||
| 214 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 215 | // u8, these are bool flags. No output. | ||
| 216 | IPC::RequestParser rp{ctx}; | ||
| 217 | |||
| 218 | bool enabled = rp.Pop<bool>(); | ||
| 219 | LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); | ||
| 220 | |||
| 221 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 222 | rb.Push(ResultSuccess); | ||
| 223 | } | ||
| 224 | |||
| 225 | void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { | ||
| 226 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 227 | |||
| 228 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 229 | rb.Push(ResultSuccess); | ||
| 230 | } | ||
| 231 | |||
| 232 | void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { | ||
| 233 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 234 | |||
| 235 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 236 | // create the layer in the Default display. | ||
| 237 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 238 | const auto layer_id = nvnflinger.CreateLayer(*display_id); | ||
| 239 | |||
| 240 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 241 | rb.Push(ResultSuccess); | ||
| 242 | rb.Push(*layer_id); | ||
| 243 | } | ||
| 244 | |||
| 245 | void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { | ||
| 246 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 247 | |||
| 248 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 249 | rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); | ||
| 250 | } | ||
| 251 | |||
| 252 | void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { | ||
| 253 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 254 | |||
| 255 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 256 | rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); | ||
| 257 | rb.Push<s64>(system_shared_buffer_id); | ||
| 258 | rb.Push<s64>(system_shared_layer_id); | ||
| 259 | } | ||
| 260 | |||
| 261 | void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { | ||
| 262 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 263 | |||
| 264 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 265 | rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); | ||
| 266 | rb.Push<s64>(system_shared_buffer_id); | ||
| 267 | } | ||
| 268 | |||
| 269 | Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { | ||
| 270 | if (buffer_sharing_enabled) { | ||
| 271 | return ResultSuccess; | ||
| 272 | } | ||
| 273 | |||
| 274 | if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) { | ||
| 275 | return VI::ResultOperationFailed; | ||
| 276 | } | ||
| 277 | |||
| 278 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 279 | const auto result = nvnflinger.GetSystemBufferManager().Initialize( | ||
| 280 | &system_shared_buffer_id, &system_shared_layer_id, *display_id); | ||
| 281 | |||
| 282 | if (result.IsSuccess()) { | ||
| 283 | buffer_sharing_enabled = true; | ||
| 284 | } | ||
| 285 | |||
| 286 | return result; | ||
| 287 | } | ||
| 288 | |||
| 289 | void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { | ||
| 290 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 291 | |||
| 292 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 293 | // create the layer in the Default display. | ||
| 294 | // This calls nn::vi::CreateRecordingLayer() which creates another layer. | ||
| 295 | // Currently we do not support more than 1 layer per display, output 1 layer id for now. | ||
| 296 | // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse | ||
| 297 | // side effects. | ||
| 298 | // TODO: Support multiple layers | ||
| 299 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 300 | const auto layer_id = nvnflinger.CreateLayer(*display_id); | ||
| 301 | |||
| 302 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 303 | rb.Push(ResultSuccess); | ||
| 304 | rb.Push(*layer_id); | ||
| 305 | } | ||
| 306 | |||
| 307 | void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { | ||
| 308 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 309 | |||
| 310 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 311 | rb.Push(ResultSuccess); | ||
| 312 | } | ||
| 313 | |||
| 314 | void ISelfController::ApproveToDisplay(HLERequestContext& ctx) { | ||
| 315 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 316 | |||
| 317 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 318 | rb.Push(ResultSuccess); | ||
| 319 | } | ||
| 320 | |||
| 321 | void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { | ||
| 322 | IPC::RequestParser rp{ctx}; | ||
| 323 | idle_time_detection_extension = rp.Pop<u32>(); | ||
| 324 | LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}", | ||
| 325 | idle_time_detection_extension); | ||
| 326 | |||
| 327 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 328 | rb.Push(ResultSuccess); | ||
| 329 | } | ||
| 330 | |||
| 331 | void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { | ||
| 332 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 333 | |||
| 334 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 335 | rb.Push(ResultSuccess); | ||
| 336 | rb.Push<u32>(idle_time_detection_extension); | ||
| 337 | } | ||
| 338 | |||
| 339 | void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { | ||
| 340 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 341 | |||
| 342 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 343 | rb.Push(ResultSuccess); | ||
| 344 | } | ||
| 345 | |||
| 346 | void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { | ||
| 347 | IPC::RequestParser rp{ctx}; | ||
| 348 | is_auto_sleep_disabled = rp.Pop<bool>(); | ||
| 349 | |||
| 350 | // On the system itself, if the previous state of is_auto_sleep_disabled | ||
| 351 | // differed from the current value passed in, it'd signify the internal | ||
| 352 | // window manager to update (and also increment some statistics like update counts) | ||
| 353 | // | ||
| 354 | // It'd also indicate this change to an idle handling context. | ||
| 355 | // | ||
| 356 | // However, given we're emulating this behavior, most of this can be ignored | ||
| 357 | // and it's sufficient to simply set the member variable for querying via | ||
| 358 | // IsAutoSleepDisabled(). | ||
| 359 | |||
| 360 | LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled); | ||
| 361 | |||
| 362 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 363 | rb.Push(ResultSuccess); | ||
| 364 | } | ||
| 365 | |||
| 366 | void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { | ||
| 367 | LOG_DEBUG(Service_AM, "called."); | ||
| 368 | |||
| 369 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 370 | rb.Push(ResultSuccess); | ||
| 371 | rb.Push(is_auto_sleep_disabled); | ||
| 372 | } | ||
| 373 | |||
| 374 | void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { | ||
| 375 | LOG_DEBUG(Service_AM, "called."); | ||
| 376 | |||
| 377 | // This command returns the total number of system ticks since ISelfController creation | ||
| 378 | // where the game was suspended. Since Yuzu doesn't implement game suspension, this command | ||
| 379 | // can just always return 0 ticks. | ||
| 380 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 381 | rb.Push(ResultSuccess); | ||
| 382 | rb.Push<u64>(0); | ||
| 383 | } | ||
| 384 | |||
| 385 | void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { | ||
| 386 | LOG_DEBUG(Service_AM, "called."); | ||
| 387 | |||
| 388 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 389 | rb.Push(ResultSuccess); | ||
| 390 | rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); | ||
| 391 | } | ||
| 392 | |||
| 393 | void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { | ||
| 394 | IPC::RequestParser rp{ctx}; | ||
| 395 | |||
| 396 | // This service call sets an internal flag whether a notification is shown when an image is | ||
| 397 | // captured. Currently we do not support capturing images via the capture button, so this can be | ||
| 398 | // stubbed for now. | ||
| 399 | const bool album_image_taken_notification_enabled = rp.Pop<bool>(); | ||
| 400 | |||
| 401 | LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}", | ||
| 402 | album_image_taken_notification_enabled); | ||
| 403 | |||
| 404 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 405 | rb.Push(ResultSuccess); | ||
| 406 | } | ||
| 407 | |||
| 408 | void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { | ||
| 409 | IPC::RequestParser rp{ctx}; | ||
| 410 | |||
| 411 | const auto report_option = rp.PopEnum<Capture::AlbumReportOption>(); | ||
| 412 | |||
| 413 | LOG_INFO(Service_AM, "called, report_option={}", report_option); | ||
| 414 | |||
| 415 | const auto screenshot_service = | ||
| 416 | system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>( | ||
| 417 | "caps:su"); | ||
| 418 | |||
| 419 | if (screenshot_service) { | ||
| 420 | screenshot_service->CaptureAndSaveScreenshot(report_option); | ||
| 421 | } | ||
| 422 | |||
| 423 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 424 | rb.Push(ResultSuccess); | ||
| 425 | } | ||
| 426 | |||
| 427 | void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { | ||
| 428 | IPC::RequestParser rp{ctx}; | ||
| 429 | |||
| 430 | const auto is_record_volume_muted = rp.Pop<bool>(); | ||
| 431 | |||
| 432 | LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted); | ||
| 433 | |||
| 434 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 435 | rb.Push(ResultSuccess); | ||
| 436 | } | ||
| 437 | |||
| 438 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h new file mode 100644 index 000000000..f157bb826 --- /dev/null +++ b/src/core/hle/service/am/self_controller.h | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class ISelfController final : public ServiceFramework<ISelfController> { | ||
| 12 | public: | ||
| 13 | explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); | ||
| 14 | ~ISelfController() override; | ||
| 15 | |||
| 16 | private: | ||
| 17 | void Exit(HLERequestContext& ctx); | ||
| 18 | void LockExit(HLERequestContext& ctx); | ||
| 19 | void UnlockExit(HLERequestContext& ctx); | ||
| 20 | void EnterFatalSection(HLERequestContext& ctx); | ||
| 21 | void LeaveFatalSection(HLERequestContext& ctx); | ||
| 22 | void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx); | ||
| 23 | void SetScreenShotPermission(HLERequestContext& ctx); | ||
| 24 | void SetOperationModeChangedNotification(HLERequestContext& ctx); | ||
| 25 | void SetPerformanceModeChangedNotification(HLERequestContext& ctx); | ||
| 26 | void SetFocusHandlingMode(HLERequestContext& ctx); | ||
| 27 | void SetRestartMessageEnabled(HLERequestContext& ctx); | ||
| 28 | void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); | ||
| 29 | void SetAlbumImageOrientation(HLERequestContext& ctx); | ||
| 30 | void IsSystemBufferSharingEnabled(HLERequestContext& ctx); | ||
| 31 | void GetSystemSharedBufferHandle(HLERequestContext& ctx); | ||
| 32 | void GetSystemSharedLayerHandle(HLERequestContext& ctx); | ||
| 33 | void CreateManagedDisplayLayer(HLERequestContext& ctx); | ||
| 34 | void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); | ||
| 35 | void SetHandlesRequestToDisplay(HLERequestContext& ctx); | ||
| 36 | void ApproveToDisplay(HLERequestContext& ctx); | ||
| 37 | void SetIdleTimeDetectionExtension(HLERequestContext& ctx); | ||
| 38 | void GetIdleTimeDetectionExtension(HLERequestContext& ctx); | ||
| 39 | void ReportUserIsActive(HLERequestContext& ctx); | ||
| 40 | void SetAutoSleepDisabled(HLERequestContext& ctx); | ||
| 41 | void IsAutoSleepDisabled(HLERequestContext& ctx); | ||
| 42 | void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx); | ||
| 43 | void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx); | ||
| 44 | void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx); | ||
| 45 | void SaveCurrentScreenshot(HLERequestContext& ctx); | ||
| 46 | void SetRecordVolumeMuted(HLERequestContext& ctx); | ||
| 47 | |||
| 48 | Result EnsureBufferSharingEnabled(Kernel::KProcess* process); | ||
| 49 | |||
| 50 | enum class ScreenshotPermission : u32 { | ||
| 51 | Inherit = 0, | ||
| 52 | Enable = 1, | ||
| 53 | Disable = 2, | ||
| 54 | }; | ||
| 55 | |||
| 56 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 57 | |||
| 58 | KernelHelpers::ServiceContext service_context; | ||
| 59 | |||
| 60 | Kernel::KEvent* launchable_event; | ||
| 61 | Kernel::KEvent* accumulated_suspended_tick_changed_event; | ||
| 62 | |||
| 63 | u32 idle_time_detection_extension = 0; | ||
| 64 | u64 num_fatal_sections_entered = 0; | ||
| 65 | u64 system_shared_buffer_id = 0; | ||
| 66 | u64 system_shared_layer_id = 0; | ||
| 67 | bool is_auto_sleep_disabled = false; | ||
| 68 | bool buffer_sharing_enabled = false; | ||
| 69 | ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit; | ||
| 70 | }; | ||
| 71 | |||
| 72 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/storage.cpp b/src/core/hle/service/am/storage.cpp new file mode 100644 index 000000000..9a86c867a --- /dev/null +++ b/src/core/hle/service/am/storage.cpp | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/storage.h" | ||
| 5 | #include "core/hle/service/am/storage_accessor.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | IStorageImpl::~IStorageImpl() = default; | ||
| 11 | |||
| 12 | class StorageDataImpl final : public IStorageImpl { | ||
| 13 | public: | ||
| 14 | explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {} | ||
| 15 | |||
| 16 | std::vector<u8>& GetData() override { | ||
| 17 | return buffer; | ||
| 18 | } | ||
| 19 | |||
| 20 | const std::vector<u8>& GetData() const override { | ||
| 21 | return buffer; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::size_t GetSize() const override { | ||
| 25 | return buffer.size(); | ||
| 26 | } | ||
| 27 | |||
| 28 | private: | ||
| 29 | std::vector<u8> buffer; | ||
| 30 | }; | ||
| 31 | |||
| 32 | IStorage::IStorage(Core::System& system_, std::vector<u8>&& buffer) | ||
| 33 | : ServiceFramework{system_, "IStorage"}, | ||
| 34 | impl{std::make_shared<StorageDataImpl>(std::move(buffer))} { | ||
| 35 | Register(); | ||
| 36 | } | ||
| 37 | |||
| 38 | void IStorage::Register() { | ||
| 39 | // clang-format off | ||
| 40 | static const FunctionInfo functions[] = { | ||
| 41 | {0, &IStorage::Open, "Open"}, | ||
| 42 | {1, nullptr, "OpenTransferStorage"}, | ||
| 43 | }; | ||
| 44 | // clang-format on | ||
| 45 | |||
| 46 | RegisterHandlers(functions); | ||
| 47 | } | ||
| 48 | |||
| 49 | IStorage::~IStorage() = default; | ||
| 50 | |||
| 51 | void IStorage::Open(HLERequestContext& ctx) { | ||
| 52 | LOG_DEBUG(Service_AM, "called"); | ||
| 53 | |||
| 54 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 55 | |||
| 56 | rb.Push(ResultSuccess); | ||
| 57 | rb.PushIpcInterface<IStorageAccessor>(system, *this); | ||
| 58 | } | ||
| 59 | |||
| 60 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/storage.h b/src/core/hle/service/am/storage.h new file mode 100644 index 000000000..d47a8d89f --- /dev/null +++ b/src/core/hle/service/am/storage.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IStorageImpl { | ||
| 11 | public: | ||
| 12 | virtual ~IStorageImpl(); | ||
| 13 | virtual std::vector<u8>& GetData() = 0; | ||
| 14 | virtual const std::vector<u8>& GetData() const = 0; | ||
| 15 | virtual std::size_t GetSize() const = 0; | ||
| 16 | }; | ||
| 17 | |||
| 18 | class IStorage final : public ServiceFramework<IStorage> { | ||
| 19 | public: | ||
| 20 | explicit IStorage(Core::System& system_, std::vector<u8>&& buffer); | ||
| 21 | ~IStorage() override; | ||
| 22 | |||
| 23 | std::vector<u8>& GetData() { | ||
| 24 | return impl->GetData(); | ||
| 25 | } | ||
| 26 | |||
| 27 | const std::vector<u8>& GetData() const { | ||
| 28 | return impl->GetData(); | ||
| 29 | } | ||
| 30 | |||
| 31 | std::size_t GetSize() const { | ||
| 32 | return impl->GetSize(); | ||
| 33 | } | ||
| 34 | |||
| 35 | private: | ||
| 36 | void Register(); | ||
| 37 | void Open(HLERequestContext& ctx); | ||
| 38 | |||
| 39 | std::shared_ptr<IStorageImpl> impl; | ||
| 40 | }; | ||
| 41 | |||
| 42 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/storage_accessor.cpp b/src/core/hle/service/am/storage_accessor.cpp new file mode 100644 index 000000000..7d8c82de3 --- /dev/null +++ b/src/core/hle/service/am/storage_accessor.cpp | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/am_results.h" | ||
| 5 | #include "core/hle/service/am/storage_accessor.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_) | ||
| 11 | : ServiceFramework{system_, "IStorageAccessor"}, backing{backing_} { | ||
| 12 | // clang-format off | ||
| 13 | static const FunctionInfo functions[] = { | ||
| 14 | {0, &IStorageAccessor::GetSize, "GetSize"}, | ||
| 15 | {10, &IStorageAccessor::Write, "Write"}, | ||
| 16 | {11, &IStorageAccessor::Read, "Read"}, | ||
| 17 | }; | ||
| 18 | // clang-format on | ||
| 19 | |||
| 20 | RegisterHandlers(functions); | ||
| 21 | } | ||
| 22 | |||
| 23 | IStorageAccessor::~IStorageAccessor() = default; | ||
| 24 | |||
| 25 | void IStorageAccessor::GetSize(HLERequestContext& ctx) { | ||
| 26 | LOG_DEBUG(Service_AM, "called"); | ||
| 27 | |||
| 28 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 29 | |||
| 30 | rb.Push(ResultSuccess); | ||
| 31 | rb.Push(static_cast<u64>(backing.GetSize())); | ||
| 32 | } | ||
| 33 | |||
| 34 | void IStorageAccessor::Write(HLERequestContext& ctx) { | ||
| 35 | IPC::RequestParser rp{ctx}; | ||
| 36 | |||
| 37 | const u64 offset{rp.Pop<u64>()}; | ||
| 38 | const auto data{ctx.ReadBuffer()}; | ||
| 39 | const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)}; | ||
| 40 | |||
| 41 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); | ||
| 42 | |||
| 43 | if (offset > backing.GetSize()) { | ||
| 44 | LOG_ERROR(Service_AM, | ||
| 45 | "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}", | ||
| 46 | backing.GetSize(), size, offset); | ||
| 47 | |||
| 48 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 49 | rb.Push(AM::ResultInvalidOffset); | ||
| 50 | return; | ||
| 51 | } | ||
| 52 | |||
| 53 | std::memcpy(backing.GetData().data() + offset, data.data(), size); | ||
| 54 | |||
| 55 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 56 | rb.Push(ResultSuccess); | ||
| 57 | } | ||
| 58 | |||
| 59 | void IStorageAccessor::Read(HLERequestContext& ctx) { | ||
| 60 | IPC::RequestParser rp{ctx}; | ||
| 61 | |||
| 62 | const u64 offset{rp.Pop<u64>()}; | ||
| 63 | const std::size_t size{std::min<u64>(ctx.GetWriteBufferSize(), backing.GetSize() - offset)}; | ||
| 64 | |||
| 65 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); | ||
| 66 | |||
| 67 | if (offset > backing.GetSize()) { | ||
| 68 | LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}", | ||
| 69 | backing.GetSize(), size, offset); | ||
| 70 | |||
| 71 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 72 | rb.Push(AM::ResultInvalidOffset); | ||
| 73 | return; | ||
| 74 | } | ||
| 75 | |||
| 76 | ctx.WriteBuffer(backing.GetData().data() + offset, size); | ||
| 77 | |||
| 78 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 79 | rb.Push(ResultSuccess); | ||
| 80 | } | ||
| 81 | |||
| 82 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/storage_accessor.h b/src/core/hle/service/am/storage_accessor.h new file mode 100644 index 000000000..8648bfc13 --- /dev/null +++ b/src/core/hle/service/am/storage_accessor.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/am/storage.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { | ||
| 12 | public: | ||
| 13 | explicit IStorageAccessor(Core::System& system_, IStorage& backing_); | ||
| 14 | ~IStorageAccessor() override; | ||
| 15 | |||
| 16 | private: | ||
| 17 | void GetSize(HLERequestContext& ctx); | ||
| 18 | void Write(HLERequestContext& ctx); | ||
| 19 | void Read(HLERequestContext& ctx); | ||
| 20 | |||
| 21 | IStorage& backing; | ||
| 22 | }; | ||
| 23 | |||
| 24 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/system_applet_proxy.cpp b/src/core/hle/service/am/system_applet_proxy.cpp new file mode 100644 index 000000000..d51a2c8db --- /dev/null +++ b/src/core/hle/service/am/system_applet_proxy.cpp | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet_common_functions.h" | ||
| 5 | #include "core/hle/service/am/application_creator.h" | ||
| 6 | #include "core/hle/service/am/audio_controller.h" | ||
| 7 | #include "core/hle/service/am/common_state_getter.h" | ||
| 8 | #include "core/hle/service/am/debug_functions.h" | ||
| 9 | #include "core/hle/service/am/display_controller.h" | ||
| 10 | #include "core/hle/service/am/global_state_controller.h" | ||
| 11 | #include "core/hle/service/am/home_menu_functions.h" | ||
| 12 | #include "core/hle/service/am/library_applet_creator.h" | ||
| 13 | #include "core/hle/service/am/library_applet_self_accessor.h" | ||
| 14 | #include "core/hle/service/am/process_winding_controller.h" | ||
| 15 | #include "core/hle/service/am/self_controller.h" | ||
| 16 | #include "core/hle/service/am/system_applet_proxy.h" | ||
| 17 | #include "core/hle/service/am/window_controller.h" | ||
| 18 | #include "core/hle/service/ipc_helpers.h" | ||
| 19 | |||
| 20 | namespace Service::AM { | ||
| 21 | |||
| 22 | ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 23 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 24 | Core::System& system_) | ||
| 25 | : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_}, | ||
| 26 | msg_queue{std::move(msg_queue_)} { | ||
| 27 | // clang-format off | ||
| 28 | static const FunctionInfo functions[] = { | ||
| 29 | {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 30 | {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"}, | ||
| 31 | {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"}, | ||
| 32 | {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"}, | ||
| 33 | {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"}, | ||
| 34 | {10, nullptr, "GetProcessWindingController"}, | ||
| 35 | {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 36 | {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, | ||
| 37 | {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, | ||
| 38 | {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"}, | ||
| 39 | {23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, | ||
| 40 | {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 41 | }; | ||
| 42 | // clang-format on | ||
| 43 | |||
| 44 | RegisterHandlers(functions); | ||
| 45 | } | ||
| 46 | |||
| 47 | void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 48 | LOG_DEBUG(Service_AM, "called"); | ||
| 49 | |||
| 50 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 51 | rb.Push(ResultSuccess); | ||
| 52 | rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); | ||
| 53 | } | ||
| 54 | |||
| 55 | void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) { | ||
| 56 | LOG_DEBUG(Service_AM, "called"); | ||
| 57 | |||
| 58 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 59 | rb.Push(ResultSuccess); | ||
| 60 | rb.PushIpcInterface<ISelfController>(system, nvnflinger); | ||
| 61 | } | ||
| 62 | |||
| 63 | void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) { | ||
| 64 | LOG_DEBUG(Service_AM, "called"); | ||
| 65 | |||
| 66 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 67 | rb.Push(ResultSuccess); | ||
| 68 | rb.PushIpcInterface<IWindowController>(system); | ||
| 69 | } | ||
| 70 | |||
| 71 | void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) { | ||
| 72 | LOG_DEBUG(Service_AM, "called"); | ||
| 73 | |||
| 74 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 75 | rb.Push(ResultSuccess); | ||
| 76 | rb.PushIpcInterface<IAudioController>(system); | ||
| 77 | } | ||
| 78 | |||
| 79 | void ISystemAppletProxy::GetDisplayController(HLERequestContext& ctx) { | ||
| 80 | LOG_DEBUG(Service_AM, "called"); | ||
| 81 | |||
| 82 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 83 | rb.Push(ResultSuccess); | ||
| 84 | rb.PushIpcInterface<IDisplayController>(system); | ||
| 85 | } | ||
| 86 | |||
| 87 | void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 88 | LOG_DEBUG(Service_AM, "called"); | ||
| 89 | |||
| 90 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 91 | rb.Push(ResultSuccess); | ||
| 92 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | ||
| 93 | } | ||
| 94 | |||
| 95 | void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { | ||
| 96 | LOG_DEBUG(Service_AM, "called"); | ||
| 97 | |||
| 98 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 99 | rb.Push(ResultSuccess); | ||
| 100 | rb.PushIpcInterface<IHomeMenuFunctions>(system); | ||
| 101 | } | ||
| 102 | |||
| 103 | void ISystemAppletProxy::GetGlobalStateController(HLERequestContext& ctx) { | ||
| 104 | LOG_DEBUG(Service_AM, "called"); | ||
| 105 | |||
| 106 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 107 | rb.Push(ResultSuccess); | ||
| 108 | rb.PushIpcInterface<IGlobalStateController>(system); | ||
| 109 | } | ||
| 110 | |||
| 111 | void ISystemAppletProxy::GetApplicationCreator(HLERequestContext& ctx) { | ||
| 112 | LOG_DEBUG(Service_AM, "called"); | ||
| 113 | |||
| 114 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 115 | rb.Push(ResultSuccess); | ||
| 116 | rb.PushIpcInterface<IApplicationCreator>(system); | ||
| 117 | } | ||
| 118 | |||
| 119 | void ISystemAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { | ||
| 120 | LOG_DEBUG(Service_AM, "called"); | ||
| 121 | |||
| 122 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 123 | rb.Push(ResultSuccess); | ||
| 124 | rb.PushIpcInterface<IAppletCommonFunctions>(system); | ||
| 125 | } | ||
| 126 | |||
| 127 | void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) { | ||
| 128 | LOG_DEBUG(Service_AM, "called"); | ||
| 129 | |||
| 130 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 131 | rb.Push(ResultSuccess); | ||
| 132 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 133 | } | ||
| 134 | |||
| 135 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/system_applet_proxy.h b/src/core/hle/service/am/system_applet_proxy.h new file mode 100644 index 000000000..b8855b1d6 --- /dev/null +++ b/src/core/hle/service/am/system_applet_proxy.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { | ||
| 12 | public: | ||
| 13 | explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 14 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 15 | Core::System& system_); | ||
| 16 | |||
| 17 | private: | ||
| 18 | void GetCommonStateGetter(HLERequestContext& ctx); | ||
| 19 | void GetSelfController(HLERequestContext& ctx); | ||
| 20 | void GetWindowController(HLERequestContext& ctx); | ||
| 21 | void GetAudioController(HLERequestContext& ctx); | ||
| 22 | void GetDisplayController(HLERequestContext& ctx); | ||
| 23 | void GetLibraryAppletCreator(HLERequestContext& ctx); | ||
| 24 | void GetHomeMenuFunctions(HLERequestContext& ctx); | ||
| 25 | void GetGlobalStateController(HLERequestContext& ctx); | ||
| 26 | void GetApplicationCreator(HLERequestContext& ctx); | ||
| 27 | void GetAppletCommonFunctions(HLERequestContext& ctx); | ||
| 28 | void GetDebugFunctions(HLERequestContext& ctx); | ||
| 29 | |||
| 30 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 31 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 32 | }; | ||
| 33 | |||
| 34 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp new file mode 100644 index 000000000..f2ba3c134 --- /dev/null +++ b/src/core/hle/service/am/window_controller.cpp | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/window_controller.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IWindowController::IWindowController(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IWindowController"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, nullptr, "CreateWindow"}, | ||
| 14 | {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, | ||
| 15 | {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"}, | ||
| 16 | {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, | ||
| 17 | {11, nullptr, "ReleaseForegroundRights"}, | ||
| 18 | {12, nullptr, "RejectToChangeIntoBackground"}, | ||
| 19 | {20, nullptr, "SetAppletWindowVisibility"}, | ||
| 20 | {21, nullptr, "SetAppletGpuTimeSlice"}, | ||
| 21 | }; | ||
| 22 | // clang-format on | ||
| 23 | |||
| 24 | RegisterHandlers(functions); | ||
| 25 | } | ||
| 26 | |||
| 27 | IWindowController::~IWindowController() = default; | ||
| 28 | |||
| 29 | void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) { | ||
| 30 | const u64 process_id = system.ApplicationProcess()->GetProcessId(); | ||
| 31 | |||
| 32 | LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id); | ||
| 33 | |||
| 34 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 35 | rb.Push(ResultSuccess); | ||
| 36 | rb.Push<u64>(process_id); | ||
| 37 | } | ||
| 38 | |||
| 39 | void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) { | ||
| 40 | const u64 process_id = 0; | ||
| 41 | |||
| 42 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 43 | |||
| 44 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 45 | rb.Push(ResultSuccess); | ||
| 46 | rb.Push<u64>(process_id); | ||
| 47 | } | ||
| 48 | |||
| 49 | void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { | ||
| 50 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 51 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 52 | rb.Push(ResultSuccess); | ||
| 53 | } | ||
| 54 | |||
| 55 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/window_controller.h b/src/core/hle/service/am/window_controller.h new file mode 100644 index 000000000..07b0e0e17 --- /dev/null +++ b/src/core/hle/service/am/window_controller.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IWindowController final : public ServiceFramework<IWindowController> { | ||
| 11 | public: | ||
| 12 | explicit IWindowController(Core::System& system_); | ||
| 13 | ~IWindowController() override; | ||
| 14 | |||
| 15 | private: | ||
| 16 | void GetAppletResourceUserId(HLERequestContext& ctx); | ||
| 17 | void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx); | ||
| 18 | void AcquireForegroundRights(HLERequestContext& ctx); | ||
| 19 | }; | ||
| 20 | |||
| 21 | } // namespace Service::AM | ||
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 49ec52546..718534ba1 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/hle/service/am/am.h" | 10 | #include "core/hle/service/am/am.h" |
| 11 | #include "core/hle/service/am/applet_ae.h" | 11 | #include "core/hle/service/am/applet_ae.h" |
| 12 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 12 | #include "core/hle/service/am/applet_oe.h" | 13 | #include "core/hle/service/am/applet_oe.h" |
| 13 | #include "core/hle/service/sm/sm.h" | 14 | #include "core/hle/service/sm/sm.h" |
| 14 | #include "hid_core/frontend/emulated_controller.h" | 15 | #include "hid_core/frontend/emulated_controller.h" |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 782bcbb61..f51fd3fa3 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include "core/frontend/applets/software_keyboard.h" | 44 | #include "core/frontend/applets/software_keyboard.h" |
| 45 | #include "core/hle/service/acc/profile_manager.h" | 45 | #include "core/hle/service/acc/profile_manager.h" |
| 46 | #include "core/hle/service/am/applet_ae.h" | 46 | #include "core/hle/service/am/applet_ae.h" |
| 47 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 47 | #include "core/hle/service/am/applet_oe.h" | 48 | #include "core/hle/service/am/applet_oe.h" |
| 48 | #include "core/hle/service/am/applets/applets.h" | 49 | #include "core/hle/service/am/applets/applets.h" |
| 49 | #include "core/hle/service/set/system_settings_server.h" | 50 | #include "core/hle/service/set/system_settings_server.h" |