Browse Source

Implement and stub services required for Mario Kart Live: Home Circuit (#331)

These changes allow Mario Kart Live: Home Circuit (v2.0.0) to boot into
menus. Kart functionality has not been implemented and will not work.

Version 1.0.0 is currently unsupported due to unimplemented ARM
registers. I plan on addressing this issue at a later date.


### Here is a list of the implemented and stubbed services in this PR:
#### Implemented:
Ldn.Lp2p.IServiceCreator: 0 (CreateNetworkService)
Ldn.Lp2p.IServiceCreator: 8 (CreateNetworkServiceMonitor)
Ldn.Lp2p.ISfService: 0 (Initialize)
Ldn.Lp2p.ISfServiceMonitor: 0 (Initialize)
Ldn.Lp2p.ISfServiceMonitor: 256 (AttachNetworkInterfaceStateChangeEvent)
Ldn.Lp2p.ISfServiceMonitor: 328 (AttachJoinEvent)
#### Stubbed:
Ldn.Lp2p.ISfService: 768 (CreateGroup)
Ldn.Lp2p.ISfService: 1536 (SendToOtherGroup)
Ldn.Lp2p.ISfService: 1544 (RecvFromOtherGroup)
Ldn.Lp2p.ISfServiceMonitor: 288 (GetGroupInfo)
Ldn.Lp2p.ISfServiceMonitor: 296 (GetGroupInfo2)
Ldn.Lp2p.ISfServiceMonitor: 312 (GetIpConfig)
Luke Warner 1 year ago
parent
commit
6b5cb151c3

+ 18 - 0
src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/IServiceCreator.cs

@@ -5,5 +5,23 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
     class IServiceCreator : IpcService
     {
         public IServiceCreator(ServiceCtx context) { }
+
+        [CommandCmif(0)]
+        // CreateNetworkService(pid, u64, u32) -> object<nn::ldn::detail::ISfService>
+        public ResultCode CreateNetworkService(ServiceCtx context)
+        {
+            MakeObject(context, new ISfService(context));
+
+            return ResultCode.Success;
+        }
+
+        [CommandCmif(8)]
+        // CreateNetworkServiceMonitor(pid, u64) -> object<nn::ldn::detail::ISfServiceMonitor>
+        public ResultCode CreateNetworkServiceMonitor(ServiceCtx context)
+        {
+            MakeObject(context, new ISfServiceMonitor(context));
+
+            return ResultCode.Success;
+        }
     }
 }

+ 45 - 0
src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfService.cs

@@ -0,0 +1,45 @@
+using Ryujinx.Common.Logging;
+
+namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
+{
+    class ISfService : IpcService
+    {
+        public ISfService(ServiceCtx context) { }
+
+        [CommandCmif(0)]
+        // Initialize()
+        public ResultCode Initialize(ServiceCtx context)
+        {
+            context.ResponseData.Write(0);
+
+            return ResultCode.Success;
+        }
+
+        [CommandCmif(768)]
+        // CreateGroup(buffer<nn::lp2p::GroupInfo, 0x31)
+        public ResultCode CreateGroup(ServiceCtx context)
+        {
+            Logger.Stub?.PrintStub(LogClass.ServiceLdn);
+
+            return ResultCode.Success;
+        }
+
+        [CommandCmif(1536)]
+        // SendToOtherGroup(nn::lp2p::MacAddress, nn::lp2p::GroupId, s16, s16, u32, buffer<unknown, 0x21>)
+        public ResultCode SendToOtherGroup(ServiceCtx context)
+        {
+            Logger.Stub?.PrintStub(LogClass.ServiceLdn);
+
+            return ResultCode.Success;
+        }
+
+        [CommandCmif(1544)]
+        // RecvFromOtherGroup(u32, buffer<unknown, 0x22>) -> (nn::lp2p::MacAddress, u16, s16, u32, s32)
+        public ResultCode RecvFromOtherGroup(ServiceCtx context)
+        {
+            Logger.Stub?.PrintStub(LogClass.ServiceLdn);
+
+            return ResultCode.Success;
+        }
+    }
+}

+ 86 - 0
src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfServiceMonitor.cs

@@ -0,0 +1,86 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.Horizon.Common;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
+{
+    class ISfServiceMonitor : IpcService
+    {
+        private readonly KEvent _stateChangeEvent;
+        private readonly KEvent _jointEvent;
+        private int _stateChangeEventHandle = 0;
+        private int _jointEventHandle = 0;
+
+        public ISfServiceMonitor(ServiceCtx context)
+        {
+            _stateChangeEvent = new KEvent(context.Device.System.KernelContext);
+            _jointEvent = new KEvent(context.Device.System.KernelContext);
+        }
+
+        [CommandCmif(0)]
+        // Initialize()
+        public ResultCode Initialize(ServiceCtx context)
+        {
+            context.ResponseData.Write(0);
+
+            return ResultCode.Success;
+        }
+
+        [CommandCmif(256)]
+        // AttachNetworkInterfaceStateChangeEvent() -> handle<copy>
+        public ResultCode AttachNetworkInterfaceStateChangeEvent(ServiceCtx context)
+        {
+            if (context.Process.HandleTable.GenerateHandle(_stateChangeEvent.ReadableEvent, out _stateChangeEventHandle) != Result.Success)
+            {
+                throw new InvalidOperationException("Out of handles!");
+            }
+
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_stateChangeEventHandle);
+
+            return ResultCode.Success;
+        }
+
+        [CommandCmif(288)]
+        // GetGroupInfo(buffer<nn::lp2p::GroupInfo, 0x32>)
+        public ResultCode GetGroupInfo(ServiceCtx context)
+        {
+            Logger.Stub?.PrintStub(LogClass.ServiceLdn);
+
+            return ResultCode.Success;
+        }
+
+        [CommandCmif(296)]
+        // GetGroupInfo2(buffer<nn::lp2p::GroupInfo, 0x32>, buffer<nn::lp2p::GroupInfo, 0x31>)
+        public ResultCode GetGroupInfo2(ServiceCtx context)
+        {
+            Logger.Stub?.PrintStub(LogClass.ServiceLdn);
+
+            return ResultCode.Success;
+        }
+
+        [CommandCmif(312)]
+        // GetIpConfig(buffer<unknown<0x100>, 0x1a>)
+        public ResultCode GetIpConfig(ServiceCtx context)
+        {
+            Logger.Stub?.PrintStub(LogClass.ServiceLdn);
+
+            return ResultCode.Success;
+        }
+
+        [CommandCmif(328)]
+        // AttachNetworkInterfaceStateChangeEvent() -> handle<copy>
+        public ResultCode AttachJoinEvent(ServiceCtx context)
+        {
+            if (context.Process.HandleTable.GenerateHandle(_jointEvent.ReadableEvent, out _jointEventHandle) != Result.Success)
+            {
+                throw new InvalidOperationException("Out of handles!");
+            }
+
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_jointEventHandle);
+
+            return ResultCode.Success;
+        }
+    }
+}