diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs index c64dddf03..f58953d80 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs @@ -3,6 +3,8 @@ using Ryujinx.Cpu; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Services.Settings; using Ryujinx.HLE.HOS.Services.Sockets.Nsd.Manager; +using Ryujinx.HLE.HOS.Services.Sockets.Nsd.Types; +using System.Runtime.InteropServices; using System.Text; namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd @@ -11,8 +13,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd [Service("nsd:u")] // Max sessions: 20 class IManager : IpcService { - private NsdSettings _nsdSettings; - private FqdnResolver _fqdnResolver; + private readonly NsdSettings _nsdSettings; + private readonly FqdnResolver _fqdnResolver; private bool _isInitialized = false; @@ -20,12 +22,21 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd { // TODO: Load nsd settings through the savedata 0x80000000000000B0 (nsdsave:/). - NxSettings.Settings.TryGetValue("nsd!test_mode", out object testMode); + if (!NxSettings.Settings.TryGetValue("nsd!test_mode", out object testMode)) + { + // return ResultCode.InvalidSettingsValue; + } + + if (!NxSettings.Settings.TryGetValue("nsd!environment_identifier", out object environmentIdentifier)) + { + // return ResultCode.InvalidSettingsValue; + } _nsdSettings = new NsdSettings { Initialized = true, - TestMode = (bool)testMode + TestMode = (bool)testMode, + Environment = (string)environmentIdentifier }; _fqdnResolver = new FqdnResolver(_nsdSettings); @@ -33,35 +44,33 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd _isInitialized = true; } + [CommandHipc(5)] // 11.0.0+ + // GetSettingUrl() -> buffer, 0x16> + public ResultCode GetSettingUrl(ServiceCtx context) + { + throw new ServiceNotImplementedException(this, context, false); + } + [CommandHipc(10)] // GetSettingName() -> buffer, 0x16> public ResultCode GetSettingName(ServiceCtx context) { - (ulong outputPosition, ulong outputSize) = context.Request.GetBufferType0x22(); - - ResultCode result = _fqdnResolver.GetSettingName(context, out string settingName); - - if (result == ResultCode.Success) - { - byte[] settingNameBuffer = Encoding.UTF8.GetBytes(settingName + '\0'); - - context.Memory.Write(outputPosition, settingNameBuffer); - } - - return result; + throw new ServiceNotImplementedException(this, context, false); } [CommandHipc(11)] - // GetEnvironmentIdentifier() -> buffer, 0x16> + // GetEnvironmentIdentifier() -> buffer environment_identifier, 0x16> public ResultCode GetEnvironmentIdentifier(ServiceCtx context) { (ulong outputPosition, ulong outputSize) = context.Request.GetBufferType0x22(); - ResultCode result = _fqdnResolver.GetEnvironmentIdentifier(context, out string identifier); + MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize); + + ResultCode result = _fqdnResolver.GetEnvironmentIdentifier(out string identifier); if (result == ResultCode.Success) { - byte[] identifierBuffer = Encoding.UTF8.GetBytes(identifier + '\0'); + byte[] identifierBuffer = Encoding.UTF8.GetBytes(identifier); context.Memory.Write(outputPosition, identifierBuffer); } @@ -122,11 +131,23 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd throw new ServiceNotImplementedException(this, context, false); } - [CommandHipc(15)] - // Unknown(bytes<1>) - public ResultCode Unknown(ServiceCtx context) + [CommandHipc(15)] // 4.0.0+ + // SetChangeEnvironmentIdentifierDisabled(bytes<1>) + public ResultCode SetChangeEnvironmentIdentifierDisabled(ServiceCtx context) { - throw new ServiceNotImplementedException(this, context, false); + byte disabled = context.RequestData.ReadByte(); + + // TODO: When sys:set service calls will be implemented + /* + if (((nn::settings::detail::GetServiceDiscoveryControlSettings() ^ disabled) & 1) != 0 ) + { + nn::settings::detail::SetServiceDiscoveryControlSettings(disabled & 1); + } + */ + + Logger.Stub?.PrintStub(LogClass.ServiceNsd, new { disabled }); + + return ResultCode.Success; } [CommandHipc(20)] @@ -226,6 +247,24 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd throw new ServiceNotImplementedException(this, context, false); } + [CommandHipc(51)] // 9.0.0+ + // WriteTestParameter(buffer) + public ResultCode WriteTestParameter(ServiceCtx context) + { + // TODO: Write test parameter through the savedata 0x80000000000000B0 (nsdsave:/test_parameter). + + throw new ServiceNotImplementedException(this, context, false); + } + + [CommandHipc(52)] // 9.0.0+ + // ReadTestParameter() -> buffer + public ResultCode ReadTestParameter(ServiceCtx context) + { + // TODO: Read test parameter through the savedata 0x80000000000000B0 (nsdsave:/test_parameter). + + throw new ServiceNotImplementedException(this, context, false); + } + [CommandHipc(60)] // ReadSaveDataFromFsForTest() -> buffer, 0x16> public ResultCode ReadSaveDataFromFsForTest(ServiceCtx context) @@ -235,8 +274,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd return ResultCode.ServiceNotInitialized; } - // TODO: Call nn::nsd::detail::fs::ReadSaveDataWithOffset() at offset 0 to write the - // whole savedata inside the buffer. + // TODO: Read the savedata 0x80000000000000B0 (nsdsave:/file) and write it inside the buffer. Logger.Stub?.PrintStub(LogClass.ServiceNsd); @@ -247,37 +285,113 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd // WriteSaveDataToFsForTest(buffer, 0x15>) public ResultCode WriteSaveDataToFsForTest(ServiceCtx context) { - // NOTE: Stubbed in system module. - - if (_isInitialized) - { - return ResultCode.NotImplemented; - } - else + if (!_isInitialized) { return ResultCode.ServiceNotInitialized; } + + // TODO: When sys:set service calls will be implemented + /* + if (nn::settings::detail::GetSettingsItemValueSize("nsd", "test_mode") != 1) + { + return ResultCode.InvalidSettingsValue; + } + */ + + if (!_nsdSettings.TestMode) + { + return ResultCode.InvalidSettingsValue; + } + + // TODO: Write the buffer inside the savedata 0x80000000000000B0 (nsdsave:/file). + + Logger.Stub?.PrintStub(LogClass.ServiceNsd); + + return ResultCode.Success; } [CommandHipc(62)] // DeleteSaveDataOfFsForTest() public ResultCode DeleteSaveDataOfFsForTest(ServiceCtx context) { - // NOTE: Stubbed in system module. - - if (_isInitialized) - { - return ResultCode.NotImplemented; - } - else + if (!_isInitialized) { return ResultCode.ServiceNotInitialized; } + + // TODO: When sys:set service calls will be implemented + /* + if (nn::settings::detail::GetSettingsItemValueSize("nsd", "test_mode") != 1) + { + return ResultCode.InvalidSettingsValue; + } + */ + + if (!_nsdSettings.TestMode) + { + return ResultCode.InvalidSettingsValue; + } + + // TODO: Delete the savedata 0x80000000000000B0. + + Logger.Stub?.PrintStub(LogClass.ServiceNsd); + + return ResultCode.Success; } - [CommandHipc(63)] + [CommandHipc(63)] // 4.0.0+ // IsChangeEnvironmentIdentifierDisabled() -> bytes<1> public ResultCode IsChangeEnvironmentIdentifierDisabled(ServiceCtx context) + { + // TODO: When sys:set service calls will be implemented use nn::settings::detail::GetServiceDiscoveryControlSettings() + + bool disabled = false; + + context.ResponseData.Write(disabled); + + Logger.Stub?.PrintStub(LogClass.ServiceNsd, new { disabled }); + + return ResultCode.Success; + } + + [CommandHipc(100)] // 10.0.0+ + // GetApplicationServerEnvironmentType() -> bytes<1> + public ResultCode GetApplicationServerEnvironmentType(ServiceCtx context) + { + // TODO: Mount the savedata 0x80000000000000B0 (nsdsave:/test_parameter) and returns the environment type stored inside if the mount succeed. + // Returns ResultCode.NullOutputObject if failed. + + ResultCode result = _fqdnResolver.GetEnvironmentIdentifier(out string identifier); + + if (result != ResultCode.Success) + { + return result; + } + + byte environmentType = identifier.Substring(0, 2) switch + { + "lp" => (byte)ApplicationServerEnvironmentType.Lp, + "sd" => (byte)ApplicationServerEnvironmentType.Sd, + "sp" => (byte)ApplicationServerEnvironmentType.Sp, + "dp" => (byte)ApplicationServerEnvironmentType.Dp, + _ => (byte)ApplicationServerEnvironmentType.None + }; + + context.ResponseData.Write(environmentType); + + return ResultCode.Success; + } + + [CommandHipc(101)] // 10.0.0+ + // SetApplicationServerEnvironmentType(bytes<1>) + public ResultCode SetApplicationServerEnvironmentType(ServiceCtx context) + { + throw new ServiceNotImplementedException(this, context, false); + } + + [CommandHipc(102)] // 10.0.0+ + // DeleteApplicationServerEnvironmentType() + public ResultCode DeleteApplicationServerEnvironmentType(ServiceCtx context) { throw new ServiceNotImplementedException(this, context, false); } diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs index c400c3b8a..2e23f3fb1 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs @@ -13,38 +13,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd.Manager _nsdSettings = nsdSettings; } - public ResultCode GetSettingName(ServiceCtx context, out string settingName) + public ResultCode GetEnvironmentIdentifier(out string identifier) { if (_nsdSettings.TestMode) { - settingName = ""; + identifier = "err"; - return ResultCode.NotImplemented; - } - else - { - settingName = ""; - - if (true) // TODO: Determine field (struct + 0x2C) - { - settingName = _nsdSettings.Environment; - - return ResultCode.Success; - } - -#pragma warning disable CS0162 - return ResultCode.NullOutputObject; -#pragma warning restore CS0162 - } - } - - public ResultCode GetEnvironmentIdentifier(ServiceCtx context, out string identifier) - { - if (_nsdSettings.TestMode) - { - identifier = "rre"; - - return ResultCode.NotImplemented; + return ResultCode.InvalidSettingsValue; } else { @@ -56,7 +31,14 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd.Manager public ResultCode Resolve(ServiceCtx context, string address, out string resolvedAddress) { - if (address != "api.sect.srv.nintendo.net" || address != "conntest.nintendowifi.net") + if (address == "api.sect.srv.nintendo.net" || + address == "ctest.cdn.nintendo.net" || + address == "ctest.cdn.n.nintendoswitch.cn" || + address == "unknown.dummy.nintendo.net") + { + resolvedAddress = address; + } + else { // TODO: Load Environment from the savedata. address = address.Replace("%", _nsdSettings.Environment); @@ -87,10 +69,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd.Manager _ => address, }; } - else - { - resolvedAddress = address; - } return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/ResultCode.cs index 0e636f9ae..993fbe8af 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/ResultCode.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/ResultCode.cs @@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd Success = 0, - NotImplemented = ( 1 << ErrorCodeShift) | ModuleId, + InvalidSettingsValue = ( 1 << ErrorCodeShift) | ModuleId, InvalidObject1 = ( 3 << ErrorCodeShift) | ModuleId, InvalidObject2 = ( 4 << ErrorCodeShift) | ModuleId, NullOutputObject = ( 5 << ErrorCodeShift) | ModuleId, diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Types/ApplicationServerEnvironmentType.cs b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Types/ApplicationServerEnvironmentType.cs new file mode 100644 index 000000000..150bdab4f --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Types/ApplicationServerEnvironmentType.cs @@ -0,0 +1,11 @@ +namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd.Types +{ + enum ApplicationServerEnvironmentType : byte + { + None, + Lp, + Sd, + Sp, + Dp + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Types/NsdSettings.cs b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Types/NsdSettings.cs index 2b31cb1d2..0a72fa874 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Types/NsdSettings.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Types/NsdSettings.cs @@ -4,6 +4,6 @@ { public bool Initialized; public bool TestMode; - public string Environment = "lp1"; // or "dd1" if devkit. + public string Environment; } } \ No newline at end of file