Move solution and projects to src

This commit is contained in:
TSR Berry
2023-04-08 01:22:00 +02:00
committed by Mary
parent cd124bda58
commit cee7121058
3466 changed files with 55 additions and 55 deletions

View File

@@ -0,0 +1,30 @@
using Ryujinx.HLE.HOS.Services.Nifm.StaticService;
namespace Ryujinx.HLE.HOS.Services.Nifm
{
[Service("nifm:a")] // Max sessions: 2
[Service("nifm:s")] // Max sessions: 16
[Service("nifm:u")] // Max sessions: 5
class IStaticService : IpcService
{
public IStaticService(ServiceCtx context) { }
[CommandCmif(4)]
// CreateGeneralServiceOld() -> object<nn::nifm::detail::IGeneralService>
public ResultCode CreateGeneralServiceOld(ServiceCtx context)
{
MakeObject(context, new IGeneralService());
return ResultCode.Success;
}
[CommandCmif(5)] // 3.0.0+
// CreateGeneralService(u64, pid) -> object<nn::nifm::detail::IGeneralService>
public ResultCode CreateGeneralService(ServiceCtx context)
{
MakeObject(context, new IGeneralService());
return ResultCode.Success;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace Ryujinx.HLE.HOS.Services.Nifm
{
enum ResultCode
{
ModuleId = 110,
ErrorCodeShift = 9,
Success = 0,
Unknown112 = (112 << ErrorCodeShift) | ModuleId, // IRequest::GetResult
Unknown180 = (180 << ErrorCodeShift) | ModuleId, // IRequest::GetAppletInfo
NoInternetConnection = (300 << ErrorCodeShift) | ModuleId,
ObjectIsNull = (350 << ErrorCodeShift) | ModuleId
}
}

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService
{
static class GeneralServiceManager
{
private static List<GeneralServiceDetail> _generalServices = new List<GeneralServiceDetail>();
public static int Count
{
get => _generalServices.Count;
}
public static void Add(GeneralServiceDetail generalServiceDetail)
{
_generalServices.Add(generalServiceDetail);
}
public static void Remove(int index)
{
_generalServices.RemoveAt(index);
}
public static GeneralServiceDetail Get(int clientId)
{
return _generalServices.First(item => item.ClientId == clientId);
}
}
}

View File

@@ -0,0 +1,8 @@
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService
{
class GeneralServiceDetail
{
public int ClientId;
public bool IsAnyInternetRequestAccepted;
}
}

View File

@@ -0,0 +1,203 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService;
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types;
using System;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
{
class IGeneralService : DisposableIpcService
{
private GeneralServiceDetail _generalServiceDetail;
private IPInterfaceProperties _targetPropertiesCache = null;
private UnicastIPAddressInformation _targetAddressInfoCache = null;
private string _cacheChosenInterface = null;
public IGeneralService()
{
_generalServiceDetail = new GeneralServiceDetail
{
ClientId = GeneralServiceManager.Count,
IsAnyInternetRequestAccepted = true // NOTE: Why not accept any internet request?
};
NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(LocalInterfaceCacheHandler);
GeneralServiceManager.Add(_generalServiceDetail);
}
[CommandCmif(1)]
// GetClientId() -> buffer<nn::nifm::ClientId, 0x1a, 4>
public ResultCode GetClientId(ServiceCtx context)
{
ulong position = context.Request.RecvListBuff[0].Position;
context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize(sizeof(int));
context.Memory.Write(position, _generalServiceDetail.ClientId);
return ResultCode.Success;
}
[CommandCmif(4)]
// CreateRequest(u32 version) -> object<nn::nifm::detail::IRequest>
public ResultCode CreateRequest(ServiceCtx context)
{
uint version = context.RequestData.ReadUInt32();
MakeObject(context, new IRequest(context.Device.System, version));
// Doesn't occur in our case.
// return ResultCode.ObjectIsNull;
Logger.Stub?.PrintStub(LogClass.ServiceNifm, new { version });
return ResultCode.Success;
}
[CommandCmif(5)]
// GetCurrentNetworkProfile() -> buffer<nn::nifm::detail::sf::NetworkProfileData, 0x1a, 0x17c>
public ResultCode GetCurrentNetworkProfile(ServiceCtx context)
{
ulong networkProfileDataPosition = context.Request.RecvListBuff[0].Position;
(IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastAddress) = GetLocalInterface(context);
if (interfaceProperties == null || unicastAddress == null)
{
return ResultCode.NoInternetConnection;
}
Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize((uint)Unsafe.SizeOf<NetworkProfileData>());
NetworkProfileData networkProfile = new NetworkProfileData
{
Uuid = UInt128Utils.CreateRandom()
};
networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties);
"RyujinxNetwork"u8.CopyTo(networkProfile.Name.AsSpan());
context.Memory.Write(networkProfileDataPosition, networkProfile);
return ResultCode.Success;
}
[CommandCmif(12)]
// GetCurrentIpAddress() -> nn::nifm::IpV4Address
public ResultCode GetCurrentIpAddress(ServiceCtx context)
{
(_, UnicastIPAddressInformation unicastAddress) = GetLocalInterface(context);
if (unicastAddress == null)
{
return ResultCode.NoInternetConnection;
}
context.ResponseData.WriteStruct(new IpV4Address(unicastAddress.Address));
Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
return ResultCode.Success;
}
[CommandCmif(15)]
// GetCurrentIpConfigInfo() -> (nn::nifm::IpAddressSetting, nn::nifm::DnsSetting)
public ResultCode GetCurrentIpConfigInfo(ServiceCtx context)
{
(IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastAddress) = GetLocalInterface(context);
if (interfaceProperties == null || unicastAddress == null)
{
return ResultCode.NoInternetConnection;
}
Logger.Info?.Print(LogClass.ServiceNifm, $"Console's local IP is \"{unicastAddress.Address}\".");
context.ResponseData.WriteStruct(new IpAddressSetting(interfaceProperties, unicastAddress));
context.ResponseData.WriteStruct(new DnsSetting(interfaceProperties));
return ResultCode.Success;
}
[CommandCmif(18)]
// GetInternetConnectionStatus() -> nn::nifm::detail::sf::InternetConnectionStatus
public ResultCode GetInternetConnectionStatus(ServiceCtx context)
{
if (!NetworkInterface.GetIsNetworkAvailable())
{
return ResultCode.NoInternetConnection;
}
InternetConnectionStatus internetConnectionStatus = new InternetConnectionStatus
{
Type = InternetConnectionType.WiFi,
WifiStrength = 3,
State = InternetConnectionState.Connected,
};
context.ResponseData.WriteStruct(internetConnectionStatus);
return ResultCode.Success;
}
[CommandCmif(21)]
// IsAnyInternetRequestAccepted(buffer<nn::nifm::ClientId, 0x19, 4>) -> bool
public ResultCode IsAnyInternetRequestAccepted(ServiceCtx context)
{
ulong position = context.Request.PtrBuff[0].Position;
ulong size = context.Request.PtrBuff[0].Size;
int clientId = context.Memory.Read<int>(position);
context.ResponseData.Write(GeneralServiceManager.Get(clientId).IsAnyInternetRequestAccepted);
return ResultCode.Success;
}
private (IPInterfaceProperties, UnicastIPAddressInformation) GetLocalInterface(ServiceCtx context)
{
if (!NetworkInterface.GetIsNetworkAvailable())
{
return (null, null);
}
string chosenInterface = context.Device.Configuration.MultiplayerLanInterfaceId;
if (_targetPropertiesCache == null || _targetAddressInfoCache == null || _cacheChosenInterface != chosenInterface)
{
_cacheChosenInterface = chosenInterface;
(_targetPropertiesCache, _targetAddressInfoCache) = NetworkHelpers.GetLocalInterface(chosenInterface);
}
return (_targetPropertiesCache, _targetAddressInfoCache);
}
private void LocalInterfaceCacheHandler(object sender, EventArgs e)
{
Logger.Info?.Print(LogClass.ServiceNifm, $"NetworkAddress changed, invalidating cached data.");
_targetPropertiesCache = null;
_targetAddressInfoCache = null;
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
NetworkChange.NetworkAddressChanged -= LocalInterfaceCacheHandler;
GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
}
}
}
}

View File

@@ -0,0 +1,142 @@
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.Nifm.StaticService
{
class IRequest : IpcService
{
private enum RequestState
{
Error = 1,
OnHold = 2,
Available = 3
}
private KEvent _event0;
private KEvent _event1;
private int _event0Handle;
private int _event1Handle;
private uint _version;
public IRequest(Horizon system, uint version)
{
_event0 = new KEvent(system.KernelContext);
_event1 = new KEvent(system.KernelContext);
_version = version;
}
[CommandCmif(0)]
// GetRequestState() -> u32
public ResultCode GetRequestState(ServiceCtx context)
{
RequestState requestState = context.Device.Configuration.EnableInternetAccess
? RequestState.Available
: RequestState.Error;
context.ResponseData.Write((int)requestState);
Logger.Stub?.PrintStub(LogClass.ServiceNifm);
return ResultCode.Success;
}
[CommandCmif(1)]
// GetResult()
public ResultCode GetResult(ServiceCtx context)
{
Logger.Stub?.PrintStub(LogClass.ServiceNifm);
return GetResultImpl();
}
private ResultCode GetResultImpl()
{
return ResultCode.Success;
}
[CommandCmif(2)]
// GetSystemEventReadableHandles() -> (handle<copy>, handle<copy>)
public ResultCode GetSystemEventReadableHandles(ServiceCtx context)
{
if (_event0Handle == 0)
{
if (context.Process.HandleTable.GenerateHandle(_event0.ReadableEvent, out _event0Handle) != Result.Success)
{
throw new InvalidOperationException("Out of handles!");
}
}
if (_event1Handle == 0)
{
if (context.Process.HandleTable.GenerateHandle(_event1.ReadableEvent, out _event1Handle) != Result.Success)
{
throw new InvalidOperationException("Out of handles!");
}
}
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_event0Handle, _event1Handle);
return ResultCode.Success;
}
[CommandCmif(3)]
// Cancel()
public ResultCode Cancel(ServiceCtx context)
{
Logger.Stub?.PrintStub(LogClass.ServiceNifm);
return ResultCode.Success;
}
[CommandCmif(4)]
// Submit()
public ResultCode Submit(ServiceCtx context)
{
Logger.Stub?.PrintStub(LogClass.ServiceNifm);
return ResultCode.Success;
}
[CommandCmif(11)]
// SetConnectionConfirmationOption(i8)
public ResultCode SetConnectionConfirmationOption(ServiceCtx context)
{
Logger.Stub?.PrintStub(LogClass.ServiceNifm);
return ResultCode.Success;
}
[CommandCmif(21)]
// GetAppletInfo(u32) -> (u32, u32, u32, buffer<bytes, 6>)
public ResultCode GetAppletInfo(ServiceCtx context)
{
uint themeColor = context.RequestData.ReadUInt32();
Logger.Stub?.PrintStub(LogClass.ServiceNifm);
ResultCode result = GetResultImpl();
if (result == ResultCode.Success || (ResultCode)((int)result & 0x3fffff) == ResultCode.Unknown112)
{
return ResultCode.Unknown180;
}
// Returns appletId, libraryAppletMode, outSize and a buffer.
// Returned applet ids- (0x19, 0xf, 0xe)
// libraryAppletMode seems to be 0 for all applets supported.
// TODO: check order
context.ResponseData.Write(0xe); // Use error applet as default for now
context.ResponseData.Write(0); // libraryAppletMode
context.ResponseData.Write(0); // outSize
return ResultCode.Success;
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 9)]
struct DnsSetting
{
[MarshalAs(UnmanagedType.U1)]
public bool IsDynamicDnsEnabled;
public IpV4Address PrimaryDns;
public IpV4Address SecondaryDns;
public DnsSetting(IPInterfaceProperties interfaceProperties)
{
IsDynamicDnsEnabled = OperatingSystem.IsWindows() && interfaceProperties.IsDynamicDnsEnabled;
if (interfaceProperties.DnsAddresses.Count == 0)
{
PrimaryDns = new IpV4Address();
SecondaryDns = new IpV4Address();
}
else
{
PrimaryDns = new IpV4Address(interfaceProperties.DnsAddresses[0]);
SecondaryDns = new IpV4Address(interfaceProperties.DnsAddresses[interfaceProperties.DnsAddresses.Count > 1 ? 1 : 0]);
}
}
}
}

