Compare commits

...

4 Commits

Author SHA1 Message Date
90432946ac Avalonia - Display language names in their corresponding language under "Change Language" (#3490)
* change languages to their native names

* fix Chinese language names

* Update MainWindow.axaml
2022-08-26 19:12:11 +02:00
9bad71afbf bsd: Fix Poll writting in input buffer (#3630)
This is a very old oversight on our Poll implementation.
This worked so far reliably because games and homebrews pass the same
buffer as input and output.
2022-08-26 18:10:45 +02:00
923089a298 Fast path for Inline-to-Memory texture data transfers (#3610)
* Fast path for Inline-to-Memory texture data transfers

* Only do it for block linear textures to be on the safe side
2022-08-26 02:16:41 +00:00
d9aa15eb24 pctl: Implement EndFreeCommunication
This PR Implement `EndFreeCommunication` (checked by RE). Nothing more.

Closes #2420
2022-08-25 23:18:37 +02:00
16 changed files with 243 additions and 65 deletions

View File

@ -131,56 +131,56 @@
<MenuItem Header="{locale:Locale MenuBarOptionsChangeLanguage}"> <MenuItem Header="{locale:Locale MenuBarOptionsChangeLanguage}">
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="en_US" CommandParameter="de_DE"
Header="American English" /> Header="Deutsch" />
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="pt_BR" CommandParameter="en_US"
Header="Brazilian Portuguese" /> Header="English (US)" />
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="es_ES" CommandParameter="es_ES"
Header="Castilian Spanish" /> Header="Español (ES)" />
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="fr_FR" CommandParameter="fr_FR"
Header="French" /> Header="Français" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="de_DE"
Header="German" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="el_GR"
Header="Greek" />
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="it_IT" CommandParameter="it_IT"
Header="Italian" /> Header="Italiano" />
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ja_JP" CommandParameter="pt_BR"
Header="Japanese" /> Header="Português (BR)" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ko_KR"
Header="Korean" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ru_RU"
Header="Russian" />
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="tr_TR" CommandParameter="tr_TR"
Header="Turkish" /> Header="Türkçe" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="el_GR"
Header="Ελληνικά" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ru_RU"
Header="Русский" />
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="zh_CN" CommandParameter="zh_CN"
Header="Simplified Chinese" /> Header="简体中文" />
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="zh_TW" CommandParameter="zh_TW"
Header="Traditional Chinese (Taiwan)" /> Header="繁體中文" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ja_JP"
Header="日本語" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ko_KR"
Header="한국어" />
</MenuItem> </MenuItem>
<Separator /> <Separator />
<MenuItem <MenuItem

View File

@ -19,6 +19,7 @@ namespace Ryujinx.Graphics.GAL
void SetData(ReadOnlySpan<byte> data); void SetData(ReadOnlySpan<byte> data);
void SetData(ReadOnlySpan<byte> data, int layer, int level); void SetData(ReadOnlySpan<byte> data, int layer, int level);
void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region);
void SetStorage(BufferRange buffer); void SetStorage(BufferRange buffer);
void Release(); void Release();
} }

View File

@ -113,6 +113,8 @@ namespace Ryujinx.Graphics.GAL.Multithreading
TextureSetDataCommand.Run(ref GetCommand<TextureSetDataCommand>(memory), threaded, renderer); TextureSetDataCommand.Run(ref GetCommand<TextureSetDataCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureSetDataSlice] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) => _lookup[(int)CommandType.TextureSetDataSlice] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
TextureSetDataSliceCommand.Run(ref GetCommand<TextureSetDataSliceCommand>(memory), threaded, renderer); TextureSetDataSliceCommand.Run(ref GetCommand<TextureSetDataSliceCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureSetDataSliceRegion] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
TextureSetDataSliceRegionCommand.Run(ref GetCommand<TextureSetDataSliceRegionCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureSetStorage] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) => _lookup[(int)CommandType.TextureSetStorage] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
TextureSetStorageCommand.Run(ref GetCommand<TextureSetStorageCommand>(memory), threaded, renderer); TextureSetStorageCommand.Run(ref GetCommand<TextureSetStorageCommand>(memory), threaded, renderer);

