Fix GetAddrInfoWithOptions and some sockets issues (#2936)

* Fix GetAddrInfoWithOptions and some sockets issues

* Was not supposed to remove this log
This commit is contained in:
gdkchan 2021-12-26 11:17:13 -03:00 committed by GitHub
parent c0056546e7
commit 0b1185284c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 237 additions and 108 deletions

View file

@ -98,6 +98,11 @@ namespace Ryujinx.HLE
/// </summary>
internal readonly bool EnablePtc;
/// <summary>
/// Control if the guest application should be told that there is a Internet connection available.
/// </summary>
internal readonly bool EnableInternetAccess;
/// <summary>
/// Control LibHac's integrity check level.
/// </summary>
@ -122,8 +127,8 @@ namespace Ryujinx.HLE
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
internal readonly string TimeZone;
/// <summary>
/// Type of the memory manager used on CPU emulation.
/// </summary>
public MemoryManagerMode MemoryManagerMode { internal get; set; }
@ -163,6 +168,7 @@ namespace Ryujinx.HLE
bool enableVsync,
bool enableDockedMode,
bool enablePtc,
bool enableInternetAccess,
IntegrityCheckLevel fsIntegrityCheckLevel,
int fsGlobalAccessLogMode,
long systemTimeOffset,
@ -186,6 +192,7 @@ namespace Ryujinx.HLE
EnableVsync = enableVsync;
EnableDockedMode = enableDockedMode;
EnablePtc = enablePtc;
EnableInternetAccess = enableInternetAccess;
FsIntegrityCheckLevel = fsIntegrityCheckLevel;
FsGlobalAccessLogMode = fsGlobalAccessLogMode;
SystemTimeOffset = systemTimeOffset;

View file

@ -8,6 +8,13 @@ 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;
@ -28,7 +35,11 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
// GetRequestState() -> u32
public ResultCode GetRequestState(ServiceCtx context)
{
context.ResponseData.Write(1);
RequestState requestState = context.Device.Configuration.EnableInternetAccess
? RequestState.Available
: RequestState.Error;
context.ResponseData.Write((int)requestState);
Logger.Stub?.PrintStub(LogClass.ServiceNifm);

View file

@ -106,7 +106,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
_isPrivileged = isPrivileged;
}
private LinuxError ConvertError(WsaError errorCode)
private static LinuxError ConvertError(WsaError errorCode)
{
if (!_errorMap.TryGetValue(errorCode, out LinuxError errno))
{
@ -116,6 +116,56 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
return errno;
}
private static SocketFlags ConvertBsdSocketFlags(BsdSocketFlags bsdSocketFlags)
{
BsdSocketFlags SupportedFlags =
BsdSocketFlags.Oob |
BsdSocketFlags.Peek |
BsdSocketFlags.DontRoute |
BsdSocketFlags.Trunc |
BsdSocketFlags.CTrunc;
SocketFlags socketFlags = SocketFlags.None;
if (bsdSocketFlags.HasFlag(BsdSocketFlags.Oob))
{
socketFlags |= SocketFlags.OutOfBand;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.Peek))
{
socketFlags |= SocketFlags.Peek;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.DontRoute))
{
socketFlags |= SocketFlags.DontRoute;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.Trunc))
{
socketFlags |= SocketFlags.Truncated;
}
if (bsdSocketFlags.HasFlag(BsdSocketFlags.CTrunc))
{
socketFlags |= SocketFlags.ControlDataTruncated;
}
bsdSocketFlags &= ~(BsdSocketFlags.Oob |
BsdSocketFlags.Peek |
BsdSocketFlags.DontRoute |
BsdSocketFlags.Trunc |
BsdSocketFlags.CTrunc);
if (bsdSocketFlags != BsdSocketFlags.None)
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported socket flags: {bsdSocketFlags}");
}
return socketFlags;
}
private ResultCode WriteWinSock2Error(ServiceCtx context, WsaError errorCode)
{
return WriteBsdResult(context, -1, ConvertError(errorCode));
@ -464,7 +514,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
public ResultCode Recv(ServiceCtx context)
{
int socketFd = context.RequestData.ReadInt32();
SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32();
BsdSocketFlags socketFlags = (BsdSocketFlags)context.RequestData.ReadInt32();
(ulong receivePosition, ulong receiveLength) = context.Request.GetBufferType0x22();
@ -474,18 +524,11 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
if (socket != null)
{
if (socketFlags != SocketFlags.None && (socketFlags & SocketFlags.OutOfBand) == 0
&& (socketFlags & SocketFlags.Peek) == 0)
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Recv flags: {socketFlags}");
return WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP);
}
byte[] receivedBuffer = new byte[receiveLength];
try
{
result = socket.Handle.Receive(receivedBuffer, socketFlags);
result = socket.Handle.Receive(receivedBuffer, ConvertBsdSocketFlags(socketFlags));
errno = SetResultErrno(socket.Handle, result);
context.Memory.Write(receivePosition, receivedBuffer);
@ -504,7 +547,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
public ResultCode RecvFrom(ServiceCtx context)
{
int socketFd = context.RequestData.ReadInt32();
SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32();
BsdSocketFlags socketFlags = (BsdSocketFlags)context.RequestData.ReadInt32();
(ulong receivePosition, ulong receiveLength) = context.Request.GetBufferType0x22();
(ulong sockAddrOutPosition, ulong sockAddrOutSize) = context.Request.GetBufferType0x22(1);
@ -515,20 +558,12 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
if (socket != null)
{
if (socketFlags != SocketFlags.None && (socketFlags & SocketFlags.OutOfBand) == 0
&& (socketFlags & SocketFlags.Peek) == 0)
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Recv flags: {socketFlags}");
return WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP);
}
byte[] receivedBuffer = new byte[receiveLength];
EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
try
{
result = socket.Handle.ReceiveFrom(receivedBuffer, receivedBuffer.Length, socketFlags, ref endPoint);
result = socket.Handle.ReceiveFrom(receivedBuffer, receivedBuffer.Length, ConvertBsdSocketFlags(socketFlags), ref endPoint);
errno = SetResultErrno(socket.Handle, result);
context.Memory.Write(receivePosition, receivedBuffer);
@ -548,7 +583,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
public ResultCode Send(ServiceCtx context)
{
int socketFd = context.RequestData.ReadInt32();
SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32();
BsdSocketFlags socketFlags = (BsdSocketFlags)context.RequestData.ReadInt32();
(ulong sendPosition, ulong sendSize) = context.Request.GetBufferType0x21();
@ -558,21 +593,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
if (socket != null)
{
if (socketFlags != SocketFlags.None && socketFlags != SocketFlags.OutOfBand
&& socketFlags != SocketFlags.Peek && socketFlags != SocketFlags.DontRoute)
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Send flags: {socketFlags}");
return WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP);
}
byte[] sendBuffer = new byte[sendSize];
context.Memory.Read(sendPosition, sendBuffer);
try
{
result = socket.Handle.Send(sendBuffer, socketFlags);
result = socket.Handle.Send(sendBuffer, ConvertBsdSocketFlags(socketFlags));
errno = SetResultErrno(socket.Handle, result);
}
catch (SocketException exception)
@ -590,7 +617,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
public ResultCode SendTo(ServiceCtx context)
{
int socketFd = context.RequestData.ReadInt32();
SocketFlags socketFlags = (SocketFlags)context.RequestData.ReadInt32();
BsdSocketFlags socketFlags = (BsdSocketFlags)context.RequestData.ReadInt32();
(ulong sendPosition, ulong sendSize) = context.Request.GetBufferType0x21();
(ulong bufferPosition, ulong bufferSize) = context.Request.GetBufferType0x21(1);
@ -601,14 +628,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
if (socket != null)
{
if (socketFlags != SocketFlags.None && socketFlags != SocketFlags.OutOfBand
&& socketFlags != SocketFlags.Peek && socketFlags != SocketFlags.DontRoute)
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Send flags: {socketFlags}");
return WriteBsdResult(context, -1, LinuxError.EOPNOTSUPP);
}
byte[] sendBuffer = new byte[sendSize];
context.Memory.Read(sendPosition, sendBuffer);
@ -617,7 +636,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
try
{
result = socket.Handle.SendTo(sendBuffer, sendBuffer.Length, socketFlags, endPoint);
result = socket.Handle.SendTo(sendBuffer, sendBuffer.Length, ConvertBsdSocketFlags(socketFlags), endPoint);
errno = SetResultErrno(socket.Handle, result);
}
catch (SocketException exception)
@ -736,10 +755,17 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
socket.Handle.Connect(endPoint);
}
catch (SocketException exception)
{
if (!socket.Handle.Blocking && exception.ErrorCode == (int)WsaError.WSAEWOULDBLOCK)
{
errno = LinuxError.EINPROGRESS;
}
else
{
errno = ConvertError((WsaError)exception.ErrorCode);
}
}
}
return WriteBsdResult(context, 0, errno);
}
@ -795,8 +821,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
public ResultCode GetSockOpt(ServiceCtx context)
{
int socketFd = context.RequestData.ReadInt32();
int level = context.RequestData.ReadInt32();
int optionName = context.RequestData.ReadInt32();
SocketOptionLevel level = (SocketOptionLevel)context.RequestData.ReadInt32();
SocketOptionName optionName = (SocketOptionName)context.RequestData.ReadInt32();
(ulong bufferPosition, ulong bufferSize) = context.Request.GetBufferType0x22();
@ -805,16 +831,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
if (socket != null)
{
errno = LinuxError.ENOPROTOOPT;
if (level == 0xFFFF)
{
errno = HandleGetSocketOption(context, socket, (SocketOptionName)optionName, bufferPosition, bufferSize);
}
else
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt Level: {(SocketOptionLevel)level}");
}
errno = HandleGetSocketOption(context, socket, optionName, level, bufferPosition, bufferSize);
}
return WriteBsdResult(context, 0, errno);
@ -916,7 +933,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
return WriteBsdResult(context, result, errno);
}
private LinuxError HandleGetSocketOption(ServiceCtx context, BsdSocket socket, SocketOptionName optionName, ulong optionValuePosition, ulong optionValueSize)
private static LinuxError HandleGetSocketOption(
ServiceCtx context,
BsdSocket socket,
SocketOptionName optionName,
SocketOptionLevel level,
ulong optionValuePosition,
ulong optionValueSize)
{
try
{
@ -936,19 +959,19 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
case SocketOptionName.SendTimeout:
case SocketOptionName.Type:
case SocketOptionName.Linger:
socket.Handle.GetSocketOption(SocketOptionLevel.Socket, optionName, optionValue);
socket.Handle.GetSocketOption(level, optionName, optionValue);
context.Memory.Write(optionValuePosition, optionValue);
return LinuxError.SUCCESS;
case (SocketOptionName)0x200:
socket.Handle.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue);
socket.Handle.GetSocketOption(level, SocketOptionName.ReuseAddress, optionValue);
context.Memory.Write(optionValuePosition, optionValue);
return LinuxError.SUCCESS;
default:
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt OptionName: {optionName}");
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt OptionName: {optionName}");
return LinuxError.EOPNOTSUPP;
}
@ -959,7 +982,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
}
}
private LinuxError HandleSetSocketOption(ServiceCtx context, BsdSocket socket, SocketOptionName optionName, ulong optionValuePosition, ulong optionValueSize)
private static LinuxError HandleSetSocketOption(
ServiceCtx context,
BsdSocket socket,
SocketOptionName optionName,
SocketOptionLevel level,
ulong optionValuePosition,
ulong optionValueSize)
{
try
{
@ -977,17 +1006,17 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
case SocketOptionName.SendTimeout:
case SocketOptionName.Type:
case SocketOptionName.ReuseAddress:
socket.Handle.SetSocketOption(SocketOptionLevel.Socket, optionName, context.Memory.Read<int>((ulong)optionValuePosition));
socket.Handle.SetSocketOption(level, optionName, context.Memory.Read<int>((ulong)optionValuePosition));
return LinuxError.SUCCESS;
case (SocketOptionName)0x200:
socket.Handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, context.Memory.Read<int>((ulong)optionValuePosition));
socket.Handle.SetSocketOption(level, SocketOptionName.ReuseAddress, context.Memory.Read<int>((ulong)optionValuePosition));
return LinuxError.SUCCESS;
case SocketOptionName.Linger:
socket.Handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger,
socket.Handle.SetSocketOption(level, SocketOptionName.Linger,
new LingerOption(context.Memory.Read<int>((ulong)optionValuePosition) != 0, context.Memory.Read<int>((ulong)optionValuePosition + 4)));
return LinuxError.SUCCESS;
@ -1009,8 +1038,8 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
public ResultCode SetSockOpt(ServiceCtx context)
{
int socketFd = context.RequestData.ReadInt32();
int level = context.RequestData.ReadInt32();
int optionName = context.RequestData.ReadInt32();
SocketOptionLevel level = (SocketOptionLevel)context.RequestData.ReadInt32();
SocketOptionName optionName = (SocketOptionName)context.RequestData.ReadInt32();
(ulong bufferPos, ulong bufferSize) = context.Request.GetBufferType0x21();
@ -1019,16 +1048,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
if (socket != null)
{
errno = LinuxError.ENOPROTOOPT;
if (level == 0xFFFF)
{
errno = HandleSetSocketOption(context, socket, (SocketOptionName)optionName, bufferPos, bufferSize);
}
else
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt Level: {(SocketOptionLevel)level}");
}
errno = HandleSetSocketOption(context, socket, optionName, level, bufferPos, bufferSize);
}
return WriteBsdResult(context, 0, errno);

View file

@ -0,0 +1,24 @@
using System.Net.Sockets;
namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
{
enum BsdSocketFlags
{
None = 0,
Oob = 0x1,
Peek = 0x2,
DontRoute = 0x4,
Eor = 0x8,
Trunc = 0x10,
CTrunc = 0x20,
WaitAll = 0x40,
DontWait = 0x80,
Eof = 0x100,
Notification = 0x2000,
Nbio = 0x4000,
Compat = 0x8000,
SoCallbck = 0x10000,
NoSignal = 0x20000,
CMsgCloExec = 0x40000
}
}

View file

@ -155,7 +155,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
ulong responseBufferPosition = context.Request.ReceiveBuff[0].Position;
ulong responseBufferSize = context.Request.ReceiveBuff[0].Size;
return GetAddrInfoRequestImpl(context, responseBufferPosition, responseBufferSize, 0, 0);
return GetAddrInfoRequestImpl(context, responseBufferPosition, responseBufferSize, false, 0, 0);
}
[CommandHipc(8)]
@ -213,7 +213,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
(ulong responseBufferPosition, ulong responseBufferSize) = context.Request.GetBufferType0x22();
(ulong optionsBufferPosition, ulong optionsBufferSize) = context.Request.GetBufferType0x21();
return GetAddrInfoRequestImpl(context, responseBufferPosition, responseBufferSize, optionsBufferPosition, optionsBufferSize);
return GetAddrInfoRequestImpl(context, responseBufferPosition, responseBufferSize, true, optionsBufferPosition, optionsBufferSize);
}
private ResultCode GetHostByNameRequestImpl(ServiceCtx context, ulong inputBufferPosition, ulong inputBufferSize, ulong outputBufferPosition, ulong outputBufferSize, ulong optionsBufferPosition, ulong optionsBufferSize)
@ -391,7 +391,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
return bufferPosition - originalBufferPosition;
}
private ResultCode GetAddrInfoRequestImpl(ServiceCtx context, ulong responseBufferPosition, ulong responseBufferSize, ulong optionsBufferPosition, ulong optionsBufferSize)
private ResultCode GetAddrInfoRequestImpl(
ServiceCtx context,
ulong responseBufferPosition,
ulong responseBufferSize,
bool withOptions,
ulong optionsBufferPosition,
ulong optionsBufferSize)
{
bool enableNsdResolve = (context.RequestData.ReadInt32() & 1) != 0;
uint cancelHandle = context.RequestData.ReadUInt32();
@ -402,7 +408,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
// NOTE: We ignore hints for now.
DeserializeAddrInfos(context.Memory, (ulong)context.Request.SendBuff[2].Position, (ulong)context.Request.SendBuff[2].Size);
if (optionsBufferSize > 0)
if (withOptions)
{
// TODO: Find unknown, Parse and use options.
uint unknown = context.RequestData.ReadUInt32();
@ -457,9 +463,19 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
serializedSize = SerializeAddrInfos(context, responseBufferPosition, responseBufferSize, hostEntry, port);
}
if (withOptions)
{
context.ResponseData.Write(serializedSize);
context.ResponseData.Write((int)errno);
context.ResponseData.Write((int)netDbErrorCode);
context.ResponseData.Write(0);
}
else
{
context.ResponseData.Write((int)netDbErrorCode);
context.ResponseData.Write((int)errno);
context.ResponseData.Write(serializedSize);
}
return ResultCode.Success;
}