View File

@@ -0,0 +1,11 @@
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
enum InternetConnectionState : byte
{
ConnectingType0 = 0,
ConnectingType1 = 1,
ConnectingType2 = 2,
ConnectingType3 = 3,
Connected = 4,
}
}

View File

@@ -0,0 +1,12 @@
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
[StructLayout(LayoutKind.Sequential)]
struct InternetConnectionStatus
{
public InternetConnectionType Type;
public byte WifiStrength;
public InternetConnectionState State;
}
}

View File

@@ -0,0 +1,9 @@
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
enum InternetConnectionType : byte
{
Invalid = 0,
WiFi = 1,
Ethernet = 2,
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0xd)]
struct IpAddressSetting
{
[MarshalAs(UnmanagedType.U1)]
public bool IsDhcpEnabled;
public IpV4Address Address;
public IpV4Address IPv4Mask;
public IpV4Address GatewayAddress;
public IpAddressSetting(IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastIPAddressInformation)
{
IsDhcpEnabled = OperatingSystem.IsMacOS() || interfaceProperties.DhcpServerAddresses.Count != 0;
Address = new IpV4Address(unicastIPAddressInformation.Address);
IPv4Mask = new IpV4Address(unicastIPAddressInformation.IPv4Mask);
GatewayAddress = (interfaceProperties.GatewayAddresses.Count == 0) ? new IpV4Address() : new IpV4Address(interfaceProperties.GatewayAddresses[0].Address);
}
}
}

