aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjduncanator <1518948+jduncanator@users.noreply.github.com>2019-11-14 16:18:44 +1100
committerAc_K <Acoustik666@gmail.com>2019-11-14 06:18:44 +0100
commit35e561276648ecfd828cfa4883d95f26959100c6 (patch)
treeec31e8287bf87d2811e7801627bd51e78a105d87
parent7c111a356704bc86038d2001f9bbe56d27152590 (diff)
Implement a rudimentary applets system (#804)
* Implement Player Select applet * Initialize the Horizon system reference * Tidy up namespaces * Resolve nits * Resolve nits * Rename stack to queue * Implement an applet FIFO * Remove debugging log * Log applet creation events * Reorganise AppletFifo * More reorganisation * Final changes
-rw-r--r--Ryujinx.HLE/HOS/Applets/AppletManager.cs29
-rw-r--r--Ryujinx.HLE/HOS/Applets/IApplet.cs13
-rw-r--r--Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs55
-rw-r--r--Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectResult.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs42
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs6
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AppletFifo.cs79
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletId.cs27
8 files changed, 245 insertions, 14 deletions
diff --git a/Ryujinx.HLE/HOS/Applets/AppletManager.cs b/Ryujinx.HLE/HOS/Applets/AppletManager.cs
new file mode 100644
index 00000000..e5426cd7
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Applets/AppletManager.cs
@@ -0,0 +1,29 @@
+using Ryujinx.HLE.HOS.Services.Am.AppletAE;
+using System;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Applets
+{
+ static class AppletManager
+ {
+ private static Dictionary<AppletId, Type> _appletMapping;
+
+ static AppletManager()
+ {
+ _appletMapping = new Dictionary<AppletId, Type>
+ {
+ { AppletId.PlayerSelect, typeof(PlayerSelectApplet) }
+ };
+ }
+
+ public static IApplet Create(AppletId applet, Horizon system)
+ {
+ if (_appletMapping.TryGetValue(applet, out Type appletClass))
+ {
+ return (IApplet)Activator.CreateInstance(appletClass, system);
+ }
+
+ throw new NotImplementedException($"{applet} applet is not implemented.");
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Applets/IApplet.cs b/Ryujinx.HLE/HOS/Applets/IApplet.cs
new file mode 100644
index 00000000..aa248bf5
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Applets/IApplet.cs
@@ -0,0 +1,13 @@
+using Ryujinx.HLE.HOS.Services.Am.AppletAE;
+using System;
+
+namespace Ryujinx.HLE.HOS.Applets
+{
+ interface IApplet
+ {
+ event EventHandler AppletStateChanged;
+
+ ResultCode Start(AppletFifo<byte[]> inData, AppletFifo<byte[]> outData);
+ ResultCode GetResult();
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs b/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs
new file mode 100644
index 00000000..7658c6db
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs
@@ -0,0 +1,55 @@
+using Ryujinx.HLE.HOS.Services.Account.Acc;
+using Ryujinx.HLE.HOS.Services.Am.AppletAE;
+using System;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Applets
+{
+ internal class PlayerSelectApplet : IApplet
+ {
+ private Horizon _system;
+
+ private AppletFifo<byte[]> _inputData;
+ private AppletFifo<byte[]> _outputData;
+
+ public event EventHandler AppletStateChanged;
+
+ public PlayerSelectApplet(Horizon system)
+ {
+ _system = system;
+ }
+
+ public ResultCode Start(AppletFifo<byte[]> inData, AppletFifo<byte[]> outData)
+ {
+ _inputData = inData;
+ _outputData = outData;
+
+ // TODO(jduncanator): Parse PlayerSelectConfig from input data
+ _outputData.Push(BuildResponse());
+
+ AppletStateChanged?.Invoke(this, null);
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode GetResult()
+ {
+ return ResultCode.Success;
+ }
+
+ private byte[] BuildResponse()
+ {
+ UserProfile currentUser = _system.State.Account.LastOpenedUser;
+
+ using (MemoryStream stream = new MemoryStream())
+ using (BinaryWriter writer = new BinaryWriter(stream))
+ {
+ writer.Write((ulong)PlayerSelectResult.Success);
+
+ currentUser.UserId.Write(writer);
+
+ return stream.ToArray();
+ }
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectResult.cs b/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectResult.cs
new file mode 100644
index 00000000..682e094e
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectResult.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Applets
+{
+ enum PlayerSelectResult : ulong
+ {
+ Success = 0,
+ Failure = 2
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs
index 9d8e2a96..8c4d1008 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs
@@ -1,19 +1,37 @@
using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Threading;
-using Ryujinx.HLE.HOS.Services.Am.AppletAE.Storage;
using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
{
class ILibraryAppletAccessor : IpcService
{
+ private IApplet _applet;
+
+ private AppletFifo<byte[]> _inData;
+ private AppletFifo<byte[]> _outData;
+
private KEvent _stateChangedEvent;
- public ILibraryAppletAccessor(Horizon system)
+ public ILibraryAppletAccessor(AppletId appletId, Horizon system)
{
_stateChangedEvent = new KEvent(system);
+
+ _applet = AppletManager.Create(appletId, system);
+ _inData = new AppletFifo<byte[]>();
+ _outData = new AppletFifo<byte[]>();
+
+ _applet.AppletStateChanged += OnAppletStateChanged;
+
+ Logger.PrintInfo(LogClass.ServiceAm, $"Applet '{appletId}' created.");
+ }
+
+ private void OnAppletStateChanged(object sender, EventArgs e)
+ {
+ _stateChangedEvent.ReadableEvent.Signal();
}
[Command(0)]
@@ -29,8 +47,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
- Logger.PrintStub(LogClass.ServiceAm);
-
return ResultCode.Success;
}
@@ -38,25 +54,23 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
// Start()
public ResultCode Start(ServiceCtx context)
{
- Logger.PrintStub(LogClass.ServiceAm);
-
- return ResultCode.Success;
+ return (ResultCode)_applet.Start(_inData, _outData);
}
[Command(30)]
// GetResult()
public ResultCode GetResult(ServiceCtx context)
{
- Logger.PrintStub(LogClass.ServiceAm);
-
- return ResultCode.Success;
+ return (ResultCode)_applet.GetResult();
}
[Command(100)]
// PushInData(object<nn::am::service::IStorage>)
public ResultCode PushInData(ServiceCtx context)
{
- Logger.PrintStub(LogClass.ServiceAm);
+ IStorage data = GetObject<IStorage>(context, 0);
+
+ _inData.Push(data.Data);
return ResultCode.Success;
}
@@ -65,9 +79,11 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
// PopOutData() -> object<nn::am::service::IStorage>
public ResultCode PopOutData(ServiceCtx context)
{
- MakeObject(context, new IStorage(StorageHelper.MakeLaunchParams()));
+ byte[] data = _outData.Pop();
+ MakeObject(context, new IStorage(data));
+
return ResultCode.Success;
}
}
-} \ No newline at end of file
+}
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs
index 8b0b225b..094ed305 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs
@@ -1,3 +1,4 @@
+using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
@@ -10,7 +11,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
// CreateLibraryApplet(u32, u32) -> object<nn::am::service::ILibraryAppletAccessor>
public ResultCode CreateLibraryApplet(ServiceCtx context)
{
- MakeObject(context, new ILibraryAppletAccessor(context.Device.System));
+ AppletId appletId = (AppletId)context.RequestData.ReadInt32();
+ int libraryAppletMode = context.RequestData.ReadInt32();
+
+ MakeObject(context, new ILibraryAppletAccessor(appletId, context.Device.System));
return ResultCode.Success;
}
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AppletFifo.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AppletFifo.cs
new file mode 100644
index 00000000..2391ba5e
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AppletFifo.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
+{
+ internal class AppletFifo<T> : IEnumerable<T>
+ {
+ private ConcurrentQueue<T> _dataQueue;
+
+ public int Count => _dataQueue.Count;
+
+ public AppletFifo()
+ {
+ _dataQueue = new ConcurrentQueue<T>();
+ }
+
+ public void Push(T item)
+ {
+ _dataQueue.Enqueue(item);
+ }
+
+ public T Pop()
+ {
+ if (_dataQueue.TryDequeue(out T result))
+ {
+ return result;
+ }
+
+ throw new InvalidOperationException("FIFO empty.");
+ }
+
+ public bool TryPop(out T result)
+ {
+ return _dataQueue.TryDequeue(out result);
+ }
+
+ public T Peek()
+ {
+ if (_dataQueue.TryPeek(out T result))
+ {
+ return result;
+ }
+
+ throw new InvalidOperationException("FIFO empty.");
+ }
+
+ public bool TryPeek(out T result)
+ {
+ return _dataQueue.TryPeek(out result);
+ }
+
+ public void Clear()
+ {
+ _dataQueue.Clear();
+ }
+
+ public T[] ToArray()
+ {
+ return _dataQueue.ToArray();
+ }
+
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ _dataQueue.CopyTo(array, arrayIndex);
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return _dataQueue.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _dataQueue.GetEnumerator();
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletId.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletId.cs
new file mode 100644
index 00000000..917f6865
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletId.cs
@@ -0,0 +1,27 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
+{
+ enum AppletId
+ {
+ Application = 0x01,
+ OverlayDisplay = 0x02,
+ QLaunch = 0x03,
+ Starter = 0x04,
+ Auth = 0x0A,
+ Cabinet = 0x0B,
+ Controller = 0x0C,
+ DataErase = 0x0D,
+ Error = 0x0E,
+ NetConnect = 0x0F,
+ PlayerSelect = 0x10,
+ SoftwareKeyboard = 0x11,
+ MiiEdit = 0x12,
+ LibAppletWeb = 0x13,
+ LibAppletShop = 0x14,
+ PhotoViewer = 0x15,
+ Settings = 0x16,
+ LibAppletOff = 0x17,
+ LibAppletWhitelisted = 0x18,
+ LibAppletAuth = 0x19,
+ MyPage = 0x1A
+ }
+}