Skip to content

Commit

Permalink
Implement and stub services required for Mario Kart Live: Home Circuit (
Browse files Browse the repository at this point in the history
#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)
  • Loading branch information
LukeWarnut authored Nov 30, 2024
1 parent 3680df6 commit 6b5cb15
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/IServiceCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 45 additions & 0 deletions src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfService.cs
Original file line number Diff line number Diff line change
@@ -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 changes: 86 additions & 0 deletions src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfServiceMonitor.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}

0 comments on commit 6b5cb15

Please sign in to comment.