ILibraryAppletAccessor.cs 8.1 KB

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