From 7b7dbdcc6ab122faffec487b797fb6cc7a5585c9 Mon Sep 17 00:00:00 2001
From: Tobias <thm.frey@gmail.com>
Date: Sun, 10 Jun 2018 06:36:07 +0200
Subject: [PATCH] Add stubs for Nfp and Acc + SvcGetThreadCoreMask
 implementation (#133)

* Stubs for NFP

* Stubs for ACC

* Implement SvcGetThreadCoreMask

* Fixup

* Fixup 2

* Fixup 3

* Address Cyuubi's feedback
---
 Ryujinx.Core/OsHle/Kernel/SvcHandler.cs       |  1 +
 Ryujinx.Core/OsHle/Kernel/SvcThread.cs        | 22 +++++
 .../Acc/IAccountServiceForApplication.cs      | 18 ++++
 .../OsHle/Services/Nfp/DeviceState.cs         |  7 ++
 Ryujinx.Core/OsHle/Services/Nfp/IUser.cs      | 91 ++++++++++++++++++-
 Ryujinx.Core/OsHle/Services/Nfp/State.cs      |  8 ++
 6 files changed, 145 insertions(+), 2 deletions(-)
 create mode 100644 Ryujinx.Core/OsHle/Services/Nfp/DeviceState.cs
 create mode 100644 Ryujinx.Core/OsHle/Services/Nfp/State.cs

diff --git a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
index 3a9166e4e..70ed38533 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
@@ -47,6 +47,7 @@ namespace Ryujinx.Core.OsHle.Kernel
                 { 0x0b, SvcSleepThread                   },
                 { 0x0c, SvcGetThreadPriority             },
                 { 0x0d, SvcSetThreadPriority             },
+                { 0x0e, SvcGetThreadCoreMask             },
                 { 0x0f, SvcSetThreadCoreMask             },
                 { 0x10, SvcGetCurrentProcessorNumber     },
                 { 0x12, SvcClearEvent                    },
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
index 118417581..c0d1bbd87 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
@@ -139,6 +139,28 @@ namespace Ryujinx.Core.OsHle.Kernel
             }
         }
 
