Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
44862dce3e | |||
e601419bd4 | |||
d6bc0de785 | |||
9f26fd3600 | |||
88df636c87 |
@ -1,6 +1,7 @@
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Core;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.Common.Locale
|
||||
@ -18,11 +19,20 @@ namespace Ryujinx.Ava.Common.Locale
|
||||
{
|
||||
LocaleKeys keyToUse = Key;
|
||||
|
||||
ReflectionBindingExtension binding = new($"[{keyToUse}]")
|
||||
{
|
||||
Mode = BindingMode.OneWay,
|
||||
Source = LocaleManager.Instance,
|
||||
};
|
||||
var builder = new CompiledBindingPathBuilder();
|
||||
|
||||
builder.SetRawSource(LocaleManager.Instance)
|
||||
.Property(new ClrPropertyInfo("Item",
|
||||
obj => (LocaleManager.Instance[keyToUse]),
|
||||
null,
|
||||
typeof(string)), (weakRef, iPropInfo) =>
|
||||
{
|
||||
return PropertyInfoAccessorFactory.CreateInpcPropertyAccessor(weakRef, iPropInfo);
|
||||
});
|
||||
|
||||
var path = builder.Build();
|
||||
|
||||
var binding = new CompiledBindingExtension(path);
|
||||
|
||||
return binding.ProvideValue(serviceProvider);
|
||||
}
|
||||
|
@ -6,9 +6,11 @@
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="{locale:Locale ErrorWindowTitle}"
|
||||
xmlns:views="using:Ryujinx.Ava.UI.Applet"
|
||||
Width="450"
|
||||
Height="340"
|
||||
CanResize="False"
|
||||
x:DataType="views:ErrorAppletWindow"
|
||||
SizeToContent="Height"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
@ -38,7 +40,7 @@
|
||||
Grid.Column="1"
|
||||
Margin="10"
|
||||
VerticalAlignment="Stretch"
|
||||
Text="{ReflectionBinding Message}"
|
||||
Text="{Binding Message}"
|
||||
TextWrapping="Wrap" />
|
||||
<StackPanel
|
||||
Name="ButtonStack"
|
||||
@ -49,4 +51,4 @@
|
||||
Orientation="Horizontal"
|
||||
Spacing="10" />
|
||||
</Grid>
|
||||
</Window>
|
||||
</Window>
|
||||
|
@ -4,7 +4,9 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="using:Ryujinx.Ava.UI.Controls"
|
||||
Width="400"
|
||||
x:DataType="views:SwkbdAppletDialog"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Grid
|
||||
@ -34,13 +36,13 @@
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="5"
|
||||
Text="{ReflectionBinding MainText}"
|
||||
Text="{Binding MainText}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="5"
|
||||
Text="{ReflectionBinding SecondaryText}"
|
||||
Text="{Binding SecondaryText}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBox
|
||||
Name="Input"
|
||||
@ -50,7 +52,7 @@
|
||||
VerticalAlignment="Center"
|
||||
Focusable="True"
|
||||
KeyUp="Message_KeyUp"
|
||||
Text="{ReflectionBinding Message}"
|
||||
Text="{Binding Message}"
|
||||
TextInput="Message_TextInput"
|
||||
TextWrapping="Wrap"
|
||||
UseFloatingWatermark="True" />
|
||||
|
@ -46,7 +46,7 @@
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
<Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator">
|
||||
<Setter Property="MinHeight" Value="{ReflectionBinding $parent[UserControl].DataContext.GridItemSelectorSize}" />
|
||||
<Setter Property="MinHeight" Value="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).GridItemSelectorSize}" />
|
||||
</Style>
|
||||
</ListBox.Styles>
|
||||
<ListBox.ItemTemplate>
|
||||
@ -56,10 +56,10 @@
|
||||
Margin="10"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}"
|
||||
Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}"
|
||||
Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}"
|
||||
Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}"
|
||||
Classes.huge="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridHuge}"
|
||||
Classes.large="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridLarge}"
|
||||
Classes.normal="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridMedium}"
|
||||
Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="4">
|
||||
<Grid>
|
||||
@ -78,7 +78,7 @@
|
||||
Margin="0,10,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
IsVisible="{ReflectionBinding $parent[UserControl].DataContext.ShowNames}">
|
||||
IsVisible="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
@ -101,4 +101,4 @@
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
@ -42,7 +42,7 @@
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.Styles>
|
||||
<Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator">
|
||||
<Setter Property="MinHeight" Value="{ReflectionBinding $parent[UserControl].DataContext.ListItemSelectorSize}" />
|
||||
<Setter Property="MinHeight" Value="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ListItemSelectorSize}" />
|
||||
</Style>
|
||||
</ListBox.Styles>
|
||||
<ListBox.ItemTemplate>
|
||||
@ -67,10 +67,10 @@
|
||||
Grid.RowSpan="3"
|
||||
Grid.Column="0"
|
||||
Margin="0"
|
||||
Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}"
|
||||
Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}"
|
||||
Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}"
|
||||
Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}"
|
||||
Classes.huge="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridHuge}"
|
||||
Classes.large="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridLarge}"
|
||||
Classes.normal="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridMedium}"
|
||||
Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
|
||||
Source="{Binding Icon, Converter={StaticResource ByteImage}}" />
|
||||
<Border
|
||||
Grid.Column="2"
|
||||
@ -157,4 +157,4 @@
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
@ -11,6 +11,7 @@
|
||||
Height="500"
|
||||
MinWidth="500"
|
||||
MinHeight="500"
|
||||
x:DataType="window:CheatWindow"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
@ -40,7 +41,7 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
LineHeight="18"
|
||||
Text="{ReflectionBinding Heading}"
|
||||
Text="{Binding Heading}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
@ -61,7 +62,7 @@
|
||||
MinWidth="160"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{ReflectionBinding BuildId}"
|
||||
Text="{Binding BuildId}"
|
||||
IsReadOnly="True" />
|
||||
<Border
|
||||
Grid.Row="3"
|
||||
@ -77,7 +78,7 @@
|
||||
MinHeight="300"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
ItemsSource="{ReflectionBinding LoadedCheats}">
|
||||
ItemsSource="{Binding LoadedCheats}">
|
||||
<TreeView.Styles>
|
||||
<Styles>
|
||||
<Style Selector="TreeViewItem:empty /template/ ItemsPresenter">
|
||||
@ -120,18 +121,18 @@
|
||||
Name="SaveButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding Save}"
|
||||
IsVisible="{ReflectionBinding !NoCheatsFound}">
|
||||
Command="{Binding Save}"
|
||||
IsVisible="{Binding !NoCheatsFound}">
|
||||
<TextBlock Text="{locale:Locale SettingsButtonSave}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="CancelButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding Close}">
|
||||
Command="{Binding Close}">
|
||||
<TextBlock Text="{locale:Locale InputDialogCancel}" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</window:StyleableWindow>
|
||||
</window:StyleableWindow>
|
||||
|
@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
private readonly string _enabledCheatsPath;
|
||||
public bool NoCheatsFound { get; }
|
||||
|
||||
private AvaloniaList<CheatsList> LoadedCheats { get; }
|
||||
public AvaloniaList<CheatsList> LoadedCheats { get; }
|
||||
|
||||
public string Heading { get; }
|
||||
public string BuildId { get; }
|
||||
|
@ -39,14 +39,14 @@
|
||||
Name="EnableAllButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding EnableAll}">
|
||||
Command="{Binding EnableAll}">
|
||||
<TextBlock Text="{locale:Locale DlcManagerEnableAllButton}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="DisableAllButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding DisableAll}">
|
||||
Command="{Binding DisableAll}">
|
||||
<TextBlock Text="{locale:Locale DlcManagerDisableAllButton}" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
@ -157,14 +157,14 @@
|
||||
Name="AddButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding Add}">
|
||||
Command="{Binding Add}">
|
||||
<TextBlock Text="{locale:Locale SettingsTabGeneralAdd}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="RemoveAllButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{ReflectionBinding RemoveAll}">
|
||||
Command="{Binding RemoveAll}">
|
||||
<TextBlock Text="{locale:Locale DlcManagerRemoveAllButton}" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
@ -189,4 +189,4 @@
|
||||
</StackPanel>
|
||||
</Panel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
@ -89,6 +89,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
context.AddCapability(Capability.DrawParameters);
|
||||
}
|
||||
|
||||
if (context.Definitions.Stage != ShaderStage.Fragment &&
|
||||
context.Definitions.Stage != ShaderStage.Geometry &&
|
||||
context.Definitions.Stage != ShaderStage.Compute &&
|
||||
(context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.Layer)) ||
|
||||
context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.ViewportIndex))))
|
||||
{
|
||||
context.AddExtension("SPV_EXT_shader_viewport_index_layer");
|
||||
context.AddCapability(Capability.ShaderViewportIndexLayerEXT);
|
||||
}
|
||||
|
||||
if (context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.ViewportMask)))
|
||||
{
|
||||
context.AddExtension("SPV_NV_viewport_array2");
|
||||
@ -277,14 +287,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
localSizeZ);
|
||||
}
|
||||
|
||||
if (context.Definitions.Stage != ShaderStage.Fragment &&
|
||||
context.Definitions.Stage != ShaderStage.Geometry &&
|
||||
context.Definitions.Stage != ShaderStage.Compute &&
|
||||
context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.Layer)))
|
||||
{
|
||||
context.AddCapability(Capability.ShaderLayer);
|
||||
}
|
||||
|
||||
if (context.Definitions.TransformFeedbackEnabled && context.Definitions.LastInVertexPipeline)
|
||||
{
|
||||
context.AddExecutionMode(spvFunc, ExecutionMode.Xfb);
|
||||
|
@ -299,11 +299,21 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
{
|
||||
try
|
||||
{
|
||||
LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: false);
|
||||
|
||||
if (result != LinuxError.SUCCESS)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid GetSockOpt Option: {option} Level: {level}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt Option: {option} Level: {level}");
|
||||
optionValue.Clear();
|
||||
|
||||
return LinuxError.EOPNOTSUPP;
|
||||
return LinuxError.SUCCESS;
|
||||
}
|
||||
|
||||
byte[] tempOptionValue = new byte[optionValue.Length];
|
||||
@ -324,11 +334,20 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
{
|
||||
try
|
||||
{
|
||||
LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: true);
|
||||
|
||||
if (result != LinuxError.SUCCESS)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid SetSockOpt Option: {option} Level: {level}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt Option: {option} Level: {level}");
|
||||
|
||||
return LinuxError.EOPNOTSUPP;
|
||||
return LinuxError.SUCCESS;
|
||||
}
|
||||
|
||||
int value = optionValue.Length >= 4 ? MemoryMarshal.Read<int>(optionValue) : MemoryMarshal.Read<byte>(optionValue);
|
||||
|
@ -183,6 +183,104 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
{ BsdSocketOption.TcpKeepCnt, SocketOptionName.TcpKeepAliveRetryCount },
|
||||
};
|
||||
|
||||
[Flags]
|
||||
private enum OptionDir
|
||||
{
|
||||
Get = 1 << 0,
|
||||
Set = 1 << 1,
|
||||
GetSet = Get | Set,
|
||||
}
|
||||
|
||||
private static readonly Dictionary<BsdSocketOption, OptionDir> _validSoSocketOptionMap = new()
|
||||
{
|
||||
{ BsdSocketOption.SoDebug, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoAcceptConn, OptionDir.Get },
|
||||
{ BsdSocketOption.SoReuseAddr, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoKeepAlive, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoDontRoute, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoBroadcast, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoUseLoopBack, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoLinger, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoOobInline, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoReusePort, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoTimestamp, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoNoSigpipe, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoAcceptFilter, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoSndBuf, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoRcvBuf, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoSndLoWat, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoRcvLoWat, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoSndTimeo, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoRcvTimeo, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoError, OptionDir.Get },
|
||||
{ BsdSocketOption.SoType, OptionDir.Get },
|
||||
{ BsdSocketOption.SoLabel, OptionDir.Get },
|
||||
{ BsdSocketOption.SoPeerLabel, OptionDir.Get },
|
||||
{ BsdSocketOption.SoListenQLimit, OptionDir.Get },
|
||||
{ BsdSocketOption.SoListenQLen, OptionDir.Get },
|
||||
{ BsdSocketOption.SoListenIncQLen, OptionDir.Get },
|
||||
{ BsdSocketOption.SoSetFib, OptionDir.Set },
|
||||
{ BsdSocketOption.SoUserCookie, OptionDir.Set },
|
||||
{ BsdSocketOption.SoProtocol, OptionDir.Get },
|
||||
{ BsdSocketOption.SoBinTime, OptionDir.GetSet },
|
||||
{ BsdSocketOption.SoNoOffload, OptionDir.Set },
|
||||
{ BsdSocketOption.SoNoDdp, OptionDir.Set },
|
||||
{ BsdSocketOption.SoReusePortLb, OptionDir.GetSet },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<BsdSocketOption, OptionDir> _validIpSocketOptionMap = new()
|
||||
{
|
||||
{ BsdSocketOption.IpOptions, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpHdrIncl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpTos, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpTtl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvOpts, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvRetOpts, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvDstAddr, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRetOpts, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMulticastIf, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMulticastTtl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMulticastLoop, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpAddMembership, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpDropMembership, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMulticastVif, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRsvpOn, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRsvpOff, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRsvpVifOn, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRsvpVifOff, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpPortRange, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvIf, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpIpsecPolicy, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpOnesBcast, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpBindany, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpBindMulti, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRssListenBucket, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpOrigDstAddr, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvTtl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpMinTtl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpDontFrag, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpRecvTos, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpAddSourceMembership, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpDropSourceMembership, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpBlockSource, OptionDir.GetSet },
|
||||
{ BsdSocketOption.IpUnblockSource, OptionDir.GetSet },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<BsdSocketOption, OptionDir> _validTcpSocketOptionMap = new()
|
||||
{
|
||||
{ BsdSocketOption.TcpNoDelay, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpMaxSeg, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpNoPush, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpNoOpt, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpMd5Sig, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpInfo, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpCongestion, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpKeepInit, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpKeepIdle, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpKeepIntvl, OptionDir.GetSet },
|
||||
{ BsdSocketOption.TcpKeepCnt, OptionDir.GetSet },
|
||||
};
|
||||
|
||||
public static LinuxError ConvertError(WsaError errorCode)
|
||||
{
|
||||
if (OperatingSystem.IsMacOS())
|
||||
@ -221,5 +319,29 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
|
||||
return table.TryGetValue(option, out name);
|
||||
}
|
||||
|
||||
public static LinuxError ValidateSocketOption(BsdSocketOption option, SocketOptionLevel level, bool write)
|
||||
{
|
||||
var table = level switch
|
||||
{
|
||||
SocketOptionLevel.Socket => _validSoSocketOptionMap,
|
||||
SocketOptionLevel.IP => _validIpSocketOptionMap,
|
||||
SocketOptionLevel.Tcp => _validTcpSocketOptionMap,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
OptionDir dir = write ? OptionDir.Set : OptionDir.Get;
|
||||
|
||||
if (table == null || !table.TryGetValue(option, out OptionDir validDir))
|
||||
{
|
||||
return LinuxError.ENOPROTOOPT;
|
||||
}
|
||||
else if ((validDir & dir) != dir)
|
||||
{
|
||||
return LinuxError.EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return LinuxError.SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user