View file

@ -21,9 +21,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
Port = port;
Address = default;
address.GetAddressBytes().AsSpan().CopyTo(Address.ToSpan());
Address.ToSpan().Reverse();
Span<byte> outAddress = Address.ToSpan();
address.TryWriteBytes(outAddress, out _);
outAddress.Reverse();
}
}
}

View file

@ -49,7 +49,7 @@ namespace Ryujinx.HLE
throw new ArgumentNullException(nameof(configuration.AudioDeviceDriver));
}
if (configuration.UserChannelPersistence== null)
if (configuration.UserChannelPersistence == null)
{
throw new ArgumentNullException(nameof(configuration.UserChannelPersistence));
}

View file

@ -79,6 +79,9 @@ namespace Ryujinx.Headless.SDL2
[Option("enable-ptc", Required = false, Default = true, HelpText = "Enables profiled translation cache persistency.")]
public bool? EnablePtc { get; set; }
[Option("enable-internet-connection", Required = false, Default = false, HelpText = "Enables guest Internet connection.")]
public bool? EnableInternetAccess { get; set; }
[Option("enable-fs-integrity-checks", Required = false, Default = true, HelpText = "Enables integrity checks on Game content files.")]
public bool? EnableFsIntegrityChecks { get; set; }

View file

@ -459,6 +459,7 @@ namespace Ryujinx.Headless.SDL2
(bool)options.EnableVsync,
(bool)options.EnableDockedMode,
(bool)options.EnablePtc,
(bool)options.EnableInternetAccess,
(bool)options.EnableFsIntegrityChecks ? LibHac.FsSystem.IntegrityCheckLevel.ErrorOnInvalid : LibHac.FsSystem.IntegrityCheckLevel.None,
options.FsGlobalAccessLogMode,
options.SystemTimeOffset,