+        private void SvcGetThreadCoreMask(AThreadState ThreadState)
+        {
+            int Handle = (int)ThreadState.X2;
+
+            Ns.Log.PrintDebug(LogClass.KernelSvc, "Handle = " + Handle.ToString("x8"));
+
+            KThread Thread = GetThread(ThreadState.Tpidr, Handle);
+
+            if (Thread != null)
+            {
+                ThreadState.X0 = 0;
+                ThreadState.X1 = (ulong)Thread.IdealCore;
+                ThreadState.X2 = (ulong)Thread.CoreMask;
+            }
+            else
+            {
+                Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
+
+                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+            }
+        }
+        
         private void SvcSetThreadCoreMask(AThreadState ThreadState)
         {
             //FIXME: This is wrong, but the "correct" way to handle
diff --git a/Ryujinx.Core/OsHle/Services/Acc/IAccountServiceForApplication.cs b/Ryujinx.Core/OsHle/Services/Acc/IAccountServiceForApplication.cs
index 84fb62bdf..56b389fc4 100644
--- a/Ryujinx.Core/OsHle/Services/Acc/IAccountServiceForApplication.cs
+++ b/Ryujinx.Core/OsHle/Services/Acc/IAccountServiceForApplication.cs
@@ -15,6 +15,8 @@ namespace Ryujinx.Core.OsHle.Services.Acc
             m_Commands = new Dictionary<int, ServiceProcessRequest>()
             {
                 { 0,   GetUserCount                        },
+                { 1,   GetUserExistence                    },
+                { 2,   ListAllUsers                        },
                 { 3,   ListOpenUsers                       },
                 { 4,   GetLastOpenedUser                   },
                 { 5,   GetProfile                          },
@@ -31,7 +33,23 @@ namespace Ryujinx.Core.OsHle.Services.Acc
 
             return 0;
         }
+        
+        public long GetUserExistence(ServiceCtx Context)
+        {
+            Context.ResponseData.Write(1);
 
+            Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed.");
+
+            return 0;
+        }
+
+        public long ListAllUsers(ServiceCtx Context)
+        {
+            Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed.");
+
+            return 0;
+        }
+        
         public long ListOpenUsers(ServiceCtx Context)
         {
             Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed.");
diff --git a/Ryujinx.Core/OsHle/Services/Nfp/DeviceState.cs b/Ryujinx.Core/OsHle/Services/Nfp/DeviceState.cs
new file mode 100644
index 000000000..f0e748203
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/Nfp/DeviceState.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.Core.OsHle.Services.Nfp
+{
+    enum DeviceState
+    {
+        Initialized = 0
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Nfp/IUser.cs b/Ryujinx.Core/OsHle/Services/Nfp/IUser.cs
index 199d4e151..9f60e974d 100644
--- a/Ryujinx.Core/OsHle/Services/Nfp/IUser.cs
+++ b/Ryujinx.Core/OsHle/Services/Nfp/IUser.cs
@@ -1,5 +1,8 @@
-using Ryujinx.Core.Logging;
+using Ryujinx.Core.Input;
+using Ryujinx.Core.Logging;
+using Ryujinx.Core.OsHle.Handles;
 using Ryujinx.Core.OsHle.Ipc;
+using Ryujinx.Core.OsHle.Services.Hid;
 using System.Collections.Generic;
 
 namespace Ryujinx.Core.OsHle.Services.Nfp
@@ -10,18 +13,102 @@ namespace Ryujinx.Core.OsHle.Services.Nfp
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
 
+        private const HidControllerId NpadId = HidControllerId.CONTROLLER_PLAYER_1;
+        
+        private State State = State.NonInitialized;
+        
+        private DeviceState DeviceState = DeviceState.Initialized;
+        
+        private KEvent ActivateEvent;
+        
+        private KEvent DeactivateEvent;
+        
+        private KEvent AvailabilityChangeEvent;
+        
         public IUser()
         {
             m_Commands = new Dictionary<int, ServiceProcessRequest>()
             {
-                { 0, Initialize }
+                { 0,  Initialize                    },
+                { 17, AttachActivateEvent           },
+                { 18, AttachDeactivateEvent         },
+                { 19, GetState                      },
+                { 20, GetDeviceState                },
+                { 21, GetNpadId                     },
+                { 23, AttachAvailabilityChangeEvent }
             };
+
+            ActivateEvent           = new KEvent();
+            DeactivateEvent         = new KEvent();
+            AvailabilityChangeEvent = new KEvent();
         }
 
         public long Initialize(ServiceCtx Context)
         {
             Context.Ns.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
 
+            State = State.Initialized;
+
+            return 0;
+        }
+
+        public long AttachActivateEvent(ServiceCtx Context)
+        {
+            Context.Ns.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
+
+            int Handle = Context.Process.HandleTable.OpenHandle(ActivateEvent);
+
+            Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);;
+
+            return 0;
+        }
+
+        public long AttachDeactivateEvent(ServiceCtx Context)
+        {
+            Context.Ns.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
+
+            int Handle = Context.Process.HandleTable.OpenHandle(DeactivateEvent);
+
+            Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
+
+            return 0;
+        }
+
+        public long GetState(ServiceCtx Context)
+        {    
+            Context.ResponseData.Write((int)State);
+            
+            Context.Ns.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");          
+
+            return 0;
+        }
+
+        public long GetDeviceState(ServiceCtx Context)
+        {
+            Context.ResponseData.Write((int)DeviceState);
+            
+            Context.Ns.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
+
+            return 0;
+        }
+
+        public long GetNpadId(ServiceCtx Context)
+        {
+            Context.ResponseData.Write((int)NpadId);
+            
+            Context.Ns.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
+
+            return 0;
+        }
+
+        public long AttachAvailabilityChangeEvent(ServiceCtx Context)
+        {
+            Context.Ns.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
+         
+            int Handle = Context.Process.HandleTable.OpenHandle(AvailabilityChangeEvent);
+
+            Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
+
             return 0;
         }
     }
diff --git a/Ryujinx.Core/OsHle/Services/Nfp/State.cs b/Ryujinx.Core/OsHle/Services/Nfp/State.cs
new file mode 100644
index 000000000..c1a07a224
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/Nfp/State.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Core.OsHle.Services.Nfp
+{
+    enum State
+    {
+        NonInitialized = 0,
+        Initialized = 1
+    }
+}
\ No newline at end of file