diff --git a/Ryujinx.HLE/HOS/Applets/AppletId.cs b/Ryujinx.HLE/HOS/Applets/AppletId.cs new file mode 100644 index 0000000000..153472e881 --- /dev/null +++ b/Ryujinx.HLE/HOS/Applets/AppletId.cs @@ -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 + } +} diff --git a/Ryujinx.HLE/HOS/Applets/AppletManager.cs b/Ryujinx.HLE/HOS/Applets/AppletManager.cs new file mode 100644 index 0000000000..2dcabcb7cd --- /dev/null +++ b/Ryujinx.HLE/HOS/Applets/AppletManager.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ryujinx.HLE.HOS.Applets +{ + static class AppletManager + { + private static Dictionary _appletMapping; + + static AppletManager() + { + _appletMapping = new Dictionary { + { 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(); + } + } +} diff --git a/Ryujinx.HLE/HOS/Applets/IApplet.cs b/Ryujinx.HLE/HOS/Applets/IApplet.cs new file mode 100644 index 0000000000..946dcecdf2 --- /dev/null +++ b/Ryujinx.HLE/HOS/Applets/IApplet.cs @@ -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); + } +} diff --git a/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelect.cs b/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelect.cs new file mode 100644 index 0000000000..06bc81b0fe --- /dev/null +++ b/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelect.cs @@ -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 _inputStack; + private Stack _outputStack; + + public event EventHandler AppletStateChanged; + + public PlayerSelect(Horizon system) + { + _inputStack = new Stack(); + _outputStack = new Stack(); + } + + 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(); + } + } + } +} diff --git a/Ryujinx.HLE/HOS/Applets/StubApplet.cs b/Ryujinx.HLE/HOS/Applets/StubApplet.cs new file mode 100644 index 0000000000..03e22644f4 --- /dev/null +++ b/Ryujinx.HLE/HOS/Applets/StubApplet.cs @@ -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; + } + } +} 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 9d8e2a96f0..fdd70ce4f7 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs @@ -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 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; } } } \ 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 8b0b225bd9..1fbad89814 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 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; }