ILibraryAppletAccessor.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.HLE.HOS.Applets;
  3. using Ryujinx.HLE.HOS.Ipc;
  4. using Ryujinx.HLE.HOS.Kernel.Common;
  5. using Ryujinx.HLE.HOS.Kernel.Threading;
  6. using System;
  7. namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
  8. {
  9. class ILibraryAppletAccessor : IpcService
  10. {
  11. private IApplet _applet;
  12. private AppletSession _normalSession;
  13. private AppletSession _interactiveSession;
  14. private KEvent _stateChangedEvent;
  15. private KEvent _normalOutDataEvent;
  16. private KEvent _interactiveOutDataEvent;
  17. public ILibraryAppletAccessor(AppletId appletId, Horizon system)
  18. {
  19. _stateChangedEvent = new KEvent(system.KernelContext);
  20. _normalOutDataEvent = new KEvent(system.KernelContext);
  21. _interactiveOutDataEvent = new KEvent(system.KernelContext);
  22. _applet = AppletManager.Create(appletId, system);
  23. _normalSession = new AppletSession();
  24. _interactiveSession = new AppletSession();
  25. _applet.AppletStateChanged += OnAppletStateChanged;
  26. _normalSession.DataAvailable += OnNormalOutData;
  27. _interactiveSession.DataAvailable += OnInteractiveOutData;
  28. Logger.Info?.Print(LogClass.ServiceAm, $"Applet '{appletId}' created.");
  29. }
  30. private void OnAppletStateChanged(object sender, EventArgs e)
  31. {
  32. _stateChangedEvent.WritableEvent.Signal();
  33. }
  34. private void OnNormalOutData(object sender, EventArgs e)
  35. {
  36. _normalOutDataEvent.WritableEvent.Signal();
  37. }
  38. private void OnInteractiveOutData(object sender, EventArgs e)
  39. {
  40. _interactiveOutDataEvent.WritableEvent.Signal();
  41. }
  42. [Command(0)]
  43. // GetAppletStateChangedEvent() -> handle<copy>
  44. public ResultCode GetAppletStateChangedEvent(ServiceCtx context)
  45. {
  46. if (context.Process.HandleTable.GenerateHandle(_stateChangedEvent.ReadableEvent, out int handle) != KernelResult.Success)
  47. {
  48. throw new InvalidOperationException("Out of handles!");
  49. }
  50. context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
  51. return ResultCode.Success;
  52. }
  53. [Command(10)]
  54. // Start()
  55. public ResultCode Start(ServiceCtx context)
  56. {
  57. return (ResultCode)_applet.Start(_normalSession.GetConsumer(),
  58. _interactiveSession.GetConsumer());
  59. }
  60. [Command(30)]
  61. // GetResult()
  62. public ResultCode GetResult(ServiceCtx context)
  63. {
  64. return (ResultCode)_applet.GetResult();
  65. }
  66. [Command(100)]
  67. // PushInData(object<nn::am::service::IStorage>)
  68. public ResultCode PushInData(ServiceCtx context)
  69. {
  70. IStorage data = GetObject<IStorage>(context, 0);
  71. _normalSession.Push(data.Data);
  72. return ResultCode.Success;
  73. }
  74. [Command(101)]
  75. // PopOutData() -> object<nn::am::service::IStorage>
  76. public ResultCode PopOutData(ServiceCtx context)
  77. {
  78. if(_normalSession.TryPop(out byte[] data))
  79. {
  80. MakeObject(context, new IStorage(data));
  81. _normalOutDataEvent.WritableEvent.Clear();
  82. return ResultCode.Success;
  83. }
  84. return ResultCode.NotAvailable;
  85. }
  86. [Command(103)]
  87. // PushInteractiveInData(object<nn::am::service::IStorage>)
  88. public ResultCode PushInteractiveInData(ServiceCtx context)
  89. {
  90. IStorage data = GetObject<IStorage>(context, 0);
  91. _interactiveSession.Push(data.Data);
  92. return ResultCode.Success;
  93. }
  94. [Command(104)]
  95. // PopInteractiveOutData() -> object<nn::am::service::IStorage>
  96. public ResultCode PopInteractiveOutData(ServiceCtx context)
  97. {
  98. if(_interactiveSession.TryPop(out byte[] data))
  99. {
  100. MakeObject(context, new IStorage(data));
  101. _interactiveOutDataEvent.WritableEvent.Clear();
  102. return ResultCode.Success;
  103. }
  104. return ResultCode.NotAvailable;
  105. }
  106. [Command(105)]
  107. // GetPopOutDataEvent() -> handle<copy>
  108. public ResultCode GetPopOutDataEvent(ServiceCtx context)
  109. {
  110. if (context.Process.HandleTable.GenerateHandle(_normalOutDataEvent.ReadableEvent, out int handle) != KernelResult.Success)
  111. {
  112. throw new InvalidOperationException("Out of handles!");
  113. }
  114. context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
  115. return ResultCode.Success;
  116. }
  117. [Command(106)]
  118. // GetPopInteractiveOutDataEvent() -> handle<copy>
  119. public ResultCode GetPopInteractiveOutDataEvent(ServiceCtx context)
  120. {
  121. if (context.Process.HandleTable.GenerateHandle(_interactiveOutDataEvent.ReadableEvent, out int handle) != KernelResult.Success)
  122. {
  123. throw new InvalidOperationException("Out of handles!");
  124. }
  125. context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
  126. return ResultCode.Success;
  127. }
  128. [Command(110)]
  129. // NeedsToExitProcess()
  130. public ResultCode NeedsToExitProcess(ServiceCtx context)
  131. {
  132. return ResultCode.Stubbed;
  133. }
  134. [Command(150)]
  135. // RequestForAppletToGetForeground()
  136. public ResultCode RequestForAppletToGetForeground(ServiceCtx context)
  137. {
  138. return ResultCode.Stubbed;
  139. }
  140. [Command(160)] // 2.0.0+
  141. // GetIndirectLayerConsumerHandle() -> u64 indirect_layer_consumer_handle
  142. public ResultCode GetIndirectLayerConsumerHandle(ServiceCtx context)
  143. {
  144. /*
  145. if (indirectLayerConsumer == null)
  146. {
  147. return ResultCode.ObjectInvalid;
  148. }
  149. */
  150. // TODO: Official sw uses this during LibraryApplet creation when LibraryAppletMode is 0x3.
  151. // Since we don't support IndirectLayer and the handle couldn't be 0, it's fine to return 1.
  152. ulong indirectLayerConsumerHandle = 1;
  153. context.ResponseData.Write(indirectLayerConsumerHandle);
  154. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { indirectLayerConsumerHandle });
  155. return ResultCode.Success;
  156. }
  157. }
  158. }