am.cpp 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <array>
  6. #include <cinttypes>
  7. #include <cstring>
  8. #include "audio_core/audio_renderer.h"
  9. #include "core/core.h"
  10. #include "core/file_sys/control_metadata.h"
  11. #include "core/file_sys/patch_manager.h"
  12. #include "core/file_sys/savedata_factory.h"
  13. #include "core/hle/ipc_helpers.h"
  14. #include "core/hle/kernel/kernel.h"
  15. #include "core/hle/kernel/process.h"
  16. #include "core/hle/kernel/readable_event.h"
  17. #include "core/hle/kernel/transfer_memory.h"
  18. #include "core/hle/kernel/writable_event.h"
  19. #include "core/hle/service/acc/profile_manager.h"
  20. #include "core/hle/service/am/am.h"
  21. #include "core/hle/service/am/applet_ae.h"
  22. #include "core/hle/service/am/applet_oe.h"
  23. #include "core/hle/service/am/applets/applets.h"
  24. #include "core/hle/service/am/applets/profile_select.h"
  25. #include "core/hle/service/am/applets/software_keyboard.h"
  26. #include "core/hle/service/am/applets/web_browser.h"
  27. #include "core/hle/service/am/idle.h"
  28. #include "core/hle/service/am/omm.h"
  29. #include "core/hle/service/am/spsm.h"
  30. #include "core/hle/service/am/tcap.h"
  31. #include "core/hle/service/apm/apm.h"
  32. #include "core/hle/service/filesystem/filesystem.h"
  33. #include "core/hle/service/ns/ns.h"
  34. #include "core/hle/service/nvflinger/nvflinger.h"
  35. #include "core/hle/service/pm/pm.h"
  36. #include "core/hle/service/set/set.h"
  37. #include "core/hle/service/sm/sm.h"
  38. #include "core/hle/service/vi/vi.h"
  39. #include "core/settings.h"
  40. namespace Service::AM {
  41. constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2};
  42. constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3};
  43. constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
  44. constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA;
  45. struct LaunchParameters {
  46. u32_le magic;
  47. u32_le is_account_selected;
  48. u128 current_user;
  49. INSERT_PADDING_BYTES(0x70);
  50. };
  51. static_assert(sizeof(LaunchParameters) == 0x88);
  52. IWindowController::IWindowController() : ServiceFramework("IWindowController") {
  53. // clang-format off
  54. static const FunctionInfo functions[] = {
  55. {0, nullptr, "CreateWindow"},
  56. {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
  57. {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
  58. {11, nullptr, "ReleaseForegroundRights"},
  59. {12, nullptr, "RejectToChangeIntoBackground"},
  60. {20, nullptr, "SetAppletWindowVisibility"},
  61. {21, nullptr, "SetAppletGpuTimeSlice"},
  62. };
  63. // clang-format on
  64. RegisterHandlers(functions);
  65. }
  66. IWindowController::~IWindowController() = default;
  67. void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
  68. const u64 process_id = Core::System::GetInstance().Kernel().CurrentProcess()->GetProcessID();
  69. LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
  70. IPC::ResponseBuilder rb{ctx, 4};
  71. rb.Push(RESULT_SUCCESS);
  72. rb.Push<u64>(process_id);
  73. }
  74. void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
  75. LOG_WARNING(Service_AM, "(STUBBED) called");
  76. IPC::ResponseBuilder rb{ctx, 2};
  77. rb.Push(RESULT_SUCCESS);
  78. }
  79. IAudioController::IAudioController() : ServiceFramework("IAudioController") {
  80. // clang-format off
  81. static const FunctionInfo functions[] = {
  82. {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
  83. {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"},
  84. {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"},
  85. {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"},
  86. {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"},
  87. };
  88. // clang-format on
  89. RegisterHandlers(functions);
  90. }
  91. IAudioController::~IAudioController() = default;
  92. void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
  93. IPC::RequestParser rp{ctx};
  94. const float main_applet_volume_tmp = rp.Pop<float>();
  95. const float library_applet_volume_tmp = rp.Pop<float>();
  96. LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
  97. main_applet_volume_tmp, library_applet_volume_tmp);
  98. // Ensure the volume values remain within the 0-100% range
  99. main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
  100. library_applet_volume =
  101. std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
  102. IPC::ResponseBuilder rb{ctx, 2};
  103. rb.Push(RESULT_SUCCESS);
  104. }
  105. void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
  106. LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume);
  107. IPC::ResponseBuilder rb{ctx, 3};
  108. rb.Push(RESULT_SUCCESS);
  109. rb.Push(main_applet_volume);
  110. }
  111. void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
  112. LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume);
  113. IPC::ResponseBuilder rb{ctx, 3};
  114. rb.Push(RESULT_SUCCESS);
  115. rb.Push(library_applet_volume);
  116. }
  117. void IAudioController::ChangeMainAppletMasterVolume(Kernel::HLERequestContext& ctx) {
  118. struct Parameters {
  119. float volume;
  120. s64 fade_time_ns;
  121. };
  122. static_assert(sizeof(Parameters) == 16);
  123. IPC::RequestParser rp{ctx};
  124. const auto parameters = rp.PopRaw<Parameters>();
  125. LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume,
  126. parameters.fade_time_ns);
  127. main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume);
  128. fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns};
  129. IPC::ResponseBuilder rb{ctx, 2};
  130. rb.Push(RESULT_SUCCESS);
  131. }
  132. void IAudioController::SetTransparentAudioRate(Kernel::HLERequestContext& ctx) {
  133. IPC::RequestParser rp{ctx};
  134. const float transparent_volume_rate_tmp = rp.Pop<float>();
  135. LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp);
  136. // Clamp volume range to 0-100%.
  137. transparent_volume_rate =
  138. std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume);
  139. IPC::ResponseBuilder rb{ctx, 2};
  140. rb.Push(RESULT_SUCCESS);
  141. }
  142. IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {
  143. // clang-format off
  144. static const FunctionInfo functions[] = {
  145. {0, nullptr, "GetLastForegroundCaptureImage"},
  146. {1, nullptr, "UpdateLastForegroundCaptureImage"},
  147. {2, nullptr, "GetLastApplicationCaptureImage"},
  148. {3, nullptr, "GetCallerAppletCaptureImage"},
  149. {4, nullptr, "UpdateCallerAppletCaptureImage"},
  150. {5, nullptr, "GetLastForegroundCaptureImageEx"},
  151. {6, nullptr, "GetLastApplicationCaptureImageEx"},
  152. {7, nullptr, "GetCallerAppletCaptureImageEx"},
  153. {8, nullptr, "TakeScreenShotOfOwnLayer"}, // 2.0.0+
  154. {9, nullptr, "CopyBetweenCaptureBuffers"}, // 5.0.0+
  155. {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
  156. {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
  157. {12, nullptr, "AcquireLastForegroundCaptureBuffer"},
  158. {13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
  159. {14, nullptr, "AcquireCallerAppletCaptureBuffer"},
  160. {15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
  161. {16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
  162. {17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
  163. {18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
  164. // 2.0.0+
  165. {20, nullptr, "ClearCaptureBuffer"},
  166. {21, nullptr, "ClearAppletTransitionBuffer"},
  167. // 4.0.0+
  168. {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"},
  169. {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
  170. {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"},
  171. {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"},
  172. {26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"},
  173. {27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"},
  174. // 6.0.0+
  175. {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
  176. };
  177. // clang-format on
  178. RegisterHandlers(functions);
  179. }
  180. IDisplayController::~IDisplayController() = default;
  181. IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} {
  182. // clang-format off
  183. static const FunctionInfo functions[] = {
  184. {0, nullptr, "NotifyMessageToHomeMenuForDebug"},
  185. {1, nullptr, "OpenMainApplication"},
  186. {10, nullptr, "EmulateButtonEvent"},
  187. {20, nullptr, "InvalidateTransitionLayer"},
  188. {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
  189. {40, nullptr, "GetAppletResourceUsageInfo"},
  190. {41, nullptr, "SetCpuBoostModeForApplet"},
  191. };
  192. // clang-format on
  193. RegisterHandlers(functions);
  194. }
  195. IDebugFunctions::~IDebugFunctions() = default;
  196. ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
  197. : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) {
  198. // clang-format off
  199. static const FunctionInfo functions[] = {
  200. {0, nullptr, "Exit"},
  201. {1, &ISelfController::LockExit, "LockExit"},
  202. {2, &ISelfController::UnlockExit, "UnlockExit"},
  203. {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
  204. {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
  205. {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
  206. {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
  207. {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
  208. {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"},
  209. {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
  210. {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
  211. {15, nullptr, "SetScreenShotAppletIdentityInfo"},
  212. {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
  213. {17, nullptr, "SetControllerFirmwareUpdateSection"},
  214. {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
  215. {19, &ISelfController::SetScreenShotImageOrientation, "SetScreenShotImageOrientation"},
  216. {20, nullptr, "SetDesirableKeyboardLayout"},
  217. {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
  218. {41, nullptr, "IsSystemBufferSharingEnabled"},
  219. {42, nullptr, "GetSystemSharedLayerHandle"},
  220. {43, nullptr, "GetSystemSharedBufferHandle"},
  221. {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
  222. {51, nullptr, "ApproveToDisplay"},
  223. {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
  224. {61, nullptr, "SetMediaPlaybackState"},
  225. {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
  226. {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
  227. {64, nullptr, "SetInputDetectionSourceSet"},
  228. {65, nullptr, "ReportUserIsActive"},
  229. {66, nullptr, "GetCurrentIlluminance"},
  230. {67, nullptr, "IsIlluminanceAvailable"},
  231. {68, nullptr, "SetAutoSleepDisabled"},
  232. {69, nullptr, "IsAutoSleepDisabled"},
  233. {70, nullptr, "ReportMultimediaError"},
  234. {71, nullptr, "GetCurrentIlluminanceEx"},
  235. {80, nullptr, "SetWirelessPriorityMode"},
  236. {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
  237. {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
  238. {100, nullptr, "SetAlbumImageTakenNotificationEnabled"},
  239. {1000, nullptr, "GetDebugStorageChannel"},
  240. };
  241. // clang-format on
  242. RegisterHandlers(functions);
  243. auto& kernel = Core::System::GetInstance().Kernel();
  244. launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
  245. "ISelfController:LaunchableEvent");
  246. // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is called.
  247. // Yuzu can just create it unconditionally, since it doesn't need to support multiple ISelfControllers.
  248. // The event is signaled on creation, and on transition from suspended -> not suspended if the event has
  249. // previously been created by a call to GetAccumulatedSuspendedTickChangedEvent.
  250. accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair(
  251. kernel, Kernel::ResetType::Manual, "ISelfController:AccumulatedSuspendedTickChangedEvent");
  252. accumulated_suspended_tick_changed_event.writable->Signal();
  253. }
  254. ISelfController::~ISelfController() = default;
  255. void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
  256. LOG_WARNING(Service_AM, "(STUBBED) called");
  257. IPC::ResponseBuilder rb{ctx, 2};
  258. rb.Push(RESULT_SUCCESS);
  259. }
  260. void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
  261. LOG_WARNING(Service_AM, "(STUBBED) called");
  262. IPC::ResponseBuilder rb{ctx, 2};
  263. rb.Push(RESULT_SUCCESS);
  264. }
  265. void ISelfController::EnterFatalSection(Kernel::HLERequestContext& ctx) {
  266. ++num_fatal_sections_entered;
  267. LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
  268. IPC::ResponseBuilder rb{ctx, 2};
  269. rb.Push(RESULT_SUCCESS);
  270. }
  271. void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
  272. LOG_DEBUG(Service_AM, "called.");
  273. // Entry and exit of fatal sections must be balanced.
  274. if (num_fatal_sections_entered == 0) {
  275. IPC::ResponseBuilder rb{ctx, 2};
  276. rb.Push(ResultCode{ErrorModule::AM, 512});
  277. return;
  278. }
  279. --num_fatal_sections_entered;
  280. IPC::ResponseBuilder rb{ctx, 2};
  281. rb.Push(RESULT_SUCCESS);
  282. }
  283. void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
  284. LOG_WARNING(Service_AM, "(STUBBED) called");
  285. launchable_event.writable->Signal();
  286. IPC::ResponseBuilder rb{ctx, 2, 1};
  287. rb.Push(RESULT_SUCCESS);
  288. rb.PushCopyObjects(launchable_event.readable);
  289. }
  290. void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
  291. LOG_WARNING(Service_AM, "(STUBBED) called");
  292. IPC::ResponseBuilder rb{ctx, 2};
  293. rb.Push(RESULT_SUCCESS);
  294. }
  295. void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
  296. IPC::RequestParser rp{ctx};
  297. bool flag = rp.Pop<bool>();
  298. LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
  299. IPC::ResponseBuilder rb{ctx, 2};
  300. rb.Push(RESULT_SUCCESS);
  301. }
  302. void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
  303. IPC::RequestParser rp{ctx};
  304. bool flag = rp.Pop<bool>();
  305. LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
  306. IPC::ResponseBuilder rb{ctx, 2};
  307. rb.Push(RESULT_SUCCESS);
  308. }
  309. void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
  310. // Takes 3 input u8s with each field located immediately after the previous
  311. // u8, these are bool flags. No output.
  312. IPC::RequestParser rp{ctx};
  313. struct FocusHandlingModeParams {
  314. u8 unknown0;
  315. u8 unknown1;
  316. u8 unknown2;
  317. };
  318. const auto flags = rp.PopRaw<FocusHandlingModeParams>();
  319. LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
  320. flags.unknown0, flags.unknown1, flags.unknown2);
  321. IPC::ResponseBuilder rb{ctx, 2};
  322. rb.Push(RESULT_SUCCESS);
  323. }
  324. void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
  325. LOG_WARNING(Service_AM, "(STUBBED) called");
  326. IPC::ResponseBuilder rb{ctx, 2};
  327. rb.Push(RESULT_SUCCESS);
  328. }
  329. void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
  330. // Takes 3 input u8s with each field located immediately after the previous
  331. // u8, these are bool flags. No output.
  332. IPC::RequestParser rp{ctx};
  333. bool enabled = rp.Pop<bool>();
  334. LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
  335. IPC::ResponseBuilder rb{ctx, 2};
  336. rb.Push(RESULT_SUCCESS);
  337. }
  338. void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) {
  339. LOG_WARNING(Service_AM, "(STUBBED) called");
  340. IPC::ResponseBuilder rb{ctx, 2};
  341. rb.Push(RESULT_SUCCESS);
  342. }
  343. void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
  344. LOG_WARNING(Service_AM, "(STUBBED) called");
  345. // TODO(Subv): Find out how AM determines the display to use, for now just
  346. // create the layer in the Default display.
  347. const auto display_id = nvflinger->OpenDisplay("Default");
  348. const auto layer_id = nvflinger->CreateLayer(*display_id);
  349. IPC::ResponseBuilder rb{ctx, 4};
  350. rb.Push(RESULT_SUCCESS);
  351. rb.Push(*layer_id);
  352. }
  353. void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) {
  354. LOG_WARNING(Service_AM, "(STUBBED) called");
  355. IPC::ResponseBuilder rb{ctx, 2};
  356. rb.Push(RESULT_SUCCESS);
  357. }
  358. void ISelfController::SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
  359. IPC::RequestParser rp{ctx};
  360. idle_time_detection_extension = rp.Pop<u32>();
  361. LOG_WARNING(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
  362. idle_time_detection_extension);
  363. IPC::ResponseBuilder rb{ctx, 2};
  364. rb.Push(RESULT_SUCCESS);
  365. }
  366. void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
  367. LOG_WARNING(Service_AM, "(STUBBED) called");
  368. IPC::ResponseBuilder rb{ctx, 3};
  369. rb.Push(RESULT_SUCCESS);
  370. rb.Push<u32>(idle_time_detection_extension);
  371. }
  372. void ISelfController::GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx) {
  373. LOG_DEBUG(Service_AM, "called.");
  374. // This command returns the total number of system ticks since ISelfController creation
  375. // where the game was suspended. Since Yuzu doesn't implement game suspension, this command
  376. // can just always return 0 ticks.
  377. IPC::ResponseBuilder rb{ctx, 4};
  378. rb.Push(RESULT_SUCCESS);
  379. rb.Push<u64>(0);
  380. }
  381. void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx) {
  382. LOG_DEBUG(Service_AM, "called.");
  383. IPC::ResponseBuilder rb{ctx, 2, 1};
  384. rb.Push(RESULT_SUCCESS);
  385. rb.PushCopyObjects(accumulated_suspended_tick_changed_event.readable);
  386. }
  387. AppletMessageQueue::AppletMessageQueue() {
  388. auto& kernel = Core::System::GetInstance().Kernel();
  389. on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
  390. "AMMessageQueue:OnMessageRecieved");
  391. on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair(
  392. kernel, Kernel::ResetType::Automatic, "AMMessageQueue:OperationModeChanged");
  393. }
  394. AppletMessageQueue::~AppletMessageQueue() = default;
  395. const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetMesssageRecieveEvent()
  396. const {
  397. return on_new_message.readable;
  398. }
  399. const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
  400. const {
  401. return on_operation_mode_changed.readable;
  402. }
  403. void AppletMessageQueue::PushMessage(AppletMessage msg) {
  404. messages.push(msg);
  405. on_new_message.writable->Signal();
  406. }
  407. AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
  408. if (messages.empty()) {
  409. on_new_message.writable->Clear();
  410. return AppletMessage::NoMessage;
  411. }
  412. auto msg = messages.front();
  413. messages.pop();
  414. if (messages.empty()) {
  415. on_new_message.writable->Clear();
  416. }
  417. return msg;
  418. }
  419. std::size_t AppletMessageQueue::GetMessageCount() const {
  420. return messages.size();
  421. }
  422. void AppletMessageQueue::OperationModeChanged() {
  423. PushMessage(AppletMessage::OperationModeChanged);
  424. PushMessage(AppletMessage::PerformanceModeChanged);
  425. on_operation_mode_changed.writable->Signal();
  426. }
  427. ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue)
  428. : ServiceFramework("ICommonStateGetter"), msg_queue(std::move(msg_queue)) {
  429. // clang-format off
  430. static const FunctionInfo functions[] = {
  431. {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
  432. {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
  433. {2, nullptr, "GetThisAppletKind"},
  434. {3, nullptr, "AllowToEnterSleep"},
  435. {4, nullptr, "DisallowToEnterSleep"},
  436. {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
  437. {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
  438. {7, nullptr, "GetCradleStatus"},
  439. {8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
  440. {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
  441. {10, nullptr, "RequestToAcquireSleepLock"},
  442. {11, nullptr, "ReleaseSleepLock"},
  443. {12, nullptr, "ReleaseSleepLockTransiently"},
  444. {13, nullptr, "GetAcquiredSleepLockEvent"},
  445. {20, nullptr, "PushToGeneralChannel"},
  446. {30, nullptr, "GetHomeButtonReaderLockAccessor"},
  447. {31, nullptr, "GetReaderLockAccessorEx"},
  448. {40, nullptr, "GetCradleFwVersion"},
  449. {50, nullptr, "IsVrModeEnabled"},
  450. {51, nullptr, "SetVrModeEnabled"},
  451. {52, nullptr, "SwitchLcdBacklight"},
  452. {53, nullptr, "BeginVrModeEx"},
  453. {54, nullptr, "EndVrModeEx"},
  454. {55, nullptr, "IsInControllerFirmwareUpdateSection"},
  455. {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
  456. {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
  457. {62, nullptr, "GetHdcpAuthenticationState"},
  458. {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
  459. {64, nullptr, "SetTvPowerStateMatchingMode"},
  460. {65, nullptr, "GetApplicationIdByContentActionName"},
  461. {66, nullptr, "SetCpuBoostMode"},
  462. {80, nullptr, "PerformSystemButtonPressingIfInFocus"},
  463. {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
  464. {91, nullptr, "GetCurrentPerformanceConfiguration"},
  465. {200, nullptr, "GetOperationModeSystemInfo"},
  466. };
  467. // clang-format on
  468. RegisterHandlers(functions);
  469. }
  470. ICommonStateGetter::~ICommonStateGetter() = default;
  471. void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) {
  472. LOG_DEBUG(Service_AM, "called");
  473. IPC::ResponseBuilder rb{ctx, 3};
  474. rb.Push(RESULT_SUCCESS);
  475. rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
  476. }
  477. void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) {
  478. LOG_DEBUG(Service_AM, "called");
  479. IPC::ResponseBuilder rb{ctx, 2, 1};
  480. rb.Push(RESULT_SUCCESS);
  481. rb.PushCopyObjects(msg_queue->GetMesssageRecieveEvent());
  482. }
  483. void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
  484. LOG_DEBUG(Service_AM, "called");
  485. const auto message = msg_queue->PopMessage();
  486. IPC::ResponseBuilder rb{ctx, 3};
  487. if (message == AppletMessageQueue::AppletMessage::NoMessage) {
  488. LOG_ERROR(Service_AM, "Message queue is empty");
  489. rb.Push(ERR_NO_MESSAGES);
  490. rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
  491. return;
  492. }
  493. rb.Push(RESULT_SUCCESS);
  494. rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
  495. }
  496. void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
  497. LOG_WARNING(Service_AM, "(STUBBED) called");
  498. IPC::ResponseBuilder rb{ctx, 3};
  499. rb.Push(RESULT_SUCCESS);
  500. rb.Push(static_cast<u8>(FocusState::InFocus));
  501. }
  502. void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) {
  503. LOG_DEBUG(Service_AM, "called");
  504. IPC::ResponseBuilder rb{ctx, 2, 1};
  505. rb.Push(RESULT_SUCCESS);
  506. rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent());
  507. }
  508. void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx) {
  509. LOG_DEBUG(Service_AM, "called");
  510. IPC::ResponseBuilder rb{ctx, 4};
  511. rb.Push(RESULT_SUCCESS);
  512. if (Settings::values.use_docked_mode) {
  513. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
  514. static_cast<u32>(Settings::values.resolution_factor));
  515. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
  516. static_cast<u32>(Settings::values.resolution_factor));
  517. } else {
  518. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) *
  519. static_cast<u32>(Settings::values.resolution_factor));
  520. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) *
  521. static_cast<u32>(Settings::values.resolution_factor));
  522. }
  523. }
  524. IStorage::IStorage(std::vector<u8> buffer)
  525. : ServiceFramework("IStorage"), buffer(std::move(buffer)) {
  526. // clang-format off
  527. static const FunctionInfo functions[] = {
  528. {0, &IStorage::Open, "Open"},
  529. {1, nullptr, "OpenTransferStorage"},
  530. };
  531. // clang-format on
  532. RegisterHandlers(functions);
  533. }
  534. IStorage::~IStorage() = default;
  535. const std::vector<u8>& IStorage::GetData() const {
  536. return buffer;
  537. }
  538. void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
  539. const bool use_docked_mode{Settings::values.use_docked_mode};
  540. LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
  541. IPC::ResponseBuilder rb{ctx, 3};
  542. rb.Push(RESULT_SUCCESS);
  543. rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
  544. }
  545. void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
  546. const bool use_docked_mode{Settings::values.use_docked_mode};
  547. LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
  548. IPC::ResponseBuilder rb{ctx, 3};
  549. rb.Push(RESULT_SUCCESS);
  550. rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked
  551. : APM::PerformanceMode::Handheld));
  552. }
  553. class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
  554. public:
  555. explicit ILibraryAppletAccessor(std::shared_ptr<Applets::Applet> applet)
  556. : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)) {
  557. // clang-format off
  558. static const FunctionInfo functions[] = {
  559. {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
  560. {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
  561. {10, &ILibraryAppletAccessor::Start, "Start"},
  562. {20, nullptr, "RequestExit"},
  563. {25, nullptr, "Terminate"},
  564. {30, &ILibraryAppletAccessor::GetResult, "GetResult"},
  565. {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
  566. {100, &ILibraryAppletAccessor::PushInData, "PushInData"},
  567. {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
  568. {102, nullptr, "PushExtraStorage"},
  569. {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
  570. {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
  571. {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
  572. {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
  573. {110, nullptr, "NeedsToExitProcess"},
  574. {120, nullptr, "GetLibraryAppletInfo"},
  575. {150, nullptr, "RequestForAppletToGetForeground"},
  576. {160, nullptr, "GetIndirectLayerConsumerHandle"},
  577. };
  578. // clang-format on
  579. RegisterHandlers(functions);
  580. }
  581. private:
  582. void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) {
  583. LOG_DEBUG(Service_AM, "called");
  584. const auto event = applet->GetBroker().GetStateChangedEvent();
  585. IPC::ResponseBuilder rb{ctx, 2, 1};
  586. rb.Push(RESULT_SUCCESS);
  587. rb.PushCopyObjects(event);
  588. }
  589. void IsCompleted(Kernel::HLERequestContext& ctx) {
  590. LOG_DEBUG(Service_AM, "called");
  591. IPC::ResponseBuilder rb{ctx, 3};
  592. rb.Push(RESULT_SUCCESS);
  593. rb.Push<u32>(applet->TransactionComplete());
  594. }
  595. void GetResult(Kernel::HLERequestContext& ctx) {
  596. LOG_DEBUG(Service_AM, "called");
  597. IPC::ResponseBuilder rb{ctx, 2};
  598. rb.Push(applet->GetStatus());
  599. }
  600. void Start(Kernel::HLERequestContext& ctx) {
  601. LOG_DEBUG(Service_AM, "called");
  602. ASSERT(applet != nullptr);
  603. applet->Initialize();
  604. applet->Execute();
  605. IPC::ResponseBuilder rb{ctx, 2};
  606. rb.Push(RESULT_SUCCESS);
  607. }
  608. void PushInData(Kernel::HLERequestContext& ctx) {
  609. LOG_DEBUG(Service_AM, "called");
  610. IPC::RequestParser rp{ctx};
  611. applet->GetBroker().PushNormalDataFromGame(*rp.PopIpcInterface<IStorage>());
  612. IPC::ResponseBuilder rb{ctx, 2};
  613. rb.Push(RESULT_SUCCESS);
  614. }
  615. void PopOutData(Kernel::HLERequestContext& ctx) {
  616. LOG_DEBUG(Service_AM, "called");
  617. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  618. const auto storage = applet->GetBroker().PopNormalDataToGame();
  619. if (storage == nullptr) {
  620. LOG_ERROR(Service_AM,
  621. "storage is a nullptr. There is no data in the current normal channel");
  622. rb.Push(ERR_NO_DATA_IN_CHANNEL);
  623. return;
  624. }
  625. rb.Push(RESULT_SUCCESS);
  626. rb.PushIpcInterface<IStorage>(std::move(*storage));
  627. }
  628. void PushInteractiveInData(Kernel::HLERequestContext& ctx) {
  629. LOG_DEBUG(Service_AM, "called");
  630. IPC::RequestParser rp{ctx};
  631. applet->GetBroker().PushInteractiveDataFromGame(*rp.PopIpcInterface<IStorage>());
  632. ASSERT(applet->IsInitialized());
  633. applet->ExecuteInteractive();
  634. applet->Execute();
  635. IPC::ResponseBuilder rb{ctx, 2};
  636. rb.Push(RESULT_SUCCESS);
  637. }
  638. void PopInteractiveOutData(Kernel::HLERequestContext& ctx) {
  639. LOG_DEBUG(Service_AM, "called");
  640. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  641. const auto storage = applet->GetBroker().PopInteractiveDataToGame();
  642. if (storage == nullptr) {
  643. LOG_ERROR(Service_AM,
  644. "storage is a nullptr. There is no data in the current interactive channel");
  645. rb.Push(ERR_NO_DATA_IN_CHANNEL);
  646. return;
  647. }
  648. rb.Push(RESULT_SUCCESS);
  649. rb.PushIpcInterface<IStorage>(std::move(*storage));
  650. }
  651. void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) {
  652. LOG_DEBUG(Service_AM, "called");
  653. IPC::ResponseBuilder rb{ctx, 2, 1};
  654. rb.Push(RESULT_SUCCESS);
  655. rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
  656. }
  657. void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) {
  658. LOG_DEBUG(Service_AM, "called");
  659. IPC::ResponseBuilder rb{ctx, 2, 1};
  660. rb.Push(RESULT_SUCCESS);
  661. rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
  662. }
  663. std::shared_ptr<Applets::Applet> applet;
  664. };
  665. void IStorage::Open(Kernel::HLERequestContext& ctx) {
  666. LOG_DEBUG(Service_AM, "called");
  667. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  668. rb.Push(RESULT_SUCCESS);
  669. rb.PushIpcInterface<IStorageAccessor>(*this);
  670. }
  671. IStorageAccessor::IStorageAccessor(IStorage& storage)
  672. : ServiceFramework("IStorageAccessor"), backing(storage) {
  673. // clang-format off
  674. static const FunctionInfo functions[] = {
  675. {0, &IStorageAccessor::GetSize, "GetSize"},
  676. {10, &IStorageAccessor::Write, "Write"},
  677. {11, &IStorageAccessor::Read, "Read"},
  678. };
  679. // clang-format on
  680. RegisterHandlers(functions);
  681. }
  682. IStorageAccessor::~IStorageAccessor() = default;
  683. void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) {
  684. LOG_DEBUG(Service_AM, "called");
  685. IPC::ResponseBuilder rb{ctx, 4};
  686. rb.Push(RESULT_SUCCESS);
  687. rb.Push(static_cast<u64>(backing.buffer.size()));
  688. }
  689. void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
  690. IPC::RequestParser rp{ctx};
  691. const u64 offset{rp.Pop<u64>()};
  692. const std::vector<u8> data{ctx.ReadBuffer()};
  693. LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size());
  694. if (data.size() > backing.buffer.size() - offset) {
  695. LOG_ERROR(Service_AM,
  696. "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}",
  697. backing.buffer.size(), data.size(), offset);
  698. IPC::ResponseBuilder rb{ctx, 2};
  699. rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
  700. return;
  701. }
  702. std::memcpy(backing.buffer.data() + offset, data.data(), data.size());
  703. IPC::ResponseBuilder rb{ctx, 2};
  704. rb.Push(RESULT_SUCCESS);
  705. }
  706. void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
  707. IPC::RequestParser rp{ctx};
  708. const u64 offset{rp.Pop<u64>()};
  709. const std::size_t size{ctx.GetWriteBufferSize()};
  710. LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
  711. if (size > backing.buffer.size() - offset) {
  712. LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}",
  713. backing.buffer.size(), size, offset);
  714. IPC::ResponseBuilder rb{ctx, 2};
  715. rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
  716. return;
  717. }
  718. ctx.WriteBuffer(backing.buffer.data() + offset, size);
  719. IPC::ResponseBuilder rb{ctx, 2};
  720. rb.Push(RESULT_SUCCESS);
  721. }
  722. ILibraryAppletCreator::ILibraryAppletCreator(u64 current_process_title_id)
  723. : ServiceFramework("ILibraryAppletCreator"),
  724. current_process_title_id(current_process_title_id) {
  725. static const FunctionInfo functions[] = {
  726. {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
  727. {1, nullptr, "TerminateAllLibraryApplets"},
  728. {2, nullptr, "AreAnyLibraryAppletsLeft"},
  729. {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
  730. {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
  731. {12, nullptr, "CreateHandleStorage"},
  732. };
  733. RegisterHandlers(functions);
  734. }
  735. ILibraryAppletCreator::~ILibraryAppletCreator() = default;
  736. void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
  737. IPC::RequestParser rp{ctx};
  738. const auto applet_id = rp.PopRaw<Applets::AppletId>();
  739. const auto applet_mode = rp.PopRaw<u32>();
  740. LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}",
  741. static_cast<u32>(applet_id), applet_mode);
  742. const auto& applet_manager{Core::System::GetInstance().GetAppletManager()};
  743. const auto applet = applet_manager.GetApplet(applet_id, current_process_title_id);
  744. if (applet == nullptr) {
  745. LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
  746. IPC::ResponseBuilder rb{ctx, 2};
  747. rb.Push(ResultCode(-1));
  748. return;
  749. }
  750. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  751. rb.Push(RESULT_SUCCESS);
  752. rb.PushIpcInterface<AM::ILibraryAppletAccessor>(applet);
  753. }
  754. void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
  755. IPC::RequestParser rp{ctx};
  756. const u64 size{rp.Pop<u64>()};
  757. LOG_DEBUG(Service_AM, "called, size={}", size);
  758. std::vector<u8> buffer(size);
  759. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  760. rb.Push(RESULT_SUCCESS);
  761. rb.PushIpcInterface<AM::IStorage>(std::move(buffer));
  762. }
  763. void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) {
  764. LOG_DEBUG(Service_AM, "called");
  765. IPC::RequestParser rp{ctx};
  766. rp.SetCurrentOffset(3);
  767. const auto handle{rp.Pop<Kernel::Handle>()};
  768. const auto transfer_mem =
  769. Core::System::GetInstance().CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(
  770. handle);
  771. if (transfer_mem == nullptr) {
  772. LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle);
  773. IPC::ResponseBuilder rb{ctx, 2};
  774. rb.Push(ResultCode(-1));
  775. return;
  776. }
  777. const u8* const mem_begin = transfer_mem->GetPointer();
  778. const u8* const mem_end = mem_begin + transfer_mem->GetSize();
  779. std::vector<u8> memory{mem_begin, mem_end};
  780. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  781. rb.Push(RESULT_SUCCESS);
  782. rb.PushIpcInterface(std::make_shared<IStorage>(std::move(memory)));
  783. }
  784. IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
  785. // clang-format off
  786. static const FunctionInfo functions[] = {
  787. {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
  788. {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
  789. {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
  790. {12, nullptr, "CreateApplicationAndRequestToStart"},
  791. {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
  792. {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
  793. {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
  794. {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
  795. {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
  796. {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
  797. {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
  798. {24, nullptr, "GetLaunchStorageInfoForDebug"},
  799. {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
  800. {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
  801. {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
  802. {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
  803. {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
  804. {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
  805. {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
  806. {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
  807. {60, nullptr, "SetMediaPlaybackStateForApplication"},
  808. {65, nullptr, "IsGamePlayRecordingSupported"},
  809. {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
  810. {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
  811. {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
  812. {70, nullptr, "RequestToShutdown"},
  813. {71, nullptr, "RequestToReboot"},
  814. {80, nullptr, "ExitAndRequestToShowThanksMessage"},
  815. {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
  816. {100, nullptr, "InitializeApplicationCopyrightFrameBuffer"},
  817. {101, nullptr, "SetApplicationCopyrightImage"},
  818. {102, nullptr, "SetApplicationCopyrightVisibility"},
  819. {110, nullptr, "QueryApplicationPlayStatistics"},
  820. {120, nullptr, "ExecuteProgram"},
  821. {121, nullptr, "ClearUserChannel"},
  822. {122, nullptr, "UnpopToUserChannel"},
  823. {500, nullptr, "StartContinuousRecordingFlushForDebug"},
  824. {1000, nullptr, "CreateMovieMaker"},
  825. {1001, nullptr, "PrepareForJit"},
  826. };
  827. // clang-format on
  828. RegisterHandlers(functions);
  829. }
  830. IApplicationFunctions::~IApplicationFunctions() = default;
  831. void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestContext& ctx) {
  832. LOG_WARNING(Service_AM, "(STUBBED) called");
  833. IPC::ResponseBuilder rb{ctx, 2};
  834. rb.Push(RESULT_SUCCESS);
  835. }
  836. void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(
  837. Kernel::HLERequestContext& ctx) {
  838. LOG_WARNING(Service_AM, "(STUBBED) called");
  839. IPC::ResponseBuilder rb{ctx, 2};
  840. rb.Push(RESULT_SUCCESS);
  841. }
  842. void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(
  843. Kernel::HLERequestContext& ctx) {
  844. LOG_WARNING(Service_AM, "(STUBBED) called");
  845. IPC::ResponseBuilder rb{ctx, 2};
  846. rb.Push(RESULT_SUCCESS);
  847. }
  848. void IApplicationFunctions::BeginBlockingHomeButton(Kernel::HLERequestContext& ctx) {
  849. LOG_WARNING(Service_AM, "(STUBBED) called");
  850. IPC::ResponseBuilder rb{ctx, 2};
  851. rb.Push(RESULT_SUCCESS);
  852. }
  853. void IApplicationFunctions::EndBlockingHomeButton(Kernel::HLERequestContext& ctx) {
  854. LOG_WARNING(Service_AM, "(STUBBED) called");
  855. IPC::ResponseBuilder rb{ctx, 2};
  856. rb.Push(RESULT_SUCCESS);
  857. }
  858. void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
  859. LOG_DEBUG(Service_AM, "called");
  860. LaunchParameters params{};
  861. params.magic = POP_LAUNCH_PARAMETER_MAGIC;
  862. params.is_account_selected = 1;
  863. Account::ProfileManager profile_manager{};
  864. const auto uuid = profile_manager.GetUser(Settings::values.current_user);
  865. ASSERT(uuid);
  866. params.current_user = uuid->uuid;
  867. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  868. rb.Push(RESULT_SUCCESS);
  869. std::vector<u8> buffer(sizeof(LaunchParameters));
  870. std::memcpy(buffer.data(), &params, buffer.size());
  871. rb.PushIpcInterface<AM::IStorage>(buffer);
  872. }
  873. void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(
  874. Kernel::HLERequestContext& ctx) {
  875. LOG_WARNING(Service_AM, "(STUBBED) called");
  876. IPC::ResponseBuilder rb{ctx, 2};
  877. rb.Push(RESULT_SUCCESS);
  878. }
  879. void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
  880. IPC::RequestParser rp{ctx};
  881. u128 uid = rp.PopRaw<u128>(); // What does this do?
  882. LOG_WARNING(Service, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
  883. IPC::ResponseBuilder rb{ctx, 4};
  884. rb.Push(RESULT_SUCCESS);
  885. rb.Push<u64>(0);
  886. } // namespace Service::AM
  887. void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
  888. // Takes an input u32 Result, no output.
  889. // For example, in some cases official apps use this with error 0x2A2 then
  890. // uses svcBreak.
  891. IPC::RequestParser rp{ctx};
  892. u32 result = rp.Pop<u32>();
  893. LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
  894. IPC::ResponseBuilder rb{ctx, 2};
  895. rb.Push(RESULT_SUCCESS);
  896. }
  897. void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
  898. LOG_WARNING(Service_AM, "(STUBBED) called");
  899. IPC::ResponseBuilder rb{ctx, 6};
  900. rb.Push(RESULT_SUCCESS);
  901. rb.Push<u64>(1);
  902. rb.Push<u64>(0);
  903. }
  904. void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
  905. // TODO(bunnei): This should be configurable
  906. LOG_DEBUG(Service_AM, "called");
  907. // Get supported languages from NACP, if possible
  908. // Default to 0 (all languages supported)
  909. u32 supported_languages = 0;
  910. FileSys::PatchManager pm{Core::System::GetInstance().CurrentProcess()->GetTitleID()};
  911. const auto res = pm.GetControlMetadata();
  912. if (res.first != nullptr) {
  913. supported_languages = res.first->GetSupportedLanguages();
  914. }
  915. // Call IApplicationManagerInterface implementation.
  916. auto& service_manager = Core::System::GetInstance().ServiceManager();
  917. auto ns_am2 = service_manager.GetService<Service::NS::NS>("ns:am2");
  918. auto app_man = ns_am2->GetApplicationManagerInterface();
  919. // Get desired application language
  920. const auto res_lang = app_man->GetApplicationDesiredLanguage(supported_languages);
  921. if (res_lang.Failed()) {
  922. IPC::ResponseBuilder rb{ctx, 2};
  923. rb.Push(res_lang.Code());
  924. return;
  925. }
  926. // Convert to settings language code.
  927. const auto res_code = app_man->ConvertApplicationLanguageToLanguageCode(*res_lang);
  928. if (res_code.Failed()) {
  929. IPC::ResponseBuilder rb{ctx, 2};
  930. rb.Push(res_code.Code());
  931. return;
  932. }
  933. LOG_DEBUG(Service_AM, "got desired_language={:016X}", *res_code);
  934. IPC::ResponseBuilder rb{ctx, 4};
  935. rb.Push(RESULT_SUCCESS);
  936. rb.Push(*res_code);
  937. }
  938. void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
  939. LOG_WARNING(Service_AM, "(STUBBED) called");
  940. IPC::ResponseBuilder rb{ctx, 2};
  941. rb.Push(RESULT_SUCCESS);
  942. }
  943. void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
  944. LOG_WARNING(Service_AM, "(STUBBED) called");
  945. IPC::ResponseBuilder rb{ctx, 2};
  946. rb.Push(RESULT_SUCCESS);
  947. }
  948. void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
  949. LOG_WARNING(Service_AM, "(STUBBED) called");
  950. IPC::ResponseBuilder rb{ctx, 3};
  951. rb.Push(RESULT_SUCCESS);
  952. rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
  953. }
  954. void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) {
  955. LOG_WARNING(Service_AM, "(STUBBED) called");
  956. IPC::ResponseBuilder rb{ctx, 6};
  957. rb.Push(RESULT_SUCCESS);
  958. // Returns a 128-bit UUID
  959. rb.Push<u64>(0);
  960. rb.Push<u64>(0);
  961. }
  962. void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) {
  963. IPC::RequestParser rp{ctx};
  964. const auto type{rp.PopRaw<FileSys::SaveDataType>()};
  965. rp.Skip(1, false);
  966. const auto user_id{rp.PopRaw<u128>()};
  967. const auto new_normal_size{rp.PopRaw<u64>()};
  968. const auto new_journal_size{rp.PopRaw<u64>()};
  969. LOG_DEBUG(Service_AM,
  970. "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
  971. "new_journal={:016X}",
  972. static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
  973. FileSystem::WriteSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id,
  974. {new_normal_size, new_journal_size});
  975. IPC::ResponseBuilder rb{ctx, 4};
  976. rb.Push(RESULT_SUCCESS);
  977. // The following value is used upon failure to help the system recover.
  978. // Since we always succeed, this should be 0.
  979. rb.Push<u64>(0);
  980. }
  981. void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) {
  982. IPC::RequestParser rp{ctx};
  983. const auto type{rp.PopRaw<FileSys::SaveDataType>()};
  984. rp.Skip(1, false);
  985. const auto user_id{rp.PopRaw<u128>()};
  986. LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", static_cast<u8>(type),
  987. user_id[1], user_id[0]);
  988. const auto size =
  989. FileSystem::ReadSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id);
  990. IPC::ResponseBuilder rb{ctx, 6};
  991. rb.Push(RESULT_SUCCESS);
  992. rb.Push(size.normal);
  993. rb.Push(size.journal);
  994. }
  995. void InstallInterfaces(SM::ServiceManager& service_manager,
  996. std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system) {
  997. auto message_queue = std::make_shared<AppletMessageQueue>();
  998. message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); // Needed on
  999. // game boot
  1000. std::make_shared<AppletAE>(nvflinger, message_queue, system)->InstallAsService(service_manager);
  1001. std::make_shared<AppletOE>(nvflinger, message_queue, system)->InstallAsService(service_manager);
  1002. std::make_shared<IdleSys>()->InstallAsService(service_manager);
  1003. std::make_shared<OMM>()->InstallAsService(service_manager);
  1004. std::make_shared<SPSM>()->InstallAsService(service_manager);
  1005. std::make_shared<TCAP>()->InstallAsService(service_manager);
  1006. }
  1007. IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions") {
  1008. // clang-format off
  1009. static const FunctionInfo functions[] = {
  1010. {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
  1011. {11, nullptr, "LockForeground"},
  1012. {12, nullptr, "UnlockForeground"},
  1013. {20, nullptr, "PopFromGeneralChannel"},
  1014. {21, nullptr, "GetPopFromGeneralChannelEvent"},
  1015. {30, nullptr, "GetHomeButtonWriterLockAccessor"},
  1016. {31, nullptr, "GetWriterLockAccessorEx"},
  1017. {100, nullptr, "PopRequestLaunchApplicationForDebug"},
  1018. };
  1019. // clang-format on
  1020. RegisterHandlers(functions);
  1021. }
  1022. IHomeMenuFunctions::~IHomeMenuFunctions() = default;
  1023. void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) {
  1024. LOG_WARNING(Service_AM, "(STUBBED) called");
  1025. IPC::ResponseBuilder rb{ctx, 2};
  1026. rb.Push(RESULT_SUCCESS);
  1027. }
  1028. IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStateController") {
  1029. // clang-format off
  1030. static const FunctionInfo functions[] = {
  1031. {0, nullptr, "RequestToEnterSleep"},
  1032. {1, nullptr, "EnterSleep"},
  1033. {2, nullptr, "StartSleepSequence"},
  1034. {3, nullptr, "StartShutdownSequence"},
  1035. {4, nullptr, "StartRebootSequence"},
  1036. {9, nullptr, "IsAutoPowerDownRequested"},
  1037. {10, nullptr, "LoadAndApplyIdlePolicySettings"},
  1038. {11, nullptr, "NotifyCecSettingsChanged"},
  1039. {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
  1040. {13, nullptr, "UpdateDefaultDisplayResolution"},
  1041. {14, nullptr, "ShouldSleepOnBoot"},
  1042. {15, nullptr, "GetHdcpAuthenticationFailedEvent"},
  1043. };
  1044. // clang-format on
  1045. RegisterHandlers(functions);
  1046. }
  1047. IGlobalStateController::~IGlobalStateController() = default;
  1048. IApplicationCreator::IApplicationCreator() : ServiceFramework("IApplicationCreator") {
  1049. // clang-format off
  1050. static const FunctionInfo functions[] = {
  1051. {0, nullptr, "CreateApplication"},
  1052. {1, nullptr, "PopLaunchRequestedApplication"},
  1053. {10, nullptr, "CreateSystemApplication"},
  1054. {100, nullptr, "PopFloatingApplicationForDevelopment"},
  1055. };
  1056. // clang-format on
  1057. RegisterHandlers(functions);
  1058. }
  1059. IApplicationCreator::~IApplicationCreator() = default;
  1060. IProcessWindingController::IProcessWindingController()
  1061. : ServiceFramework("IProcessWindingController") {
  1062. // clang-format off
  1063. static const FunctionInfo functions[] = {
  1064. {0, nullptr, "GetLaunchReason"},
  1065. {11, nullptr, "OpenCallingLibraryApplet"},
  1066. {21, nullptr, "PushContext"},
  1067. {22, nullptr, "PopContext"},
  1068. {23, nullptr, "CancelWindingReservation"},
  1069. {30, nullptr, "WindAndDoReserved"},
  1070. {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
  1071. {41, nullptr, "ReserveToStartAndWait"},
  1072. };
  1073. // clang-format on
  1074. RegisterHandlers(functions);
  1075. }
  1076. IProcessWindingController::~IProcessWindingController() = default;
  1077. } // namespace Service::AM