Implement Player Select applet

This commit is contained in:
jduncanator 2019-10-31 15:38:08 +11:00
parent 59f48e3710
commit f59379df7b
7 changed files with 215 additions and 12 deletions

View file

@ -0,0 +1,27 @@
namespace Ryujinx.HLE.HOS.Applets
{
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
}
}

View file

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Ryujinx.HLE.HOS.Applets
{
static class AppletManager
{
private static Dictionary<AppletId, Type> _appletMapping;
static AppletManager()
{
_appletMapping = new Dictionary<AppletId, Type> {
{ AppletId.PlayerSelect, typeof(PlayerSelect) }
};
}
public static IApplet Create(AppletId applet, Horizon system)
{
if(_appletMapping.TryGetValue(applet, out Type appletClass))
{
return (IApplet)Activator.CreateInstance(appletClass, system);
}
return new StubApplet();
}
}
}

View file

@ -0,0 +1,17 @@
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
using System;
using System.Collections.Generic;
using System.Text;
namespace Ryujinx.HLE.HOS.Applets
{
interface IApplet
{
event EventHandler AppletStateChanged;
ResultCode Start();
ResultCode GetResult();
ResultCode PushInData(IStorage data);
ResultCode PopOutData(out IStorage data);
}
}

View file

@ -0,0 +1,76 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Ryujinx.HLE.HOS.Applets
{
internal class PlayerSelect : IApplet
{
private Horizon _system;
private Stack<IStorage> _inputStack;
private Stack<IStorage> _outputStack;
public event EventHandler AppletStateChanged;
public PlayerSelect(Horizon system)
{
_inputStack = new Stack<IStorage>();
_outputStack = new Stack<IStorage>();
}
public ResultCode Start()
{
_outputStack.Push(new IStorage(BuildResponse()));
AppletStateChanged?.Invoke(this, null);
return ResultCode.Success;
}
public ResultCode GetResult()
{
return ResultCode.Success;
}
public ResultCode PushInData(IStorage data)
{
_inputStack.Push(data);
return ResultCode.Success;
}
public ResultCode PopOutData(out IStorage data)
{
if (_outputStack.Count > 0)
{
data = _outputStack.Pop();
}
else
{
data = null;
}
return ResultCode.Success;
}
private byte[] BuildResponse()
{
var currentUser = _system.State.Account.LastOpenedUser;
using (var ms = new MemoryStream())
{
var writer = new BinaryWriter(ms);
// Result (0 = Success, 2 = Failure)
writer.Write(0UL);
// UserID Low (long) High (long)
currentUser.UserId.Write(writer);
return ms.ToArray();
}
}
}
}

View file

@ -0,0 +1,41 @@
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

@ -1,4 +1,5 @@
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;
@ -9,11 +10,21 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
{
class ILibraryAppletAccessor : IpcService
{
private IApplet _applet;
private KEvent _stateChangedEvent;
public ILibraryAppletAccessor(Horizon system)
public ILibraryAppletAccessor(AppletId appletId, Horizon system)
{
_stateChangedEvent = new KEvent(system);
_applet = AppletManager.Create(appletId, system);
_applet.AppletStateChanged += OnAppletStateChanged;
}
private void OnAppletStateChanged(object sender, EventArgs e)
{
_stateChangedEvent.ReadableEvent.Signal();
}
[Command(0)]
@ -29,8 +40,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
Logger.PrintStub(LogClass.ServiceAm);
return ResultCode.Success;
}
@ -38,18 +47,14 @@ 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();
}
[Command(30)]
// GetResult()
public ResultCode GetResult(ServiceCtx context)
{
Logger.PrintStub(LogClass.ServiceAm);
return ResultCode.Success;
return (ResultCode)_applet.GetResult();
}
[Command(100)]
@ -65,9 +70,14 @@ 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()));
var result = _applet.PopOutData(out IStorage storage);
return ResultCode.Success;
if(storage != null)
{
MakeObject(context, storage);
}
return (ResultCode)result;
}
}
}

View file

@ -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));
int appletId = context.RequestData.ReadInt32();
int libraryAppletMode = context.RequestData.ReadInt32();
MakeObject(context, new ILibraryAppletAccessor((AppletId)appletId, context.Device.System));
return ResultCode.Success;
}