View File

@ -37,6 +37,7 @@
TextureRelease, TextureRelease,
TextureSetData, TextureSetData,
TextureSetDataSlice, TextureSetDataSlice,
TextureSetDataSliceRegion,
TextureSetStorage, TextureSetStorage,
WindowPresent, WindowPresent,

View File

@ -0,0 +1,31 @@
using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources;
using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{
struct TextureSetDataSliceRegionCommand : IGALCommand
{
public CommandType CommandType => CommandType.TextureSetDataSliceRegion;
private TableRef<ThreadedTexture> _texture;
private TableRef<byte[]> _data;
private int _layer;
private int _level;
private Rectangle<int> _region;
public void Set(TableRef<ThreadedTexture> texture, TableRef<byte[]> data, int layer, int level, Rectangle<int> region)
{
_texture = texture;
_data = data;
_layer = layer;
_level = level;
_region = region;
}
public static void Run(ref TextureSetDataSliceRegionCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
ThreadedTexture texture = command._texture.Get(threaded);
texture.Base.SetData(new ReadOnlySpan<byte>(command._data.Get(threaded)), command._layer, command._level, command._region);
}
}
}

View File

@ -119,6 +119,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
_renderer.QueueCommand(); _renderer.QueueCommand();
} }
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
{
_renderer.New<TextureSetDataSliceRegionCommand>().Set(Ref(this), Ref(data.ToArray()), layer, level, region);
_renderer.QueueCommand();
}
public void SetStorage(BufferRange buffer) public void SetStorage(BufferRange buffer)
{ {
_renderer.New<TextureSetStorageCommand>().Set(Ref(this), buffer); _renderer.New<TextureSetStorageCommand>().Set(Ref(this), buffer);

View File

@ -224,7 +224,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
xCount, xCount,
yCount, yCount,
dstLinear, dstLinear,
dst.MemoryLayout); dst.MemoryLayout.UnpackGobBlocksInY(),
dst.MemoryLayout.UnpackGobBlocksInZ());
if (target != null) if (target != null)
{ {

View File

@ -29,6 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
private int _dstHeight; private int _dstHeight;
private int _dstStride; private int _dstStride;
private int _dstGobBlocksInY; private int _dstGobBlocksInY;
private int _dstGobBlocksInZ;
private int _lineLengthIn; private int _lineLengthIn;
private int _lineCount; private int _lineCount;
@ -117,6 +118,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
_dstHeight = (int)state.SetDstHeight; _dstHeight = (int)state.SetDstHeight;
_dstStride = (int)state.PitchOut; _dstStride = (int)state.PitchOut;
_dstGobBlocksInY = 1 << (int)state.SetDstBlockSizeHeight; _dstGobBlocksInY = 1 << (int)state.SetDstBlockSizeHeight;
_dstGobBlocksInZ = 1 << (int)state.SetDstBlockSizeDepth;
_lineLengthIn = (int)state.LineLengthIn; _lineLengthIn = (int)state.LineLengthIn;
_lineCount = (int)state.LineCount; _lineCount = (int)state.LineCount;
@ -176,6 +178,31 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
} }
else else
{ {
// TODO: Verify if the destination X/Y and width/height are taken into account
// for linear texture transfers. If not, we can use the fast path for that aswell.
// Right now the copy code at the bottom assumes that it is used on both which might be incorrect.
if (!_isLinear)
{
var target = memoryManager.Physical.TextureCache.FindTexture(
memoryManager,
_dstGpuVa,
1,
_dstStride,
_dstHeight,
_lineLengthIn,
_lineCount,
_isLinear,
_dstGobBlocksInY,
_dstGobBlocksInZ);
if (target != null)
{
target.SetData(data, 0, 0, new GAL.Rectangle<int>(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount));
return;
}
}
var dstCalculator = new OffsetCalculator( var dstCalculator = new OffsetCalculator(
_dstWidth, _dstWidth,
_dstHeight, _dstHeight,

View File

@ -761,6 +761,24 @@ namespace Ryujinx.Graphics.Gpu.Image
_hasData = true; _hasData = true;
} }
/// <summary>
/// Uploads new texture data to the host GPU for a specific layer/level and 2D sub-region.
/// </summary>
/// <param name="data">New data</param>
/// <param name="layer">Target layer</param>
/// <param name="level">Target level</param>
/// <param name="region">Target sub-region of the texture to update</param>
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
{
BlacklistScale();
HostTexture.SetData(data, layer, level, region);
_currentData = null;
_hasData = true;
}
/// <summary> /// <summary>
/// Converts texture data to a format and layout that is supported by the host GPU. /// Converts texture data to a format and layout that is supported by the host GPU.
/// </summary> /// </summary>

View File

@ -905,7 +905,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="xCount">Number of pixels to be copied per line</param> /// <param name="xCount">Number of pixels to be copied per line</param>
/// <param name="yCount">Number of lines to be copied</param> /// <param name="yCount">Number of lines to be copied</param>
/// <param name="linear">True if the texture has a linear layout, false otherwise</param> /// <param name="linear">True if the texture has a linear layout, false otherwise</param>
/// <param name="memoryLayout">If <paramref name="linear"/> is false, should have the memory layout, otherwise ignored</param> /// <param name="gobBlocksInY">If <paramref name="linear"/> is false, the amount of GOB blocks in the Y axis</param>
/// <param name="gobBlocksInZ">If <paramref name="linear"/> is false, the amount of GOB blocks in the Z axis</param>
/// <returns>A matching texture, or null if there is no match</returns> /// <returns>A matching texture, or null if there is no match</returns>
public Texture FindTexture( public Texture FindTexture(
MemoryManager memoryManager, MemoryManager memoryManager,
@ -916,7 +917,8 @@ namespace Ryujinx.Graphics.Gpu.Image
int xCount, int xCount,
int yCount, int yCount,
bool linear, bool linear,
MemoryLayout memoryLayout) int gobBlocksInY,
int gobBlocksInZ)
{ {
ulong address = memoryManager.Translate(gpuVa); ulong address = memoryManager.Translate(gpuVa);
@ -955,8 +957,8 @@ namespace Ryujinx.Graphics.Gpu.Image
bool sizeMatch = xCount * bpp == texture.Info.Width * format.BytesPerPixel && height == texture.Info.Height; bool sizeMatch = xCount * bpp == texture.Info.Width * format.BytesPerPixel && height == texture.Info.Height;
bool formatMatch = !texture.Info.IsLinear && bool formatMatch = !texture.Info.IsLinear &&
texture.Info.GobBlocksInY == memoryLayout.UnpackGobBlocksInY() && texture.Info.GobBlocksInY == gobBlocksInY &&
texture.Info.GobBlocksInZ == memoryLayout.UnpackGobBlocksInZ(); texture.Info.GobBlocksInZ == gobBlocksInZ;
match = sizeMatch && formatMatch; match = sizeMatch && formatMatch;
} }

View File

@ -58,6 +58,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
throw new NotSupportedException(); throw new NotSupportedException();
} }
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
{
throw new NotSupportedException();
}
public void SetStorage(BufferRange buffer) public void SetStorage(BufferRange buffer)
{ {
if (_buffer != BufferHandle.Null && if (_buffer != BufferHandle.Null &&

View File

@ -1,4 +1,5 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System; using System;
@ -385,7 +386,34 @@ namespace Ryujinx.Graphics.OpenGL.Image
int width = Math.Max(Info.Width >> level, 1); int width = Math.Max(Info.Width >> level, 1);
int height = Math.Max(Info.Height >> level, 1); int height = Math.Max(Info.Height >> level, 1);
ReadFrom2D((IntPtr)ptr, layer, level, width, height); ReadFrom2D((IntPtr)ptr, layer, level, 0, 0, width, height);
}
}
}
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
{
if (Format == Format.S8UintD24Unorm)
{
data = FormatConverter.ConvertS8D24ToD24S8(data);
}
int wInBlocks = BitUtils.DivRoundUp(region.Width, Info.BlockWidth);
int hInBlocks = BitUtils.DivRoundUp(region.Height, Info.BlockHeight);
unsafe
{
fixed (byte* ptr = data)
{
ReadFrom2D(
(IntPtr)ptr,
layer,
level,
region.X,
region.Y,
region.Width,
region.Height,
BitUtils.AlignUp(wInBlocks * Info.BytesPerPixel, 4) * hInBlocks);
} }
} }
} }
@ -397,15 +425,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
public void ReadFromPbo2D(int offset, int layer, int level, int width, int height) public void ReadFromPbo2D(int offset, int layer, int level, int width, int height)
{ {
ReadFrom2D(IntPtr.Zero + offset, layer, level, width, height); ReadFrom2D(IntPtr.Zero + offset, layer, level, 0, 0, width, height);
} }
private void ReadFrom2D(IntPtr data, int layer, int level, int width, int height) private void ReadFrom2D(IntPtr data, int layer, int level, int x, int y, int width, int height)
{
int mipSize = Info.GetMipSize2D(level);
ReadFrom2D(data, layer, level, x, y, width, height, mipSize);
}
private void ReadFrom2D(IntPtr data, int layer, int level, int x, int y, int width, int height, int mipSize)
{ {
TextureTarget target = Target.Convert(); TextureTarget target = Target.Convert();
int mipSize = Info.GetMipSize2D(level);
Bind(target, 0); Bind(target, 0);
FormatInfo format = FormatTable.GetFormatInfo(Info.Format); FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
@ -418,7 +451,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.CompressedTexSubImage1D( GL.CompressedTexSubImage1D(
target, target,
level, level,
0, x,
width, width,
format.PixelFormat, format.PixelFormat,
mipSize, mipSize,
@ -429,7 +462,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.TexSubImage1D( GL.TexSubImage1D(
target, target,
level, level,
0, x,
width, width,
format.PixelFormat, format.PixelFormat,
format.PixelType, format.PixelType,
@ -443,7 +476,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.CompressedTexSubImage2D( GL.CompressedTexSubImage2D(
target, target,
level, level,
0, x,
layer, layer,
width, width,
1, 1,
@ -456,7 +489,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.TexSubImage2D( GL.TexSubImage2D(
target, target,
level, level,
0, x,
layer, layer,
width, width,
1, 1,
@ -472,8 +505,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.CompressedTexSubImage2D( GL.CompressedTexSubImage2D(
target, target,
level, level,
0, x,
0, y,
width, width,
height, height,
format.PixelFormat, format.PixelFormat,
@ -485,8 +518,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.TexSubImage2D( GL.TexSubImage2D(
target, target,
level, level,
0, x,
0, y,
width, width,
height, height,
format.PixelFormat, format.PixelFormat,
@ -503,8 +536,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.CompressedTexSubImage3D( GL.CompressedTexSubImage3D(
target, target,
level, level,
0, x,
0, y,
layer, layer,
width, width,
height, height,
@ -518,8 +551,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.TexSubImage3D( GL.TexSubImage3D(
target, target,
level, level,
0, x,
0, y,
layer, layer,
width, width,
height, height,
@ -536,8 +569,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.CompressedTexSubImage2D( GL.CompressedTexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + layer, TextureTarget.TextureCubeMapPositiveX + layer,
level, level,
0, x,
0, y,
width, width,
height, height,
format.PixelFormat, format.PixelFormat,
@ -549,8 +582,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
GL.TexSubImage2D( GL.TexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + layer, TextureTarget.TextureCubeMapPositiveX + layer,
level, level,
0, x,
0, y,
width, width,
height, height,
format.PixelFormat, format.PixelFormat,

View File

@ -98,6 +98,11 @@ namespace Ryujinx.Graphics.Vulkan
throw new NotSupportedException(); throw new NotSupportedException();
} }
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
{
throw new NotSupportedException();
}
public void SetStorage(BufferRange buffer) public void SetStorage(BufferRange buffer)
{ {
if (_bufferHandle == buffer.Handle && if (_bufferHandle == buffer.Handle &&

View File

@ -819,7 +819,7 @@ namespace Ryujinx.Graphics.Vulkan
var buffer = bufferHolder.GetBuffer(cbs.CommandBuffer).Get(cbs).Value; var buffer = bufferHolder.GetBuffer(cbs.CommandBuffer).Get(cbs).Value;
var image = GetImage().Get(cbs).Value; var image = GetImage().Get(cbs).Value;
CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, size, true, x, y, width, height); CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, size, true, 0, 0, x, y, width, height);
} }
bufferHolder.WaitForFences(); bufferHolder.WaitForFences();
@ -893,7 +893,12 @@ namespace Ryujinx.Graphics.Vulkan
SetData(data, layer, level, 1, 1, singleSlice: true); SetData(data, layer, level, 1, 1, singleSlice: true);
} }
private void SetData(ReadOnlySpan<byte> data, int layer, int level, int layers, int levels, bool singleSlice) public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
{
SetData(data, layer, level, 1, 1, singleSlice: true, region);
}
private void SetData(ReadOnlySpan<byte> data, int layer, int level, int layers, int levels, bool singleSlice, Rectangle<int>? region = null)
{ {
int bufferDataLength = GetBufferDataLength(data.Length); int bufferDataLength = GetBufferDataLength(data.Length);
@ -917,8 +922,26 @@ namespace Ryujinx.Graphics.Vulkan
var buffer = bufferHolder.GetBuffer(cbs.CommandBuffer).Get(cbs).Value; var buffer = bufferHolder.GetBuffer(cbs.CommandBuffer).Get(cbs).Value;
var image = imageAuto.Get(cbs).Value; var image = imageAuto.Get(cbs).Value;
if (region.HasValue)
{
CopyFromOrToBuffer(
cbs.CommandBuffer,
buffer,
image,
bufferDataLength,
false,
layer,
level,
region.Value.X,
region.Value.Y,
region.Value.Width,
region.Value.Height);
}
else
{
CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, bufferDataLength, false, layer, level, layers, levels, singleSlice); CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, bufferDataLength, false, layer, level, layers, levels, singleSlice);
} }
}
private int GetBufferDataLength(int length) private int GetBufferDataLength(int length)
{ {
@ -1059,6 +1082,8 @@ namespace Ryujinx.Graphics.Vulkan
Image image, Image image,
int size, int size,
bool to, bool to,
int dstLayer,
int dstLevel,
int x, int x,
int y, int y,
int width, int width,
@ -1071,13 +1096,21 @@ namespace Ryujinx.Graphics.Vulkan
aspectFlags = ImageAspectFlags.ImageAspectDepthBit; aspectFlags = ImageAspectFlags.ImageAspectDepthBit;
} }
var sl = new ImageSubresourceLayers(aspectFlags, (uint)FirstLevel, (uint)FirstLayer, 1); var sl = new ImageSubresourceLayers(aspectFlags, (uint)(FirstLevel + dstLevel), (uint)(FirstLayer + dstLayer), 1);
var extent = new Extent3D((uint)width, (uint)height, 1); var extent = new Extent3D((uint)width, (uint)height, 1);
int rowLengthAlignment = Info.BlockWidth;
// We expect all data being written into the texture to have a stride aligned by 4.
if (!to && Info.BytesPerPixel < 4)
{
rowLengthAlignment = 4 / Info.BytesPerPixel;
}
var region = new BufferImageCopy( var region = new BufferImageCopy(
0, 0,
(uint)AlignUpNpot(width, Info.BlockWidth), (uint)AlignUpNpot(width, rowLengthAlignment),
(uint)AlignUpNpot(height, Info.BlockHeight), (uint)AlignUpNpot(height, Info.BlockHeight),
sl, sl,
new Offset3D(x, y, 0), new Offset3D(x, y, 0),

View File

@ -14,11 +14,14 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
private ParentalControlFlagValue _parentalControlFlag; private ParentalControlFlagValue _parentalControlFlag;
private int[] _ratingAge; private int[] _ratingAge;
#pragma warning disable CS0414
// TODO: Find where they are set. // TODO: Find where they are set.
private bool _restrictionEnabled = false; private bool _restrictionEnabled = false;
private bool _featuresRestriction = false; private bool _featuresRestriction = false;
private bool _freeCommunicationEnabled = false;
private bool _stereoVisionRestrictionConfigurable = true; private bool _stereoVisionRestrictionConfigurable = true;
private bool _stereoVisionRestriction = false; private bool _stereoVisionRestriction = false;
#pragma warning restore CS0414
public IParentalControlService(ServiceCtx context, ulong pid, bool withInitialize, int permissionFlag) public IParentalControlService(ServiceCtx context, ulong pid, bool withInitialize, int permissionFlag)
{ {
@ -88,13 +91,22 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
return ResultCode.FreeCommunicationDisabled; return ResultCode.FreeCommunicationDisabled;
} }
// NOTE: This sets an internal field to true. Usage have to be determined. _freeCommunicationEnabled = true;
Logger.Stub?.PrintStub(LogClass.ServicePctl); Logger.Stub?.PrintStub(LogClass.ServicePctl);
return ResultCode.Success; return ResultCode.Success;
} }
[CommandHipc(1017)] // 10.0.0+
// EndFreeCommunication()
public ResultCode EndFreeCommunication(ServiceCtx context)
{
_freeCommunicationEnabled = false;
return ResultCode.Success;
}
[CommandHipc(1013)] // 4.0.0+ [CommandHipc(1013)] // 4.0.0+
// ConfirmStereoVisionPermission() // ConfirmStereoVisionPermission()
public ResultCode ConfirmStereoVisionPermission(ServiceCtx context) public ResultCode ConfirmStereoVisionPermission(ServiceCtx context)

View File

@ -219,9 +219,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
int fdsCount = context.RequestData.ReadInt32(); int fdsCount = context.RequestData.ReadInt32();
int timeout = context.RequestData.ReadInt32(); int timeout = context.RequestData.ReadInt32();
(ulong bufferPosition, ulong bufferSize) = context.Request.GetBufferType0x21(); (ulong inputBufferPosition, ulong inputBufferSize) = context.Request.GetBufferType0x21();
(ulong outputBufferPosition, ulong outputBufferSize) = context.Request.GetBufferType0x22();
if (timeout < -1 || fdsCount < 0 || (ulong)(fdsCount * 8) > bufferSize) if (timeout < -1 || fdsCount < 0 || (ulong)(fdsCount * 8) > inputBufferSize)
{ {
return WriteBsdResult(context, -1, LinuxError.EINVAL); return WriteBsdResult(context, -1, LinuxError.EINVAL);
} }
@ -230,7 +231,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
for (int i = 0; i < fdsCount; i++) for (int i = 0; i < fdsCount; i++)
{ {
PollEventData pollEventData = context.Memory.Read<PollEventData>(bufferPosition + (ulong)(i * Unsafe.SizeOf<PollEventData>())); PollEventData pollEventData = context.Memory.Read<PollEventData>(inputBufferPosition + (ulong)(i * Unsafe.SizeOf<PollEventData>()));
IFileDescriptor fileDescriptor = _context.RetrieveFileDescriptor(pollEventData.SocketFd); IFileDescriptor fileDescriptor = _context.RetrieveFileDescriptor(pollEventData.SocketFd);
@ -277,7 +278,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
{ {
bool IsUnexpectedLinuxError(LinuxError error) bool IsUnexpectedLinuxError(LinuxError error)
{ {
return errno != LinuxError.SUCCESS && errno != LinuxError.ETIMEDOUT; return error != LinuxError.SUCCESS && error != LinuxError.ETIMEDOUT;
} }
// Hybrid approach // Hybrid approach
@ -332,7 +333,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
// TODO: Spanify // TODO: Spanify
for (int i = 0; i < fdsCount; i++) for (int i = 0; i < fdsCount; i++)
{ {
context.Memory.Write(bufferPosition + (ulong)(i * Unsafe.SizeOf<PollEventData>()), events[i].Data); context.Memory.Write(outputBufferPosition + (ulong)(i * Unsafe.SizeOf<PollEventData>()), events[i].Data);
} }
return WriteBsdResult(context, updateCount, errno); return WriteBsdResult(context, updateCount, errno);