View File

@@ -0,0 +1,13 @@
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0xc2)]
struct IpSettingData
{
public IpAddressSetting IpAddressSetting;
public DnsSetting DnsSetting;
public ProxySetting ProxySetting;
public short Mtu;
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Net;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
[StructLayout(LayoutKind.Sequential)]
struct IpV4Address
{
public uint Address;
public IpV4Address(IPAddress address)
{
if (address == null)
{
Address = 0;
}
else
{
Address = BitConverter.ToUInt32(address.GetAddressBytes());
}
}
}
}

View File

@@ -0,0 +1,17 @@
using Ryujinx.Common.Memory;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x17C)]
struct NetworkProfileData
{
public IpSettingData IpSettingData;
public UInt128 Uuid;
public Array64<byte> Name;
public Array4<byte> Unknown;
public WirelessSettingData WirelessSettingData;
public byte Padding;
}
}

View File

@@ -0,0 +1,27 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0xaa)]
public struct ProxySetting
{
[MarshalAs(UnmanagedType.I1)]
public bool Enabled;
private byte _padding;
public short Port;
private NameStruct _name;
[MarshalAs(UnmanagedType.I1)]
public bool AutoAuthEnabled;
public Array32<byte> User;
public Array32<byte> Pass;
private byte _padding2;
[StructLayout(LayoutKind.Sequential, Size = 0x64)]
private struct NameStruct { }
public Span<byte> Name => SpanHelpers.AsSpan<NameStruct, byte>(ref _name);
}
}

View File

@@ -0,0 +1,15 @@
using Ryujinx.Common.Memory;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x65)]
struct WirelessSettingData
{
public byte SsidLength;
public Array32<byte> Ssid;
public Array3<byte> Unknown;
public Array64<byte> Passphrase1;
public byte Passphrase2;
}
}