From c7a385a6aac4dfd788afef9ecfee02b95a08514e Mon Sep 17 00:00:00 2001 From: Babib3l Date: Mon, 18 May 2026 20:43:59 +0200 Subject: [PATCH] make mii sharing not crash - ldn not functional yet --- .../HOS/Services/Ldn/ISystemServiceCreator.cs | 22 ++++++++- .../ISystemLocalCommunicationService.cs | 45 +++++++++++++++++++ .../IUserLocalCommunicationService.cs | 34 ++++++++++---- .../Nifm/StaticService/IGeneralService.cs | 22 +++++++++ 4 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/ISystemLocalCommunicationService.cs diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/ISystemServiceCreator.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/ISystemServiceCreator.cs index 535013b0b..36e9468c5 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/ISystemServiceCreator.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/ISystemServiceCreator.cs @@ -1,8 +1,28 @@ +using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator; + namespace Ryujinx.HLE.HOS.Services.Ldn { [Service("ldn:s")] class ISystemServiceCreator : IpcService { - public ISystemServiceCreator(ServiceCtx context) { } + public ISystemServiceCreator(ServiceCtx context) : base(context.Device.System.LdnServer) { } + + [CommandCmif(0)] + // CreateSystemLocalCommunicationService() -> object + public ResultCode CreateSystemLocalCommunicationService(ServiceCtx context) + { + MakeObject(context, new ISystemLocalCommunicationService(context)); + + return ResultCode.Success; + } + + [CommandCmif(1)] // 18.0.0+ + // CreateClientProcessMonitor() -> object + public ResultCode CreateClientProcessMonitor(ServiceCtx context) + { + MakeObject(context, new IClientProcessMonitor(context)); + + return ResultCode.Success; + } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/ISystemLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/ISystemLocalCommunicationService.cs new file mode 100644 index 000000000..1e6ad72f5 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/ISystemLocalCommunicationService.cs @@ -0,0 +1,45 @@ +using Ryujinx.Common.Logging; + +namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator +{ + class ISystemLocalCommunicationService : IUserLocalCommunicationService + { + private const int NifmRequestId = 90; + + public ISystemLocalCommunicationService(ServiceCtx context) : base(context) { } + + // NOTE: This overrides the parent's Initialize method with the same command ID (402) + // The CommandCmif attribute is inherited from the parent class + public override ResultCode Initialize(ServiceCtx context) + { + uint operationMode = context.RequestData.ReadUInt32(); + + Logger.Stub?.PrintStub(LogClass.ServiceLdn, new { operationMode }); + + return ResultCode.Success; + } + + [CommandCmif(403)] + // InitializeWithVersion(s32 version, pid) + public ResultCode InitializeWithVersion(ServiceCtx context) + { + int version = context.RequestData.ReadInt32(); + + Logger.Stub?.PrintStub(LogClass.ServiceLdn, new { version }); + + return InitializeImpl(context, context.Process.Pid, NifmRequestId); + } + + [CommandCmif(404)] // 11.0.0+ + // InitializeWithPriority(s32 version, s32 priority, pid) + public ResultCode InitializeWithPriority(ServiceCtx context) + { + int version = context.RequestData.ReadInt32(); + int priority = context.RequestData.ReadInt32(); + + Logger.Stub?.PrintStub(LogClass.ServiceLdn, new { version, priority }); + + return InitializeImpl(context, context.Process.Pid, NifmRequestId); + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs index 2f764e99f..f062020f1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs @@ -21,9 +21,18 @@ using System.Runtime.InteropServices; namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator { - class IUserLocalCommunicationService : IpcService, IDisposable + class IUserLocalCommunicationService : IpcService { public INetworkClient NetworkClient { get; private set; } + private readonly ServiceCtx _context; + + public IUserLocalCommunicationService(ServiceCtx context) : base(context.Device.System.LdnServer) + { + _context = context; + _stateChangeEvent = new KEvent(context.Device.System.KernelContext); + _state = NetworkState.None; + _disconnectReason = DisconnectReason.None; + } private const int NifmRequestID = 90; private const string DefaultIPAddress = "127.0.0.1"; @@ -40,13 +49,6 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator private AccessPoint _accessPoint; private Station _station; - public IUserLocalCommunicationService(ServiceCtx context) - { - _stateChangeEvent = new KEvent(context.Device.System.KernelContext); - _state = NetworkState.None; - _disconnectReason = DisconnectReason.None; - } - private ushort CheckDevelopmentChannel(ushort channel) { return (ushort)(!IsDevelopment ? 0 : channel); @@ -457,6 +459,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, $"ScanImpl: resultCode = {resultCode}"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"ScanImpl: resultCode={resultCode}, state={_state}, private={isPrivate}"); return resultCode; } @@ -482,6 +485,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, $"ScanInternal: availableGames = {availableGames}"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"ScanInternal: availableGames={availableGames.Length}, channel={channel}"); return ResultCode.Success; } @@ -534,12 +538,14 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator if (_nifmResultCode != ResultCode.Success) { Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, $"OpenAccessPoint: _nifmResultCode = {_nifmResultCode}"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"OpenAccessPoint: nifmResultCode={_nifmResultCode}, state={_state}"); return _nifmResultCode; } if (_state != NetworkState.Initialized) { Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, "OpenAccessPoint: Invalid state!"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"OpenAccessPoint: invalid state={_state}"); return ResultCode.InvalidState; } @@ -551,6 +557,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator // NOTE: Calls nifm service and return related result codes. // Since we use our own implementation we can return ResultCode.Success. + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"OpenAccessPoint: state={_state}"); return ResultCode.Success; } @@ -628,6 +635,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator if (_nifmResultCode != ResultCode.Success) { Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, $"CreateNetworkImpl: _nifmResultCode = {_nifmResultCode}"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"CreateNetworkImpl: nifmResultCode={_nifmResultCode}, state={_state}, private={isPrivate}"); return _nifmResultCode; } @@ -672,6 +680,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator else { Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, "CreateNetworkImpl: Invalid state!"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"CreateNetworkImpl: invalid state={_state}, private={isPrivate}"); return ResultCode.InvalidState; } } @@ -679,6 +688,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } } + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"CreateNetworkImpl: invalid argument, state={_state}, private={isPrivate}"); return ResultCode.InvalidArgument; } @@ -845,12 +855,14 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator if (_nifmResultCode != ResultCode.Success) { Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, $"OpenStation: _nifmResultCode = {_nifmResultCode}"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"OpenStation: nifmResultCode={_nifmResultCode}, state={_state}"); return _nifmResultCode; } if (_state != NetworkState.Initialized) { Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, "OpenStation: Invalid state!"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"OpenStation: invalid state={_state}"); return ResultCode.InvalidState; } @@ -865,6 +877,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator // Since we use our own implementation we can return ResultCode.Success. Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, $"OpenStation: _station = {_station}"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"OpenStation: state={_state}"); return ResultCode.Success; } @@ -963,6 +976,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator if (_nifmResultCode != ResultCode.Success) { Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, $"ConnectImpl: _nifmResultCode = {_nifmResultCode}"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"ConnectImpl: nifmResultCode={_nifmResultCode}, state={_state}, private={isPrivate}"); return _nifmResultCode; } @@ -1008,6 +1022,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, $"ConnectImpl: resultCode = {resultCode}"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"ConnectImpl: resultCode={resultCode}, state={_state}, private={isPrivate}"); return resultCode; } @@ -1148,7 +1163,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator [CommandCmif(402)] // 7.0.0+ // Initialize(u64 ip_addresses, pid) - public ResultCode Initialize(ServiceCtx context) + public virtual ResultCode Initialize(ServiceCtx context) { _ = new IPAddress(context.RequestData.ReadUInt32()); _ = new IPAddress(context.RequestData.ReadUInt32()); @@ -1225,6 +1240,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } Logger.NetLog?.PrintMsg(LogClass.ServiceLdn, $"InitializeImpl: resultCode = {resultCode}"); + Logger.Info?.PrintMsg(LogClass.ServiceLdn, $"InitializeImpl: resultCode={resultCode}, state={_state}, nifmRequestId={nifmRequestId}"); return resultCode; } diff --git a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs index dd4efce6e..4f3067c4b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs @@ -129,6 +129,17 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService return ResultCode.Success; } + [CommandCmif(17)] + // IsWirelessCommunicationEnabled() -> bool + public ResultCode IsWirelessCommunicationEnabled(ServiceCtx context) + { + context.ResponseData.Write(true); + + Logger.Stub?.PrintStub(LogClass.ServiceNifm); + + return ResultCode.Success; + } + [CommandCmif(18)] // GetInternetConnectionStatus() -> nn::nifm::detail::sf::InternetConnectionStatus public ResultCode GetInternetConnectionStatus(ServiceCtx context) @@ -166,6 +177,17 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService return ResultCode.Success; } + [CommandCmif(22)] + // IsAnyForegroundRequestAccepted() -> bool + public ResultCode IsAnyForegroundRequestAccepted(ServiceCtx context) + { + context.ResponseData.Write(false); + + Logger.Stub?.PrintStub(LogClass.ServiceNifm); + + return ResultCode.Success; + } + private (IPInterfaceProperties, UnicastIPAddressInformation) GetLocalInterface(ServiceCtx context) { if (!NetworkInterface.GetIsNetworkAvailable())