From fdda67d4762c6a283ff0f1f76c02a02b21d9b119 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sun, 29 Jul 2018 01:36:29 -0300
Subject: [PATCH] Some fix to IRequest on NIFM, support sending objects to
 services (#294)

---
 Ryujinx.HLE/OsHle/Ipc/IpcHandleDesc.cs      | 14 ++++----
 Ryujinx.HLE/OsHle/Ipc/IpcMessage.cs         |  4 +--
 Ryujinx.HLE/OsHle/Services/IpcService.cs    | 39 ++++++++++++++++++---
 Ryujinx.HLE/OsHle/Services/Nifm/IRequest.cs | 18 +++++-----
 4 files changed, 54 insertions(+), 21 deletions(-)

diff --git a/Ryujinx.HLE/OsHle/Ipc/IpcHandleDesc.cs b/Ryujinx.HLE/OsHle/Ipc/IpcHandleDesc.cs
index 953cac7643..609cc6e05f 100644
--- a/Ryujinx.HLE/OsHle/Ipc/IpcHandleDesc.cs
+++ b/Ryujinx.HLE/OsHle/Ipc/IpcHandleDesc.cs
@@ -47,13 +47,15 @@ namespace Ryujinx.HLE.OsHle.Ipc
             HasPId = true;
         }
 
-        public static IpcHandleDesc MakeCopy(int Handle) => new IpcHandleDesc(
-                new int[] { Handle },
-                new int[0]);
+        public static IpcHandleDesc MakeCopy(params int[] Handles)
+        {
+            return new IpcHandleDesc(Handles, new int[0]);
+        }
 
-        public static IpcHandleDesc MakeMove(int Handle) => new IpcHandleDesc(
-                new int[0],
-                new int[] { Handle });
+        public static IpcHandleDesc MakeMove(params int[] Handles)
+        {
+            return new IpcHandleDesc(new int[0], Handles);
+        }
 
         public byte[] GetBytes()
         {
diff --git a/Ryujinx.HLE/OsHle/Ipc/IpcMessage.cs b/Ryujinx.HLE/OsHle/Ipc/IpcMessage.cs
index 4e648aec97..0a64a16426 100644
--- a/Ryujinx.HLE/OsHle/Ipc/IpcMessage.cs
+++ b/Ryujinx.HLE/OsHle/Ipc/IpcMessage.cs
@@ -15,7 +15,7 @@ namespace Ryujinx.HLE.OsHle.Ipc
         public List<IpcBuffDesc>         ExchangeBuff { get; private set; }
         public List<IpcRecvListBuffDesc> RecvListBuff { get; private set; }
 
-        public List<int> ResponseObjIds { get; private set; }
+        public List<int> ObjectIds { get; private set; }
 
         public byte[] RawData { get; set; }
 
@@ -27,7 +27,7 @@ namespace Ryujinx.HLE.OsHle.Ipc
             ExchangeBuff = new List<IpcBuffDesc>();
             RecvListBuff = new List<IpcRecvListBuffDesc>();
 
-            ResponseObjIds = new List<int>();
+            ObjectIds = new List<int>();
         }
 
         public IpcMessage(byte[] Data, long CmdPtr) : this()
diff --git a/Ryujinx.HLE/OsHle/Services/IpcService.cs b/Ryujinx.HLE/OsHle/Services/IpcService.cs
index 25fd56fec0..3c1a136f1b 100644
--- a/Ryujinx.HLE/OsHle/Services/IpcService.cs
+++ b/Ryujinx.HLE/OsHle/Services/IpcService.cs
@@ -50,9 +50,18 @@ namespace Ryujinx.HLE.OsHle.Services
                 int DomainWord0 = Context.RequestData.ReadInt32();
                 int DomainObjId = Context.RequestData.ReadInt32();
 
-                long Padding = Context.RequestData.ReadInt64();
+                int DomainCmd       = (DomainWord0 >> 0)  & 0xff;
+                int InputObjCount   = (DomainWord0 >> 8)  & 0xff;
+                int DataPayloadSize = (DomainWord0 >> 16) & 0xffff;
 