View file

@ -14,8 +14,11 @@ namespace Ryujinx.Configuration
/// <summary>
/// The current version of the file format
/// </summary>
public const int CurrentVersion = 33;
public const int CurrentVersion = 34;
/// <summary>
/// Version of the configuration file format
/// </summary>
public int Version { get; set; }
/// <summary>
@ -98,7 +101,6 @@ namespace Ryujinx.Configuration
/// </summary>
public GraphicsDebugLevel LoggingGraphicsDebugLevel { get; set; }
/// <summary>
/// Change System Language
/// </summary>
@ -154,16 +156,16 @@ namespace Ryujinx.Configuration
/// </summary>
public bool EnableShaderCache { get; set; }
/// <summary>
/// Enables or disables multi-core scheduling of threads
/// </summary>
public bool EnableMulticoreScheduling { get; set; }
/// <summary>
/// Enables or disables profiled translation cache persistency
/// </summary>
public bool EnablePtc { get; set; }
/// <summary>
/// Enables or disables guest Internet access
/// </summary>
public bool EnableInternetAccess { get; set; }
/// <summary>
/// Enables integrity checks on Game content files
/// </summary>

View file

@ -205,6 +205,11 @@ namespace Ryujinx.Configuration
/// </summary>
public ReactiveObject<bool> EnablePtc { get; private set; }
/// <summary>
/// Enables or disables guest Internet access
/// </summary>
public ReactiveObject<bool> EnableInternetAccess { get; private set; }
/// <summary>
/// Enables integrity checks on Game content files
/// </summary>
@ -250,6 +255,8 @@ namespace Ryujinx.Configuration
EnableDockedMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableDockedMode));
EnablePtc = new ReactiveObject<bool>();
EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc));
EnableInternetAccess = new ReactiveObject<bool>();
EnableInternetAccess.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableInternetAccess));
EnableFsIntegrityChecks = new ReactiveObject<bool>();
EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFsIntegrityChecks));
FsGlobalAccessLogMode = new ReactiveObject<int>();
@ -464,6 +471,7 @@ namespace Ryujinx.Configuration
EnableVsync = Graphics.EnableVsync,
EnableShaderCache = Graphics.EnableShaderCache,
EnablePtc = System.EnablePtc,
EnableInternetAccess = System.EnableInternetAccess,
EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
FsGlobalAccessLogMode = System.FsGlobalAccessLogMode,
AudioBackend = System.AudioBackend,
@ -534,6 +542,7 @@ namespace Ryujinx.Configuration
Graphics.EnableVsync.Value = true;
Graphics.EnableShaderCache.Value = true;
System.EnablePtc.Value = true;
System.EnableInternetAccess.Value = false;
System.EnableFsIntegrityChecks.Value = true;
System.FsGlobalAccessLogMode.Value = 0;
System.AudioBackend.Value = AudioBackend.SDL2;
@ -956,6 +965,15 @@ namespace Ryujinx.Configuration
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 34)
{
Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 34.");
configurationFileFormat.EnableInternetAccess = false;
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
Graphics.ResScale.Value = configurationFileFormat.ResScale;
@ -984,6 +1002,7 @@ namespace Ryujinx.Configuration
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
System.EnablePtc.Value = configurationFileFormat.EnablePtc;
System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode;
System.AudioBackend.Value = configurationFileFormat.AudioBackend;

View file

@ -563,6 +563,7 @@ namespace Ryujinx.Ui
ConfigurationState.Instance.Graphics.EnableVsync,
ConfigurationState.Instance.System.EnableDockedMode,
ConfigurationState.Instance.System.EnablePtc,
ConfigurationState.Instance.System.EnableInternetAccess,
fsIntegrityCheckLevel,
ConfigurationState.Instance.System.FsGlobalAccessLogMode,
ConfigurationState.Instance.System.SystemTimeOffset,

View file

@ -52,6 +52,7 @@ namespace Ryujinx.Ui.Windows
[GUI] CheckButton _vSyncToggle;
[GUI] CheckButton _shaderCacheToggle;
[GUI] CheckButton _ptcToggle;
[GUI] CheckButton _internetToggle;
[GUI] CheckButton _fsicToggle;
[GUI] RadioButton _mmSoftware;
[GUI] RadioButton _mmHost;
@ -226,6 +227,11 @@ namespace Ryujinx.Ui.Windows
_ptcToggle.Click();
}
if (ConfigurationState.Instance.System.EnableInternetAccess)
{
_internetToggle.Click();
}
if (ConfigurationState.Instance.System.EnableFsIntegrityChecks)
{
_fsicToggle.Click();
@ -496,6 +502,7 @@ namespace Ryujinx.Ui.Windows
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active;
ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active;
ConfigurationState.Instance.System.EnableInternetAccess.Value = _internetToggle.Active;
ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active;
ConfigurationState.Instance.System.MemoryManagerMode.Value = memoryMode;
ConfigurationState.Instance.System.ExpandRam.Value = _expandRamToggle.Active;

View file

@ -1507,6 +1507,24 @@
<property name="position">6</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="_internetToggle">
<property name="label" translatable="yes">Enable guest Internet access</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="tooltip-text" translatable="yes">Enables guest Internet access. If enabled, the application will behave as if the emulated Switch console was connected to the Internet. Note that in some cases, applications may still access the Internet even with this option disabled</property>
<property name="halign">start</property>
<property name="margin-top">5</property>
<property name="margin-bottom">5</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">7</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="_fsicToggle">
<property name="label" translatable="yes">Enable FS Integrity Checks</property>
@ -1522,7 +1540,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">7</property>
<property name="position">8</property>
</packing>
</child>
</object>