Implement an applet FIFO

This commit is contained in:
jduncanator 2019-11-04 15:16:46 +11:00
parent 653f15af82
commit 67c630c066
5 changed files with 112 additions and 90 deletions

View file

@ -0,0 +1,79 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Applets
{
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();
}
}
}

View file

@ -7,9 +7,7 @@ namespace Ryujinx.HLE.HOS.Applets
{
event EventHandler AppletStateChanged;
ResultCode Start();
ResultCode Start(AppletFifo<byte[]> inData, AppletFifo<byte[]> outData);
ResultCode GetResult();
ResultCode PushInData(IStorage data);
ResultCode PopOutData(out IStorage data);
}
}

View file

@ -1,29 +1,30 @@
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
using System;
using System.Collections.Generic;
using System.IO;
namespace Ryujinx.HLE.HOS.Applets
{
internal class PlayerSelect : IApplet
{
private Horizon _system;
private Queue<IStorage> _inputQueue;
private Queue<IStorage> _outputQueue;
private Horizon _system;
private AppletFifo<byte[]> _inputData;
private AppletFifo<byte[]> _outputData;
public event EventHandler AppletStateChanged;
public PlayerSelect(Horizon system)
{
_system = system;
_inputQueue = new Queue<IStorage>();
_outputQueue = new Queue<IStorage>();
_system = system;
}
public ResultCode Start()
public ResultCode Start(AppletFifo<byte[]> inData, AppletFifo<byte[]> outData)
{
_outputQueue.Enqueue(new IStorage(BuildResponse()));
_inputData = inData;
_outputData = outData;
// TODO(jduncanator): Parse PlayerSelectConfig from input data
_outputData.Push(BuildResponse());
AppletStateChanged?.Invoke(this, null);
@ -35,40 +36,18 @@ namespace Ryujinx.HLE.HOS.Applets
return ResultCode.Success;
}
public ResultCode PushInData(IStorage data)
{
_inputQueue.Enqueue(data);
return ResultCode.Success;
}
public ResultCode PopOutData(out IStorage data)
{
if (_outputQueue.Count > 0)
{
data = _outputQueue.Dequeue();
}
else
{
data = null;
}
return ResultCode.Success;
}
private byte[] BuildResponse()
{
UserProfile currentUser = _system.State.Account.LastOpenedUser;
using (MemoryStream ms = new MemoryStream())
using (MemoryStream stream = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(stream))
{
BinaryWriter writer = new BinaryWriter(ms);
writer.Write((ulong)PlayerSelectResult.Success);
// UserID Low (long) High (long)
currentUser.UserId.Write(writer);
return ms.ToArray();
return stream.ToArray();
}
}
}

View file

@ -1,41 +0,0 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
using System;
namespace Ryujinx.HLE.HOS.Applets
{
internal class StubApplet : IApplet
{
public event EventHandler AppletStateChanged;
public ResultCode Start()
{
Logger.PrintStub(LogClass.ServiceAm);
return ResultCode.Success;
}
public ResultCode PushInData(IStorage data)
{
Logger.PrintStub(LogClass.ServiceAm);
return ResultCode.Success;
}
public ResultCode PopOutData(out IStorage data)
{
Logger.PrintStub(LogClass.ServiceAm);
data = null;
return ResultCode.Success;
}
public ResultCode GetResult()
{
Logger.PrintStub(LogClass.ServiceAm);
return ResultCode.Success;
}
}
}

View file

@ -11,13 +11,19 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
{
private IApplet _applet;
private AppletFifo<byte[]> _inData;
private AppletFifo<byte[]> _outData;
private KEvent _stateChangedEvent;
public ILibraryAppletAccessor(AppletId appletId, Horizon system)
{
_stateChangedEvent = new KEvent(system);
_applet = AppletManager.Create(appletId, system);
_applet = AppletManager.Create(appletId, system);
_inData = new AppletFifo<byte[]>();
_outData = new AppletFifo<byte[]>();
_applet.AppletStateChanged += OnAppletStateChanged;
}
@ -46,7 +52,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
// Start()
public ResultCode Start(ServiceCtx context)
{
return (ResultCode)_applet.Start();
return (ResultCode)_applet.Start(_inData, _outData);
}
[Command(30)]
@ -60,7 +66,11 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
// PushInData(object<nn::am::service::IStorage>)
public ResultCode PushInData(ServiceCtx context)
{
Logger.PrintStub(LogClass.ServiceAm);
var data = GetObject<IStorage>(context, 0);
Logger.PrintWarning(LogClass.ServiceAm, $"PushInData size: {data.Data.Length} bytes");
_inData.Push(data.Data);
return ResultCode.Success;
}
@ -69,14 +79,11 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
// PopOutData() -> object<nn::am::service::IStorage>
public ResultCode PopOutData(ServiceCtx context)
{
ResultCode result = (ResultCode)_applet.PopOutData(out IStorage storage);
byte[] data = _outData.Pop();
if (result == ResultCode.Success && storage != null)
{
MakeObject(context, storage);
}
MakeObject(context, new IStorage(data));
return result;
return ResultCode.Success;
}
}
}
}