-                int DomainCmd = DomainWord0 & 0xff;
+                Context.RequestData.BaseStream.Seek(0x10 + DataPayloadSize, SeekOrigin.Begin);
+
+                for (int Index = 0; Index < InputObjCount; Index++)
+                {
+                    Context.Request.ObjectIds.Add(Context.RequestData.ReadInt32());
+                }
+
+                Context.RequestData.BaseStream.Seek(0x10, SeekOrigin.Begin);
 
                 if (DomainCmd == 1)
                 {
@@ -88,14 +97,14 @@ namespace Ryujinx.HLE.OsHle.Services
 
                 if (IsDomain)
                 {
-                    foreach (int Id in Context.Response.ResponseObjIds)
+                    foreach (int Id in Context.Response.ObjectIds)
                     {
                         Context.ResponseData.Write(Id);
                     }
 
                     Context.ResponseData.BaseStream.Seek(0, SeekOrigin.Begin);
 
-                    Context.ResponseData.Write(Context.Response.ResponseObjIds.Count);
+                    Context.ResponseData.Write(Context.Response.ObjectIds.Count);
                 }
 
                 Context.ResponseData.BaseStream.Seek(IsDomain ? 0x10 : 0, SeekOrigin.Begin);
@@ -117,7 +126,7 @@ namespace Ryujinx.HLE.OsHle.Services
 
             if (Service.IsDomain)
             {
-                Context.Response.ResponseObjIds.Add(Service.Add(Obj));
+                Context.Response.ObjectIds.Add(Service.Add(Obj));
             }
             else
             {
@@ -129,6 +138,26 @@ namespace Ryujinx.HLE.OsHle.Services
             }
         }
 
+        protected static T GetObject<T>(ServiceCtx Context, int Index) where T : IpcService
+        {
+            IpcService Service = Context.Session.Service;
+
+            if (!Service.IsDomain)
+            {
+                int Handle = Context.Request.HandleDesc.ToMove[Index];
+
+                KSession Session = Context.Process.HandleTable.GetData<KSession>(Handle);
+
+                return Session?.Service is T ? (T)Session.Service : null;
+            }
+
+            int ObjId = Context.Request.ObjectIds[Index];
+
+            IIpcService Obj = Service.GetObject(ObjId);
+
+            return Obj is T ? (T)Obj : null;
+        }
+
         private int Add(IIpcService Obj)
         {
             return DomainObjects.Add(Obj);
diff --git a/Ryujinx.HLE/OsHle/Services/Nifm/IRequest.cs b/Ryujinx.HLE/OsHle/Services/Nifm/IRequest.cs
index c8c679c4c5..2056187ddd 100644
--- a/Ryujinx.HLE/OsHle/Services/Nifm/IRequest.cs
+++ b/Ryujinx.HLE/OsHle/Services/Nifm/IRequest.cs
@@ -12,7 +12,8 @@ namespace Ryujinx.HLE.OsHle.Services.Nifm
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
 
-        private KEvent Event;
+        private KEvent Event0;
+        private KEvent Event1;
 
         public IRequest()
         {
@@ -26,12 +27,13 @@ namespace Ryujinx.HLE.OsHle.Services.Nifm
                 { 11, SetConnectionConfirmationOption }
             };
 
-            Event = new KEvent();
+            Event0 = new KEvent();
+            Event1 = new KEvent();
         }
 
         public long GetRequestState(ServiceCtx Context)
         {
-            Context.ResponseData.Write(0);
+            Context.ResponseData.Write(1);
 
             Context.Ns.Log.PrintStub(LogClass.ServiceNifm, "Stubbed.");
 
@@ -45,13 +47,12 @@ namespace Ryujinx.HLE.OsHle.Services.Nifm
             return 0;
         }
 
-        //GetSystemEventReadableHandles() -> (KObject, KObject)
         public long GetSystemEventReadableHandles(ServiceCtx Context)
         {
-            //FIXME: Is this supposed to return 2 events?
-            int Handle = Context.Process.HandleTable.OpenHandle(Event);
+            int Handle0 = Context.Process.HandleTable.OpenHandle(Event0);
+            int Handle1 = Context.Process.HandleTable.OpenHandle(Event1);
 
-            Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
+            Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle0, Handle1);
 
             return 0;
         }
@@ -86,7 +87,8 @@ namespace Ryujinx.HLE.OsHle.Services.Nifm
         {
             if (Disposing)
             {
-                Event.Dispose();
+                Event0.Dispose();
+                Event1.Dispose();
             }
         }
     }