Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a6cd044f0f | ||
|
f5a1de6ac5 | ||
|
2aeb5b00e3 | ||
|
60ba7b71f2 | ||
|
7c1d2bbb98 | ||
|
beacf8c1c8 | ||
|
0dbe45ae37 | ||
|
2b50e52e48 |
@@ -36,7 +36,7 @@
|
||||
|
||||
## Compatibility
|
||||
|
||||
As of September 2022, Ryujinx has been tested on approximately 3,600 titles; over 3,400 boot past menus and into gameplay, with roughly 2,700 of those being considered playable. You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues).
|
||||
As of October 2022, Ryujinx has been tested on approximately 3,600 titles; over 3,500 boot past menus and into gameplay, with roughly 3,000 of those being considered playable. You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues).
|
||||
Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
||||
|
||||
## Usage
|
||||
|
@@ -295,8 +295,6 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
if (_validTzRegions.Contains(location))
|
||||
{
|
||||
TimeZone = location;
|
||||
|
||||
OnPropertyChanged(nameof(TimeZone));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
||||
InitializeComponent();
|
||||
Load();
|
||||
|
||||
FuncMultiValueConverter<string, string> converter = new(parts => string.Format("{0} {1} {2}", parts.ToArray()));
|
||||
FuncMultiValueConverter<string, string> converter = new(parts => string.Format("{0} {1} {2}", parts.ToArray()).Trim());
|
||||
MultiBinding tzMultiBinding = new() { Converter = converter };
|
||||
tzMultiBinding.Bindings.Add(new Binding("UtcDifference"));
|
||||
tzMultiBinding.Bindings.Add(new Binding("Location"));
|
||||
|
@@ -386,8 +386,25 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_waitable.WaitForFences(_gd.Api, _device, offset, size);
|
||||
}
|
||||
|
||||
private bool BoundToRange(int offset, ref int size)
|
||||
{
|
||||
if (offset >= Size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size = Math.Min(Size - offset, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, int offset, int size)
|
||||
{
|
||||
if (!BoundToRange(offset, ref size))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var key = new I8ToI16CacheKey(_gd);
|
||||
|
||||
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
|
||||
@@ -407,6 +424,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public Auto<DisposableBuffer> GetAlignedVertexBuffer(CommandBufferScoped cbs, int offset, int size, int stride, int alignment)
|
||||
{
|
||||
if (!BoundToRange(offset, ref size))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var key = new AlignedVertexBufferCacheKey(_gd, stride, alignment);
|
||||
|
||||
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
|
||||
@@ -428,6 +450,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public Auto<DisposableBuffer> GetBufferTopologyConversion(CommandBufferScoped cbs, int offset, int size, IndexBufferPattern pattern, int indexSize)
|
||||
{
|
||||
if (!BoundToRange(offset, ref size))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var key = new TopologyConversionCacheKey(_gd, pattern, indexSize);
|
||||
|
||||
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
|
||||
|
@@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public int GetPrimitiveCount(int vertexCount)
|
||||
{
|
||||
return Math.Max(0, ((vertexCount - BaseIndex) + IndexStride - 1) / IndexStride);
|
||||
return Math.Max(0, (vertexCount - BaseIndex) / IndexStride);
|
||||
}
|
||||
|
||||
public int GetConvertedCount(int indexCount)
|
||||
|
@@ -49,7 +49,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
else
|
||||
{
|
||||
autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int _);
|
||||
autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int bufferSize);
|
||||
|
||||
if (_offset >= bufferSize)
|
||||
{
|
||||
autoBuffer = null;
|
||||
}
|
||||
|
||||
offset = _offset;
|
||||
size = _size;
|
||||
|
@@ -95,7 +95,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
using var emptyVb = gd.BufferManager.Create(gd, EmptyVbSize);
|
||||
emptyVb.SetData(0, new byte[EmptyVbSize]);
|
||||
_vertexBuffers[0] = new VertexBufferState(emptyVb.GetBuffer(), 0, EmptyVbSize, 0);
|
||||
_vertexBuffers[0] = new VertexBufferState(emptyVb.GetBuffer(), 0, 0, EmptyVbSize, 0);
|
||||
_vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length);
|
||||
|
||||
ClearScissor = new Rectangle<int>(0, 0, 0xffff, 0xffff);
|
||||
@@ -1243,7 +1243,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
_vertexBuffers[i].BindVertexBuffer(Gd, Cbs, (uint)i, ref _newState);
|
||||
|
||||
_vertexBuffersDirty &= ~(1u << i);
|
||||
_vertexBuffersDirty &= ~(1UL << i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -515,10 +515,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
dst.Info,
|
||||
srcRegion,
|
||||
dstRegion,
|
||||
src.FirstLevel,
|
||||
dst.FirstLevel,
|
||||
src.FirstLayer,
|
||||
dst.FirstLayer,
|
||||
src.FirstLevel,
|
||||
dst.FirstLevel,
|
||||
layers,
|
||||
levels,
|
||||
linearFilter,
|
||||
|
@@ -57,37 +57,48 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
if (gd.NeedsVertexBufferAlignment(AttributeScalarAlignment, out int alignment) && (_stride % alignment) != 0)
|
||||
{
|
||||
autoBuffer = gd.BufferManager.GetAlignedVertexBuffer(cbs, _handle, _offset, _size, _stride, alignment);
|
||||
int stride = (_stride + (alignment - 1)) & -alignment;
|
||||
|
||||
var buffer = autoBuffer.Get(cbs, _offset, _size).Value;
|
||||
if (autoBuffer != null)
|
||||
{
|
||||
int stride = (_stride + (alignment - 1)) & -alignment;
|
||||
int newSize = (_size / _stride) * stride;
|
||||
|
||||
if (gd.Capabilities.SupportsExtendedDynamicState)
|
||||
{
|
||||
gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
|
||||
cbs.CommandBuffer,
|
||||
binding,
|
||||
1,
|
||||
buffer,
|
||||
0,
|
||||
(ulong)(_size / _stride) * (ulong)stride,
|
||||
(ulong)stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, 0);
|
||||
var buffer = autoBuffer.Get(cbs, 0, newSize).Value;
|
||||
|
||||
if (gd.Capabilities.SupportsExtendedDynamicState)
|
||||
{
|
||||
gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
|
||||
cbs.CommandBuffer,
|
||||
binding,
|
||||
1,
|
||||
buffer,
|
||||
0,
|
||||
(ulong)newSize,
|
||||
(ulong)stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, 0);
|
||||
}
|
||||
|
||||
_buffer = autoBuffer;
|
||||
}
|
||||
|
||||
_buffer = autoBuffer;
|
||||
state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)stride;
|
||||
state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride;
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int _);
|
||||
autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int size);
|
||||
|
||||
// The original stride must be reapplied in case it was rewritten.
|
||||
state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride;
|
||||
|
||||
if (_offset >= size)
|
||||
{
|
||||
autoBuffer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2540,11 +2540,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||
|
||||
for (int attempt = 0; attempt < 8; attempt++)
|
||||
{
|
||||
address = BitUtils.AlignDown(regionStart + GetRandomValue(0, aslrMaxOffset) * (ulong)alignment, alignment);
|
||||
ulong aslrAddress = BitUtils.AlignDown(regionStart + GetRandomValue(0, aslrMaxOffset) * (ulong)alignment, alignment);
|
||||
ulong aslrEndAddr = aslrAddress + totalNeededSize;
|
||||
|
||||
ulong endAddr = address + totalNeededSize;
|
||||
|
||||
KMemoryInfo info = _blockManager.FindBlock(address).GetInfo();
|
||||
KMemoryInfo info = _blockManager.FindBlock(aslrAddress).GetInfo();
|
||||
|
||||
if (info.State != MemoryState.Unmapped)
|
||||
{
|
||||
@@ -2554,11 +2553,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||
ulong currBaseAddr = info.Address + reservedPagesCount * PageSize;
|
||||
ulong currEndAddr = info.Address + info.Size;
|
||||
|
||||
if (address >= regionStart &&
|
||||
address >= currBaseAddr &&
|
||||
endAddr - 1 <= regionEndAddr - 1 &&
|
||||
endAddr - 1 <= currEndAddr - 1)
|
||||
if (aslrAddress >= regionStart &&
|
||||
aslrAddress >= currBaseAddr &&
|
||||
aslrEndAddr - 1 <= regionEndAddr - 1 &&
|
||||
aslrEndAddr - 1 <= currEndAddr - 1)
|
||||
{
|
||||
address = aslrAddress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2603,7 +2603,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||
|
||||
ulong totalNeededSize = reservedSize + neededPagesCount * PageSize;
|
||||
|
||||
ulong regionEndAddr = regionStart + regionPagesCount * PageSize;
|
||||
ulong regionEndAddr = (regionStart + regionPagesCount * PageSize) - 1;
|
||||
|
||||
KMemoryBlock currBlock = _blockManager.FindBlock(regionStart);
|
||||
|
||||
|
@@ -12,6 +12,7 @@ using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using static Ryujinx.HLE.Utilities.StringUtils;
|
||||
@@ -787,6 +788,26 @@ namespace Ryujinx.HLE.HOS.Services.Fs
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(205)]
|
||||
// OpenDataStorageWithProgramIndex(u8 program_index) -> object<nn::fssrv::sf::IStorage>
|
||||
public ResultCode OpenDataStorageWithProgramIndex(ServiceCtx context)
|
||||
{
|
||||
byte programIndex = context.RequestData.ReadByte();
|
||||
|
||||
if ((context.Device.Application.TitleId & 0xf) != programIndex)
|
||||
{
|
||||
throw new NotImplementedException($"Accessing storage from other programs is not supported (program index = {programIndex}).");
|
||||
}
|
||||
|
||||
var storage = context.Device.FileSystem.RomFs.AsStorage(true);
|
||||
using var sharedStorage = new SharedRef<LibHac.Fs.IStorage>(storage);
|
||||
using var sfStorage = new SharedRef<IStorage>(new StorageInterfaceAdapter(ref sharedStorage.Ref()));
|
||||
|
||||
MakeObject(context, new FileSystemProxy.IStorage(ref sfStorage.Ref()));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(400)]
|
||||
// OpenDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage> dataStorage
|
||||
public ResultCode OpenDeviceOperator(ServiceCtx context)
|
||||
|
@@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
||||
|
||||
public bool Evaluate()
|
||||
{
|
||||
return (_input.Value & _mask) != 0;
|
||||
return (_input.Value & _mask) == _mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user