am.cpp 52 KB

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