From 0a0a95fd815ad5726783ba10d4d5d9910a0bab73 Mon Sep 17 00:00:00 2001 From: edisionnano Date: Wed, 26 Jan 2022 00:31:04 +0200 Subject: [PATCH 01/14] Convert Octal-Mode to Decimal (#3041) Apparently C# doesn't use 0 as a prefix like C does. --- Ryujinx/Modules/Updater/Updater.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ryujinx/Modules/Updater/Updater.cs b/Ryujinx/Modules/Updater/Updater.cs index 4a96208fa..f3a250158 100644 --- a/Ryujinx/Modules/Updater/Updater.cs +++ b/Ryujinx/Modules/Updater/Updater.cs @@ -396,7 +396,7 @@ namespace Ryujinx.Modules if (!OperatingSystem.IsWindows()) { - chmod(ryuBin, 0777); + chmod(ryuBin, 493); } } From fd6d3ec88fd7233190388ae6eefd9dc2488453a0 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Thu, 27 Jan 2022 17:17:13 +0000 Subject: [PATCH 02/14] Fix res scale parameters not being updated in vertex shader (#3046) This fixes an issue where the render scale array would not be updated when technically the scales on the flat array were the same, but the start index for the vertex scales was different. --- .../Image/TextureBindingsManager.cs | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs index 97a9eee43..7ac4e12e2 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs @@ -49,6 +49,7 @@ namespace Ryujinx.Graphics.Gpu.Image private readonly float[] _scales; private bool _scaleChanged; + private int _lastFragmentTotal; /// /// Constructs a new instance of the texture bindings manager. @@ -288,26 +289,30 @@ namespace Ryujinx.Graphics.Gpu.Image /// private void CommitRenderScale() { + // Stage 0 total: Compute or Vertex. + int total = _textureBindingsCount[0] + _imageBindingsCount[0]; + + int fragmentIndex = (int)ShaderStage.Fragment - 1; + int fragmentTotal = _isCompute ? 0 : (_textureBindingsCount[fragmentIndex] + _imageBindingsCount[fragmentIndex]); + + if (total != 0 && fragmentTotal != _lastFragmentTotal) + { + // Must update scales in the support buffer if: + // - Vertex stage has bindings. + // - Fragment stage binding count has been updated since last render scale update. + + _scaleChanged = true; + } + if (_scaleChanged) { - int fragmentTotal = 0; - int total; - if (!_isCompute) { - int fragmentIndex = (int)ShaderStage.Fragment - 1; - fragmentTotal = _textureBindingsCount[fragmentIndex] + _imageBindingsCount[fragmentIndex]; - - int vertexIndex = (int)ShaderStage.Vertex - 1; - int vertexTotal = _textureBindingsCount[vertexIndex] + _imageBindingsCount[vertexIndex]; - - total = fragmentTotal + vertexTotal; - } - else - { - total = _textureBindingsCount[0] + _imageBindingsCount[0]; + total += fragmentTotal; // Add the fragment bindings to the total. } + _lastFragmentTotal = fragmentTotal; + _context.Renderer.Pipeline.UpdateRenderScale(_scales, total, fragmentTotal); _scaleChanged = false; From c52158b73361bd25364c23c2b39780d2e626c858 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Thu, 27 Jan 2022 21:50:32 +0000 Subject: [PATCH 03/14] Add timestamp to 16-byte/4-word semaphore releases. (#3049) * Add timestamp to 16-byte semaphore releases. BOTW was reading a ulong 8 bytes after a semaphore return. Turns out this is the timestamp it was trying to do performance calculation with, so I've made it write when necessary. This mode was also added to the DMA semaphore I added recently, as it is required by a few games. (i think quake?) The timestamp code has been moved to GPU context. Check other games with an unusually low framerate cap or dynamic resolution to see if they have improved. * Cast dma semaphore payload to ulong to fill the space * Write timestamp first Might be just worrying too much, but we don't want the applcation reading timestamp if it sees the payload before timestamp is written. --- Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs | 3 +- .../Engine/GPFifo/GPFifoClass.cs | 6 +++ .../Engine/Threed/SemaphoreUpdater.cs | 38 +--------------- Ryujinx.Graphics.Gpu/GpuContext.cs | 44 +++++++++++++++++++ 4 files changed, 54 insertions(+), 37 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs b/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs index 44964b8fd..763391b40 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs @@ -115,7 +115,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma } else /* if (type == LaunchDmaSemaphoreType.ReleaseFourWordSemaphore) */ { - Logger.Warning?.Print(LogClass.Gpu, "DMA semaphore type ReleaseFourWordSemaphore was used, but is not currently implemented."); + _channel.MemoryManager.Write(address + 8, _context.GetTimestamp()); + _channel.MemoryManager.Write(address, (ulong)_state.State.SetSemaphorePayload); } } } diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs index dab4e9db6..686c2a9b6 100644 --- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs +++ b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoClass.cs @@ -75,6 +75,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo SemaphoredOperation operation = _state.State.SemaphoredOperation; + if (_state.State.SemaphoredReleaseSize == SemaphoredReleaseSize.SixteenBytes) + { + _parent.MemoryManager.Write(address + 4, 0); + _parent.MemoryManager.Write(address + 8, _context.GetTimestamp()); + } + // TODO: Acquire operations (Wait), interrupts for invalid combinations. if (operation == SemaphoredOperation.Release) { diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/SemaphoreUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/SemaphoreUpdater.cs index cb0d593db..986c02aba 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Threed/SemaphoreUpdater.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Threed/SemaphoreUpdater.cs @@ -1,6 +1,4 @@ -using Ryujinx.Common; -using Ryujinx.Graphics.GAL; -using System.Runtime.InteropServices; +using Ryujinx.Graphics.GAL; namespace Ryujinx.Graphics.Gpu.Engine.Threed { @@ -9,9 +7,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// class SemaphoreUpdater { - private const int NsToTicksFractionNumerator = 384; - private const int NsToTicksFractionDenominator = 625; - /// /// GPU semaphore operation. /// @@ -154,14 +149,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed { ulong gpuVa = _state.State.SemaphoreAddress.Pack(); - ulong ticks = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds); - - if (GraphicsConfig.FastGpuTime) - { - // Divide by some amount to report time as if operations were performed faster than they really are. - // This can prevent some games from switching to a lower resolution because rendering is too slow. - ticks /= 256; - } + ulong ticks = _context.GetTimestamp(); ICounterEvent counter = null; @@ -197,27 +185,5 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed _channel.MemoryManager.CounterCache.AddOrUpdate(gpuVa, counter); } - - /// - /// Converts a nanoseconds timestamp value to Maxwell time ticks. - /// - /// - /// The frequency is 614400000 Hz. - /// - /// Timestamp in nanoseconds - /// Maxwell ticks - private static ulong ConvertNanosecondsToTicks(ulong nanoseconds) - { - // We need to divide first to avoid overflows. - // We fix up the result later by calculating the difference and adding - // that to the result. - ulong divided = nanoseconds / NsToTicksFractionDenominator; - - ulong rounded = divided * NsToTicksFractionDenominator; - - ulong errorBias = (nanoseconds - rounded) * NsToTicksFractionNumerator / NsToTicksFractionDenominator; - - return divided * NsToTicksFractionNumerator + errorBias; - } } } diff --git a/Ryujinx.Graphics.Gpu/GpuContext.cs b/Ryujinx.Graphics.Gpu/GpuContext.cs index ddc95b2c0..8ea7c91fb 100644 --- a/Ryujinx.Graphics.Gpu/GpuContext.cs +++ b/Ryujinx.Graphics.Gpu/GpuContext.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Engine.GPFifo; using Ryujinx.Graphics.Gpu.Memory; @@ -15,6 +16,9 @@ namespace Ryujinx.Graphics.Gpu /// public sealed class GpuContext : IDisposable { + private const int NsToTicksFractionNumerator = 384; + private const int NsToTicksFractionDenominator = 625; + /// /// Event signaled when the host emulation context is ready to be used by the gpu context. /// @@ -180,6 +184,46 @@ namespace Ryujinx.Graphics.Gpu } } + /// + /// Converts a nanoseconds timestamp value to Maxwell time ticks. + /// + /// + /// The frequency is 614400000 Hz. + /// + /// Timestamp in nanoseconds + /// Maxwell ticks + private static ulong ConvertNanosecondsToTicks(ulong nanoseconds) + { + // We need to divide first to avoid overflows. + // We fix up the result later by calculating the difference and adding + // that to the result. + ulong divided = nanoseconds / NsToTicksFractionDenominator; + + ulong rounded = divided * NsToTicksFractionDenominator; + + ulong errorBias = (nanoseconds - rounded) * NsToTicksFractionNumerator / NsToTicksFractionDenominator; + + return divided * NsToTicksFractionNumerator + errorBias; + } + + /// + /// Gets the value of the GPU timer. + /// + /// The current GPU timestamp + public ulong GetTimestamp() + { + ulong ticks = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds); + + if (GraphicsConfig.FastGpuTime) + { + // Divide by some amount to report time as if operations were performed faster than they really are. + // This can prevent some games from switching to a lower resolution because rendering is too slow. + ticks /= 256; + } + + return ticks; + } + /// /// Shader cache state update handler. /// From 20ce37dee6158ede18ad699338ecea083728423b Mon Sep 17 00:00:00 2001 From: Mary Date: Sat, 29 Jan 2022 22:18:03 +0100 Subject: [PATCH 04/14] kernel: A bit of refactoring and fix GetThreadContext3 correctness (#3042) * Start refactoring kernel a bit and import some changes from kernel decoupling PR * kernel: Put output always at the start in Syscall functions * kernel: Rewrite GetThreadContext3 to use a structure and to be accurate * kernel: make KernelTransfer use generic types and simplify * Fix some warning and do not use getters on MemoryInfo * Address gdkchan's comment * GetThreadContext3: use correct pause flag --- .../HOS/Kernel/Common/KernelTransfer.cs | 56 ++-- .../HOS/Kernel/Memory/KPageTableBase.cs | 6 +- .../HOS/Kernel/Memory/MemoryPermission.cs | 5 +- Ryujinx.HLE/HOS/Kernel/Memory/MemoryState.cs | 1 + Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 8 +- .../Kernel/Process/KProcessCapabilities.cs | 12 +- .../SupervisorCall/InvalidSvcException.cs | 2 +- .../HOS/Kernel/SupervisorCall/MemoryInfo.cs | 37 +++ .../HOS/Kernel/SupervisorCall/Syscall.cs | 284 +++++++----------- .../HOS/Kernel/SupervisorCall/Syscall32.cs | 70 ++--- .../HOS/Kernel/SupervisorCall/Syscall64.cs | 68 ++--- .../Kernel/SupervisorCall/ThreadContext.cs | 22 ++ .../HOS/Kernel/Threading/KAddressArbiter.cs | 14 +- Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | 108 ++++++- Ryujinx.HLE/HOS/Services/IpcService.cs | 2 +- Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs | 2 +- Ryujinx.HLE/HOS/Services/ServerBase.cs | 10 +- 17 files changed, 386 insertions(+), 321 deletions(-) create mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/MemoryInfo.cs create mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/ThreadContext.cs diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs b/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs index 53e539a23..cbc276c50 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs @@ -1,54 +1,50 @@ using Ryujinx.Cpu; using Ryujinx.HLE.HOS.Kernel.Process; using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace Ryujinx.HLE.HOS.Kernel.Common { static class KernelTransfer { - public static bool UserToKernelInt32(KernelContext context, ulong address, out int value) + public static bool UserToKernel(out T value, ulong address) where T : unmanaged { KProcess currentProcess = KernelStatic.GetCurrentProcess(); - if (currentProcess.CpuMemory.IsMapped(address) && - currentProcess.CpuMemory.IsMapped(address + 3)) + if (currentProcess.CpuMemory.IsRangeMapped(address, (ulong)Unsafe.SizeOf())) { - value = currentProcess.CpuMemory.Read(address); + value = currentProcess.CpuMemory.Read(address); return true; } - value = 0; + value = default; return false; } - public static bool UserToKernelInt32Array(KernelContext context, ulong address, Span values) + public static bool UserToKernelArray(ulong address, Span values) where T : unmanaged { KProcess currentProcess = KernelStatic.GetCurrentProcess(); - for (int index = 0; index < values.Length; index++, address += 4) + Span data = MemoryMarshal.Cast(values); + + if (currentProcess.CpuMemory.IsRangeMapped(address, (ulong)data.Length)) { - if (currentProcess.CpuMemory.IsMapped(address) && - currentProcess.CpuMemory.IsMapped(address + 3)) - { - values[index]= currentProcess.CpuMemory.Read(address); - } - else - { - return false; - } + currentProcess.CpuMemory.Read(address, data); + + return true; } - return true; + return false; } - public static bool UserToKernelString(KernelContext context, ulong address, int size, out string value) + public static bool UserToKernelString(out string value, ulong address, uint size) { KProcess currentProcess = KernelStatic.GetCurrentProcess(); - if (currentProcess.CpuMemory.IsMapped(address) && - currentProcess.CpuMemory.IsMapped(address + (ulong)size - 1)) + if (currentProcess.CpuMemory.IsRangeMapped(address, size)) { value = MemoryHelper.ReadAsciiString(currentProcess.CpuMemory, address, size); @@ -60,27 +56,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Common return false; } - public static bool KernelToUserInt32(KernelContext context, ulong address, int value) + public static bool KernelToUser(ulong address, T value) where T: unmanaged { KProcess currentProcess = KernelStatic.GetCurrentProcess(); - if (currentProcess.CpuMemory.IsMapped(address) && - currentProcess.CpuMemory.IsMapped(address + 3)) - { - currentProcess.CpuMemory.Write(address, value); - - return true; - } - - return false; - } - - public static bool KernelToUserInt64(KernelContext context, ulong address, long value) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - if (currentProcess.CpuMemory.IsMapped(address) && - currentProcess.CpuMemory.IsMapped(address + 7)) + if (currentProcess.CpuMemory.IsRangeMapped(address, (ulong)Unsafe.SizeOf())) { currentProcess.CpuMemory.Write(address, value); diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs index ff87ecb79..fb3d669de 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -2682,7 +2682,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return Context.MemoryManager.MemoryRegions[(int)_memRegion]; } - public long GetMmUsedPages() + public ulong GetMmUsedPages() { lock (_blockManager) { @@ -2690,9 +2690,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } } - private long GetMmUsedSize() + private ulong GetMmUsedSize() { - return _blockManager.BlocksCount * KMemoryBlockSize; + return (ulong)(_blockManager.BlocksCount * KMemoryBlockSize); } public bool IsInvalidRegion(ulong address, ulong size) diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs index 12300e4f7..563b817d8 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs @@ -5,8 +5,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory [Flags] enum KMemoryPermission : uint { - None = 0, - Mask = uint.MaxValue, + None = 0, + UserMask = Read | Write | Execute, + Mask = uint.MaxValue, Read = 1 << 0, Write = 1 << 1, diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/MemoryState.cs b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryState.cs index f7161a88c..d3b61780c 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/MemoryState.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryState.cs @@ -26,6 +26,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory KernelStack = 0x00002013, CodeReadOnly = 0x00402214, CodeWritable = 0x00402015, + UserMask = 0xff, Mask = 0xffffffff, PermissionChangeAllowed = 1 << 8, diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index be45f02aa..20b3a4973 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public KAddressArbiter AddressArbiter { get; private set; } - public long[] RandomEntropy { get; private set; } + public ulong[] RandomEntropy { get; private set; } public KThread[] PinnedThreads { get; private set; } private bool _signaled; @@ -102,7 +102,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process Capabilities = new KProcessCapabilities(); - RandomEntropy = new long[KScheduler.CpuCoresCount]; + RandomEntropy = new ulong[KScheduler.CpuCoresCount]; PinnedThreads = new KThread[KScheduler.CpuCoresCount]; // TODO: Remove once we no longer need to initialize it externally. @@ -868,12 +868,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public bool IsCpuCoreAllowed(int core) { - return (Capabilities.AllowedCpuCoresMask & (1L << core)) != 0; + return (Capabilities.AllowedCpuCoresMask & (1UL << core)) != 0; } public bool IsPriorityAllowed(int priority) { - return (Capabilities.AllowedThreadPriosMask & (1L << priority)) != 0; + return (Capabilities.AllowedThreadPriosMask & (1UL << priority)) != 0; } public override bool IsSignaled() diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs index 28944c4f5..55e839ab0 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs @@ -11,8 +11,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public byte[] SvcAccessMask { get; private set; } public byte[] IrqAccessMask { get; private set; } - public long AllowedCpuCoresMask { get; private set; } - public long AllowedThreadPriosMask { get; private set; } + public ulong AllowedCpuCoresMask { get; private set; } + public ulong AllowedThreadPriosMask { get; private set; } public int DebuggingFlags { get; private set; } public int HandleTableSize { get; private set; } @@ -28,7 +28,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public KernelResult InitializeForKernel(ReadOnlySpan capabilities, KPageTableBase memoryManager) { AllowedCpuCoresMask = 0xf; - AllowedThreadPriosMask = -1; + AllowedThreadPriosMask = ulong.MaxValue; DebuggingFlags &= ~3; KernelReleaseVersion = KProcess.KernelVersionPacked; @@ -303,16 +303,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return KernelResult.Success; } - private static long GetMaskFromMinMax(int min, int max) + private static ulong GetMaskFromMinMax(int min, int max) { int range = max - min + 1; if (range == 64) { - return -1L; + return ulong.MaxValue; } - long mask = (1L << range) - 1; + ulong mask = (1UL << range) - 1; return mask << min; } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InvalidSvcException.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InvalidSvcException.cs index b78a22847..f2e28bb7b 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InvalidSvcException.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InvalidSvcException.cs @@ -2,7 +2,7 @@ using System; namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { - public class InvalidSvcException : Exception + class InvalidSvcException : Exception { public InvalidSvcException(string message) : base(message) { } } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/MemoryInfo.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/MemoryInfo.cs new file mode 100644 index 000000000..a71cce1fe --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/MemoryInfo.cs @@ -0,0 +1,37 @@ +using Ryujinx.HLE.HOS.Kernel.Memory; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + struct MemoryInfo + { + public ulong Address; + public ulong Size; + public MemoryState State; + public MemoryAttribute Attribute; + public KMemoryPermission Permission; + public int IpcRefCount; + public int DeviceRefCount; +#pragma warning disable CS0414 + private int _padding; +#pragma warning restore CS0414 + + public MemoryInfo( + ulong address, + ulong size, + MemoryState state, + MemoryAttribute attribute, + KMemoryPermission permission, + int ipcRefCount, + int deviceRefCount) + { + Address = address; + Size = size; + State = state; + Attribute = attribute; + Permission = permission; + IpcRefCount = ipcRefCount; + DeviceRefCount = deviceRefCount; + _padding = 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index 2dd9d8070..c022d6e29 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall // Process - public KernelResult GetProcessId(int handle, out long pid) + public KernelResult GetProcessId(out long pid, int handle) { KProcess currentProcess = KernelStatic.GetCurrentProcess(); @@ -50,9 +50,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall } public KernelResult CreateProcess( + out int handle, ProcessCreationInfo info, ReadOnlySpan capabilities, - out int handle, IProcessContextFactory contextFactory, ThreadStart customThreadStart = null) { @@ -170,19 +170,19 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall // IPC - public KernelResult ConnectToNamedPort(ulong namePtr, out int handle) + public KernelResult ConnectToNamedPort(out int handle, ulong namePtr) { handle = 0; - if (!KernelTransfer.UserToKernelString(_context, namePtr, 12, out string name)) + if (!KernelTransfer.UserToKernelString(out string name, namePtr, 12)) { return KernelResult.UserCopyFailed; } - return ConnectToNamedPort(name, out handle); + return ConnectToNamedPort(out handle, name); } - public KernelResult ConnectToNamedPort(string name, out int handle) + public KernelResult ConnectToNamedPort(out int handle, string name) { handle = 0; @@ -193,7 +193,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall KAutoObject autoObj = KAutoObject.FindNamedObject(_context, name); - if (!(autoObj is KClientPort clientPort)) + if (autoObj is not KClientPort clientPort) { return KernelResult.NotFound; } @@ -284,7 +284,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return result; } - public KernelResult SendAsyncRequestWithUserBuffer(ulong messagePtr, ulong messageSize, int handle, out int doneEventHandle) + public KernelResult SendAsyncRequestWithUserBuffer(out int doneEventHandle, ulong messagePtr, ulong messageSize, int handle) { doneEventHandle = 0; @@ -355,10 +355,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall } public KernelResult CreateSession( - bool isLight, - ulong namePtr, out int serverSessionHandle, - out int clientSessionHandle) + out int clientSessionHandle, + bool isLight, + ulong namePtr) { serverSessionHandle = 0; clientSessionHandle = 0; @@ -420,7 +420,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return result; } - public KernelResult AcceptSession(int portHandle, out int sessionHandle) + public KernelResult AcceptSession(out int sessionHandle, int portHandle) { sessionHandle = 0; @@ -472,11 +472,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall } public KernelResult ReplyAndReceive( + out int handleIndex, ulong handlesPtr, int handlesCount, int replyTargetHandle, - long timeout, - out int handleIndex) + long timeout) { handleIndex = 0; @@ -501,7 +501,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall int[] handles = new int[handlesCount]; - if (!KernelTransfer.UserToKernelInt32Array(_context, handlesPtr, handles)) + if (!KernelTransfer.UserToKernelArray(handlesPtr, handles)) { return KernelResult.UserCopyFailed; } @@ -511,10 +511,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall timeout += KTimeManager.DefaultTimeIncrementNanoseconds; } - return ReplyAndReceive(handles, replyTargetHandle, timeout, out handleIndex); + return ReplyAndReceive(out handleIndex, handles, replyTargetHandle, timeout); } - public KernelResult ReplyAndReceive(ReadOnlySpan handles, int replyTargetHandle, long timeout, out int handleIndex) + public KernelResult ReplyAndReceive(out int handleIndex, ReadOnlySpan handles, int replyTargetHandle, long timeout) { handleIndex = 0; @@ -577,13 +577,13 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall } public KernelResult ReplyAndReceiveWithUserBuffer( + out int handleIndex, ulong handlesPtr, ulong messagePtr, ulong messageSize, int handlesCount, int replyTargetHandle, - long timeout, - out int handleIndex) + long timeout) { handleIndex = 0; @@ -615,7 +615,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall int[] handles = new int[handlesCount]; - if (!KernelTransfer.UserToKernelInt32Array(_context, handlesPtr, handles)) + if (!KernelTransfer.UserToKernelArray(handlesPtr, handles)) { currentProcess.MemoryManager.UnborrowIpcBuffer(messagePtr, messageSize); @@ -681,11 +681,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall } public KernelResult CreatePort( + out int serverPortHandle, + out int clientPortHandle, int maxSessions, bool isLight, - ulong namePtr, - out int serverPortHandle, - out int clientPortHandle) + ulong namePtr) { serverPortHandle = clientPortHandle = 0; @@ -715,11 +715,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return result; } - public KernelResult ManageNamedPort(ulong namePtr, int maxSessions, out int handle) + public KernelResult ManageNamedPort(out int handle, ulong namePtr, int maxSessions) { handle = 0; - if (!KernelTransfer.UserToKernelString(_context, namePtr, 12, out string name)) + if (!KernelTransfer.UserToKernelString(out string name, namePtr, 12)) { return KernelResult.UserCopyFailed; } @@ -729,10 +729,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.MaximumExceeded; } - return ManageNamedPort(name, maxSessions, out handle); + return ManageNamedPort(out handle, name, maxSessions); } - public KernelResult ManageNamedPort(string name, int maxSessions, out int handle) + public KernelResult ManageNamedPort(out int handle, string name, int maxSessions) { handle = 0; @@ -767,7 +767,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return result; } - public KernelResult ConnectToPort(int clientPortHandle, out int clientSessionHandle) + public KernelResult ConnectToPort(out int clientSessionHandle, int clientPortHandle) { clientSessionHandle = 0; @@ -820,18 +820,18 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall // Memory - public KernelResult SetHeapSize(ulong size, out ulong position) + public KernelResult SetHeapSize(out ulong address, ulong size) { if ((size & 0xfffffffe001fffff) != 0) { - position = 0; + address = 0; return KernelResult.InvalidSize; } KProcess process = KernelStatic.GetCurrentProcess(); - return process.MemoryManager.SetHeapSize(size, out position); + return process.MemoryManager.SetHeapSize(size, out address); } public KernelResult SetMemoryPermission(ulong address, ulong size, KMemoryPermission permission) @@ -867,12 +867,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall } public KernelResult SetMemoryAttribute( - ulong position, + ulong address, ulong size, MemoryAttribute attributeMask, MemoryAttribute attributeValue) { - if (!PageAligned(position)) + if (!PageAligned(address)) { return KernelResult.InvalidAddress; } @@ -892,13 +892,13 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall KProcess process = KernelStatic.GetCurrentProcess(); - if (!process.MemoryManager.InsideAddrSpace(position, size)) + if (!process.MemoryManager.InsideAddrSpace(address, size)) { return KernelResult.InvalidMemState; } KernelResult result = process.MemoryManager.SetMemoryAttribute( - position, + address, size, attributeMask, attributeValue); @@ -978,20 +978,34 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return process.MemoryManager.Unmap(dst, src, size); } - public KernelResult QueryMemory(ulong infoPtr, ulong position, out ulong pageInfo) + public KernelResult QueryMemory(ulong infoPtr, out ulong pageInfo, ulong address) + { + KernelResult result = QueryMemory(out MemoryInfo info, out pageInfo, address); + + if (result == KernelResult.Success) + { + return KernelTransfer.KernelToUser(infoPtr, info) + ? KernelResult.Success + : KernelResult.InvalidMemState; + } + + return result; + } + + public KernelResult QueryMemory(out MemoryInfo info, out ulong pageInfo, ulong address) { KProcess process = KernelStatic.GetCurrentProcess(); - KMemoryInfo blkInfo = process.MemoryManager.QueryMemory(position); + KMemoryInfo blockInfo = process.MemoryManager.QueryMemory(address); - process.CpuMemory.Write(infoPtr + 0x00, blkInfo.Address); - process.CpuMemory.Write(infoPtr + 0x08, blkInfo.Size); - process.CpuMemory.Write(infoPtr + 0x10, (int)blkInfo.State & 0xff); - process.CpuMemory.Write(infoPtr + 0x14, (int)blkInfo.Attribute); - process.CpuMemory.Write(infoPtr + 0x18, (int)blkInfo.Permission); - process.CpuMemory.Write(infoPtr + 0x1c, blkInfo.IpcRefCount); - process.CpuMemory.Write(infoPtr + 0x20, blkInfo.DeviceRefCount); - process.CpuMemory.Write(infoPtr + 0x24, 0); + info = new MemoryInfo( + blockInfo.Address, + blockInfo.Size, + blockInfo.State & MemoryState.UserMask, + blockInfo.Attribute, + blockInfo.Permission & KMemoryPermission.UserMask, + blockInfo.IpcRefCount, + blockInfo.DeviceRefCount); pageInfo = 0; @@ -1084,7 +1098,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall currentProcess); } - public KernelResult CreateTransferMemory(ulong address, ulong size, KMemoryPermission permission, out int handle) + public KernelResult CreateTransferMemory(out int handle, ulong address, ulong size, KMemoryPermission permission) { handle = 0; @@ -1414,9 +1428,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission); } - private static bool PageAligned(ulong position) + private static bool PageAligned(ulong address) { - return (position & (KPageTableBase.PageSize - 1)) == 0; + return (address & (KPageTableBase.PageSize - 1)) == 0; } // System @@ -1575,7 +1589,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall Logger.Warning?.Print(LogClass.KernelSvc, str); } - public KernelResult GetInfo(InfoType id, int handle, long subId, out long value) + public KernelResult GetInfo(out ulong value, InfoType id, int handle, long subId) { value = 0; @@ -1621,30 +1635,30 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall case InfoType.CoreMask: value = process.Capabilities.AllowedCpuCoresMask; break; case InfoType.PriorityMask: value = process.Capabilities.AllowedThreadPriosMask; break; - case InfoType.AliasRegionAddress: value = (long)process.MemoryManager.AliasRegionStart; break; + case InfoType.AliasRegionAddress: value = process.MemoryManager.AliasRegionStart; break; case InfoType.AliasRegionSize: - value = (long)(process.MemoryManager.AliasRegionEnd - - process.MemoryManager.AliasRegionStart); break; + value = (process.MemoryManager.AliasRegionEnd - + process.MemoryManager.AliasRegionStart); break; - case InfoType.HeapRegionAddress: value = (long)process.MemoryManager.HeapRegionStart; break; + case InfoType.HeapRegionAddress: value = process.MemoryManager.HeapRegionStart; break; case InfoType.HeapRegionSize: - value = (long)(process.MemoryManager.HeapRegionEnd - - process.MemoryManager.HeapRegionStart); break; + value = (process.MemoryManager.HeapRegionEnd - + process.MemoryManager.HeapRegionStart); break; - case InfoType.TotalMemorySize: value = (long)process.GetMemoryCapacity(); break; + case InfoType.TotalMemorySize: value = process.GetMemoryCapacity(); break; - case InfoType.UsedMemorySize: value = (long)process.GetMemoryUsage(); break; + case InfoType.UsedMemorySize: value = process.GetMemoryUsage(); break; - case InfoType.AslrRegionAddress: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break; + case InfoType.AslrRegionAddress: value = process.MemoryManager.GetAddrSpaceBaseAddr(); break; - case InfoType.AslrRegionSize: value = (long)process.MemoryManager.GetAddrSpaceSize(); break; + case InfoType.AslrRegionSize: value = process.MemoryManager.GetAddrSpaceSize(); break; - case InfoType.StackRegionAddress: value = (long)process.MemoryManager.StackRegionStart; break; + case InfoType.StackRegionAddress: value = process.MemoryManager.StackRegionStart; break; case InfoType.StackRegionSize: - value = (long)(process.MemoryManager.StackRegionEnd - - process.MemoryManager.StackRegionStart); break; + value = (process.MemoryManager.StackRegionEnd - + process.MemoryManager.StackRegionStart); break; - case InfoType.SystemResourceSizeTotal: value = (long)process.PersonalMmHeapPagesCount * KPageTableBase.PageSize; break; + case InfoType.SystemResourceSizeTotal: value = process.PersonalMmHeapPagesCount * KPageTableBase.PageSize; break; case InfoType.SystemResourceSizeUsed: if (process.PersonalMmHeapPagesCount != 0) @@ -1654,20 +1668,21 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall break; - case InfoType.ProgramId: value = (long)process.TitleId; break; + case InfoType.ProgramId: value = process.TitleId; break; - case InfoType.UserExceptionContextAddress: value = (long)process.UserExceptionContextAddress; break; + case InfoType.UserExceptionContextAddress: value = process.UserExceptionContextAddress; break; - case InfoType.TotalNonSystemMemorySize: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break; + case InfoType.TotalNonSystemMemorySize: value = process.GetMemoryCapacityWithoutPersonalMmHeap(); break; - case InfoType.UsedNonSystemMemorySize: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break; + case InfoType.UsedNonSystemMemorySize: value = process.GetMemoryUsageWithoutPersonalMmHeap(); break; - case InfoType.IsApplication: value = process.IsApplication ? 1 : 0; break; + case InfoType.IsApplication: value = process.IsApplication ? 1UL : 0UL; break; case InfoType.FreeThreadCount: if (process.ResourceLimit != null) { - value = process.ResourceLimit.GetLimitValue(LimitableResource.Thread) - process.ResourceLimit.GetCurrentValue(LimitableResource.Thread); + value = (ulong)(process.ResourceLimit.GetLimitValue(LimitableResource.Thread) - + process.ResourceLimit.GetCurrentValue(LimitableResource.Thread)); } else { @@ -1692,7 +1707,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidCombination; } - value = KernelStatic.GetCurrentProcess().Debug ? 1 : 0; + value = KernelStatic.GetCurrentProcess().Debug ? 1UL : 0UL; break; } @@ -1743,7 +1758,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidCombination; } - value = KTimeManager.ConvertHostTicksToTicks(_context.Schedulers[currentCore].TotalIdleTimeTicks); + value = (ulong)KTimeManager.ConvertHostTicksToTicks(_context.Schedulers[currentCore].TotalIdleTimeTicks); break; } @@ -1796,7 +1811,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall if (subId != -1) { - value = KTimeManager.ConvertHostTicksToTicks(timeDelta); + value = (ulong)KTimeManager.ConvertHostTicksToTicks(timeDelta); } else { @@ -1807,7 +1822,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall totalTimeRunning += timeDelta; } - value = KTimeManager.ConvertHostTicksToTicks(totalTimeRunning); + value = (ulong)KTimeManager.ConvertHostTicksToTicks(totalTimeRunning); } break; @@ -1844,7 +1859,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return result; } - public KernelResult GetProcessList(ulong address, int maxCount, out int count) + public KernelResult GetProcessList(out int count, ulong address, int maxCount) { count = 0; @@ -1878,7 +1893,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { if (copyCount < maxCount) { - if (!KernelTransfer.KernelToUserInt64(_context, address + (ulong)copyCount * 8, process.Pid)) + if (!KernelTransfer.KernelToUser(address + (ulong)copyCount * 8, process.Pid)) { return KernelResult.UserCopyFailed; } @@ -1893,7 +1908,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.Success; } - public KernelResult GetSystemInfo(uint id, int handle, long subId, out long value) + public KernelResult GetSystemInfo(out long value, uint id, int handle, long subId) { value = 0; @@ -1949,7 +1964,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.Success; } - public KernelResult GetResourceLimitLimitValue(int handle, LimitableResource resource, out long limitValue) + public KernelResult GetResourceLimitLimitValue(out long limitValue, int handle, LimitableResource resource) { limitValue = 0; @@ -1970,7 +1985,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.Success; } - public KernelResult GetResourceLimitCurrentValue(int handle, LimitableResource resource, out long limitValue) + public KernelResult GetResourceLimitCurrentValue(out long limitValue, int handle, LimitableResource resource) { limitValue = 0; @@ -1991,7 +2006,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.Success; } - public KernelResult GetResourceLimitPeakValue(int handle, LimitableResource resource, out long peak) + public KernelResult GetResourceLimitPeakValue(out long peak, int handle, LimitableResource resource) { peak = 0; @@ -2041,12 +2056,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall // Thread public KernelResult CreateThread( + out int handle, ulong entrypoint, ulong argsPtr, ulong stackTop, int priority, - int cpuCore, - out int handle) + int cpuCore) { handle = 0; @@ -2152,7 +2167,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall } } - public KernelResult GetThreadPriority(int handle, out int priority) + public KernelResult GetThreadPriority(out int priority, int handle) { KProcess process = KernelStatic.GetCurrentProcess(); @@ -2190,7 +2205,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.Success; } - public KernelResult GetThreadCoreMask(int handle, out int preferredCore, out long affinityMask) + public KernelResult GetThreadCoreMask(out int preferredCore, out ulong affinityMask, int handle) { KProcess process = KernelStatic.GetCurrentProcess(); @@ -2212,7 +2227,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall } } - public KernelResult SetThreadCoreMask(int handle, int preferredCore, long affinityMask) + public KernelResult SetThreadCoreMask(int handle, int preferredCore, ulong affinityMask) { KProcess currentProcess = KernelStatic.GetCurrentProcess(); @@ -2220,7 +2235,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { preferredCore = currentProcess.DefaultCpuCore; - affinityMask = 1 << preferredCore; + affinityMask = 1UL << preferredCore; } else { @@ -2242,7 +2257,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidCpuCore; } } - else if ((affinityMask & (1 << preferredCore)) == 0) + else if ((affinityMask & (1UL << preferredCore)) == 0) { return KernelResult.InvalidCombination; } @@ -2265,7 +2280,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelStatic.GetCurrentThread().CurrentCore; } - public KernelResult GetThreadId(int handle, out long threadUid) + public KernelResult GetThreadId(out long threadUid, int handle) { KProcess process = KernelStatic.GetCurrentProcess(); @@ -2331,96 +2346,21 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidThread; } - IVirtualMemoryManager memory = currentProcess.CpuMemory; + KernelResult result = thread.GetThreadContext3(out ThreadContext context); - memory.Write(address + 0x0, thread.Context.GetX(0)); - memory.Write(address + 0x8, thread.Context.GetX(1)); - memory.Write(address + 0x10, thread.Context.GetX(2)); - memory.Write(address + 0x18, thread.Context.GetX(3)); - memory.Write(address + 0x20, thread.Context.GetX(4)); - memory.Write(address + 0x28, thread.Context.GetX(5)); - memory.Write(address + 0x30, thread.Context.GetX(6)); - memory.Write(address + 0x38, thread.Context.GetX(7)); - memory.Write(address + 0x40, thread.Context.GetX(8)); - memory.Write(address + 0x48, thread.Context.GetX(9)); - memory.Write(address + 0x50, thread.Context.GetX(10)); - memory.Write(address + 0x58, thread.Context.GetX(11)); - memory.Write(address + 0x60, thread.Context.GetX(12)); - memory.Write(address + 0x68, thread.Context.GetX(13)); - memory.Write(address + 0x70, thread.Context.GetX(14)); - memory.Write(address + 0x78, thread.Context.GetX(15)); - memory.Write(address + 0x80, thread.Context.GetX(16)); - memory.Write(address + 0x88, thread.Context.GetX(17)); - memory.Write(address + 0x90, thread.Context.GetX(18)); - memory.Write(address + 0x98, thread.Context.GetX(19)); - memory.Write(address + 0xa0, thread.Context.GetX(20)); - memory.Write(address + 0xa8, thread.Context.GetX(21)); - memory.Write(address + 0xb0, thread.Context.GetX(22)); - memory.Write(address + 0xb8, thread.Context.GetX(23)); - memory.Write(address + 0xc0, thread.Context.GetX(24)); - memory.Write(address + 0xc8, thread.Context.GetX(25)); - memory.Write(address + 0xd0, thread.Context.GetX(26)); - memory.Write(address + 0xd8, thread.Context.GetX(27)); - memory.Write(address + 0xe0, thread.Context.GetX(28)); - memory.Write(address + 0xe8, thread.Context.GetX(29)); - memory.Write(address + 0xf0, thread.Context.GetX(30)); - memory.Write(address + 0xf8, thread.Context.GetX(31)); + if (result == KernelResult.Success) + { + return KernelTransfer.KernelToUser(address, context) + ? KernelResult.Success + : KernelResult.InvalidMemState; + } - memory.Write(address + 0x100, thread.LastPc); - - memory.Write(address + 0x108, (ulong)GetPsr(thread.Context)); - - memory.Write(address + 0x110, thread.Context.GetV(0)); - memory.Write(address + 0x120, thread.Context.GetV(1)); - memory.Write(address + 0x130, thread.Context.GetV(2)); - memory.Write(address + 0x140, thread.Context.GetV(3)); - memory.Write(address + 0x150, thread.Context.GetV(4)); - memory.Write(address + 0x160, thread.Context.GetV(5)); - memory.Write(address + 0x170, thread.Context.GetV(6)); - memory.Write(address + 0x180, thread.Context.GetV(7)); - memory.Write(address + 0x190, thread.Context.GetV(8)); - memory.Write(address + 0x1a0, thread.Context.GetV(9)); - memory.Write(address + 0x1b0, thread.Context.GetV(10)); - memory.Write(address + 0x1c0, thread.Context.GetV(11)); - memory.Write(address + 0x1d0, thread.Context.GetV(12)); - memory.Write(address + 0x1e0, thread.Context.GetV(13)); - memory.Write(address + 0x1f0, thread.Context.GetV(14)); - memory.Write(address + 0x200, thread.Context.GetV(15)); - memory.Write(address + 0x210, thread.Context.GetV(16)); - memory.Write(address + 0x220, thread.Context.GetV(17)); - memory.Write(address + 0x230, thread.Context.GetV(18)); - memory.Write(address + 0x240, thread.Context.GetV(19)); - memory.Write(address + 0x250, thread.Context.GetV(20)); - memory.Write(address + 0x260, thread.Context.GetV(21)); - memory.Write(address + 0x270, thread.Context.GetV(22)); - memory.Write(address + 0x280, thread.Context.GetV(23)); - memory.Write(address + 0x290, thread.Context.GetV(24)); - memory.Write(address + 0x2a0, thread.Context.GetV(25)); - memory.Write(address + 0x2b0, thread.Context.GetV(26)); - memory.Write(address + 0x2c0, thread.Context.GetV(27)); - memory.Write(address + 0x2d0, thread.Context.GetV(28)); - memory.Write(address + 0x2e0, thread.Context.GetV(29)); - memory.Write(address + 0x2f0, thread.Context.GetV(30)); - memory.Write(address + 0x300, thread.Context.GetV(31)); - - memory.Write(address + 0x310, (int)thread.Context.Fpcr); - memory.Write(address + 0x314, (int)thread.Context.Fpsr); - memory.Write(address + 0x318, thread.Context.Tpidr); - - return KernelResult.Success; - } - - private static int GetPsr(ARMeilleure.State.ExecutionContext context) - { - return (context.GetPstateFlag(ARMeilleure.State.PState.NFlag) ? (1 << (int)ARMeilleure.State.PState.NFlag) : 0) | - (context.GetPstateFlag(ARMeilleure.State.PState.ZFlag) ? (1 << (int)ARMeilleure.State.PState.ZFlag) : 0) | - (context.GetPstateFlag(ARMeilleure.State.PState.CFlag) ? (1 << (int)ARMeilleure.State.PState.CFlag) : 0) | - (context.GetPstateFlag(ARMeilleure.State.PState.VFlag) ? (1 << (int)ARMeilleure.State.PState.VFlag) : 0); + return result; } // Thread synchronization - public KernelResult WaitSynchronization(ulong handlesPtr, int handlesCount, long timeout, out int handleIndex) + public KernelResult WaitSynchronization(out int handleIndex, ulong handlesPtr, int handlesCount, long timeout) { handleIndex = 0; @@ -2456,7 +2396,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall Span handles = new Span(currentThread.WaitSyncHandles).Slice(0, handlesCount); - if (!KernelTransfer.UserToKernelInt32Array(_context, handlesPtr, handles)) + if (!KernelTransfer.UserToKernelArray(handlesPtr, handles)) { return KernelResult.UserCopyFailed; } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs index d955807d8..f1b5b0e56 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs @@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult ConnectToNamedPort32([R(1)] uint namePtr, [R(1)] out int handle) { - return _syscall.ConnectToNamedPort(namePtr, out handle); + return _syscall.ConnectToNamedPort(out handle, namePtr); } public KernelResult SendSyncRequest32([R(0)] int handle) @@ -36,17 +36,17 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(1)] out int serverSessionHandle, [R(2)] out int clientSessionHandle) { - return _syscall.CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle); + return _syscall.CreateSession(out serverSessionHandle, out clientSessionHandle, isLight, namePtr); } public KernelResult AcceptSession32([R(1)] int portHandle, [R(1)] out int sessionHandle) { - return _syscall.AcceptSession(portHandle, out sessionHandle); + return _syscall.AcceptSession(out sessionHandle, portHandle); } public KernelResult ReplyAndReceive32( [R(0)] uint timeoutLow, - [R(1)] ulong handlesPtr, + [R(1)] uint handlesPtr, [R(2)] int handlesCount, [R(3)] int replyTargetHandle, [R(4)] uint timeoutHigh, @@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); - return _syscall.ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex); + return _syscall.ReplyAndReceive(out handleIndex, handlesPtr, handlesCount, replyTargetHandle, timeout); } public KernelResult CreatePort32( @@ -64,45 +64,45 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(1)] out int serverPortHandle, [R(2)] out int clientPortHandle) { - return _syscall.CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle); + return _syscall.CreatePort(out serverPortHandle, out clientPortHandle, maxSessions, isLight, namePtr); } public KernelResult ManageNamedPort32([R(1)] uint namePtr, [R(2)] int maxSessions, [R(1)] out int handle) { - return _syscall.ManageNamedPort(namePtr, maxSessions, out handle); + return _syscall.ManageNamedPort(out handle, namePtr, maxSessions); } public KernelResult ConnectToPort32([R(1)] int clientPortHandle, [R(1)] out int clientSessionHandle) { - return _syscall.ConnectToPort(clientPortHandle, out clientSessionHandle); + return _syscall.ConnectToPort(out clientSessionHandle, clientPortHandle); } // Memory - public KernelResult SetHeapSize32([R(1)] uint size, [R(1)] out uint position) + public KernelResult SetHeapSize32([R(1)] uint size, [R(1)] out uint address) { - KernelResult result = _syscall.SetHeapSize(size, out ulong temporaryPosition); + KernelResult result = _syscall.SetHeapSize(out ulong address64, size); - position = (uint)temporaryPosition; + address = (uint)address64; return result; } public KernelResult SetMemoryPermission32( - [R(0)] ulong position, - [R(1)] ulong size, + [R(0)] uint address, + [R(1)] uint size, [R(2)] KMemoryPermission permission) { - return _syscall.SetMemoryPermission(position, size, permission); + return _syscall.SetMemoryPermission(address, size, permission); } public KernelResult SetMemoryAttribute32( - [R(0)] uint position, + [R(0)] uint address, [R(1)] uint size, [R(2)] MemoryAttribute attributeMask, [R(3)] MemoryAttribute attributeValue) { - return _syscall.SetMemoryAttribute(position, size, attributeMask, attributeValue); + return _syscall.SetMemoryAttribute(address, size, attributeMask, attributeValue); } public KernelResult MapMemory32([R(0)] uint dst, [R(1)] uint src, [R(2)] uint size) @@ -115,9 +115,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.UnmapMemory(dst, src, size); } - public KernelResult QueryMemory32([R(0)] uint infoPtr, [R(1)] uint r1, [R(2)] uint position, [R(1)] out uint pageInfo) + public KernelResult QueryMemory32([R(0)] uint infoPtr, [R(1)] uint r1, [R(2)] uint address, [R(1)] out uint pageInfo) { - KernelResult result = _syscall.QueryMemory(infoPtr, position, out ulong pageInfo64); + KernelResult result = _syscall.QueryMemory(infoPtr, out ulong pageInfo64, address); pageInfo = (uint)pageInfo64; @@ -140,7 +140,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(3)] KMemoryPermission permission, [R(1)] out int handle) { - return _syscall.CreateTransferMemory(address, size, permission, out handle); + return _syscall.CreateTransferMemory(out handle, address, size, permission); } public KernelResult MapTransferMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size, [R(3)] KMemoryPermission permission) @@ -237,7 +237,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetProcessId32([R(1)] int handle, [R(1)] out int pidLow, [R(2)] out int pidHigh) { - KernelResult result = _syscall.GetProcessId(handle, out long pid); + KernelResult result = _syscall.GetProcessId(out long pid, handle); pidLow = (int)(pid & uint.MaxValue); pidHigh = (int)(pid >> 32); @@ -265,7 +265,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { long subId = (long)(subIdLow | ((ulong)subIdHigh << 32)); - KernelResult result = _syscall.GetInfo(id, handle, subId, out long value); + KernelResult result = _syscall.GetInfo(out ulong value, id, handle, subId); valueHigh = (uint)(value >> 32); valueLow = (uint)(value & uint.MaxValue); @@ -280,14 +280,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetProcessList32([R(1)] ulong address, [R(2)] int maxCount, [R(1)] out int count) { - return _syscall.GetProcessList(address, maxCount, out count); + return _syscall.GetProcessList(out count, address, maxCount); } public KernelResult GetSystemInfo32([R(1)] uint subIdLow, [R(2)] uint id, [R(3)] int handle, [R(3)] uint subIdHigh, [R(1)] out int valueLow, [R(2)] out int valueHigh) { long subId = (long)(subIdLow | ((ulong)subIdHigh << 32)); - KernelResult result = _syscall.GetSystemInfo(id, handle, subId, out long value); + KernelResult result = _syscall.GetSystemInfo(out long value, id, handle, subId); valueHigh = (int)(value >> 32); valueLow = (int)(value & uint.MaxValue); @@ -297,7 +297,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetResourceLimitLimitValue32([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out int limitValueLow, [R(2)] out int limitValueHigh) { - KernelResult result = _syscall.GetResourceLimitLimitValue(handle, resource, out long limitValue); + KernelResult result = _syscall.GetResourceLimitLimitValue(out long limitValue, handle, resource); limitValueHigh = (int)(limitValue >> 32); limitValueLow = (int)(limitValue & uint.MaxValue); @@ -307,7 +307,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetResourceLimitCurrentValue32([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out int limitValueLow, [R(2)] out int limitValueHigh) { - KernelResult result = _syscall.GetResourceLimitCurrentValue(handle, resource, out long limitValue); + KernelResult result = _syscall.GetResourceLimitCurrentValue(out long limitValue, handle, resource); limitValueHigh = (int)(limitValue >> 32); limitValueLow = (int)(limitValue & uint.MaxValue); @@ -317,7 +317,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetResourceLimitPeakValue32([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out int peakLow, [R(2)] out int peakHigh) { - KernelResult result = _syscall.GetResourceLimitPeakValue(handle, resource, out long peak); + KernelResult result = _syscall.GetResourceLimitPeakValue(out long peak, handle, resource); peakHigh = (int)(peak >> 32); peakLow = (int)(peak & uint.MaxValue); @@ -359,7 +359,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(4)] int cpuCore, [R(1)] out int handle) { - return _syscall.CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle); + return _syscall.CreateThread(out handle, entrypoint, argsPtr, stackTop, priority, cpuCore); } public KernelResult StartThread32([R(0)] int handle) @@ -381,7 +381,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetThreadPriority32([R(1)] int handle, [R(1)] out int priority) { - return _syscall.GetThreadPriority(handle, out priority); + return _syscall.GetThreadPriority(out priority, handle); } public KernelResult SetThreadPriority32([R(0)] int handle, [R(1)] int priority) @@ -389,19 +389,19 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.SetThreadPriority(handle, priority); } - public KernelResult GetThreadCoreMask32([R(2)] int handle, [R(1)] out int preferredCore, [R(2)] out int affinityMaskLow, [R(3)] out int affinityMaskHigh) + public KernelResult GetThreadCoreMask32([R(2)] int handle, [R(1)] out int preferredCore, [R(2)] out uint affinityMaskLow, [R(3)] out uint affinityMaskHigh) { - KernelResult result = _syscall.GetThreadCoreMask(handle, out preferredCore, out long affinityMask); + KernelResult result = _syscall.GetThreadCoreMask(out preferredCore, out ulong affinityMask, handle); - affinityMaskLow = (int)(affinityMask & uint.MaxValue); - affinityMaskHigh = (int)(affinityMask >> 32); + affinityMaskLow = (uint)(affinityMask & uint.MaxValue); + affinityMaskHigh = (uint)(affinityMask >> 32); return result; } public KernelResult SetThreadCoreMask32([R(0)] int handle, [R(1)] int preferredCore, [R(2)] uint affinityMaskLow, [R(3)] uint affinityMaskHigh) { - long affinityMask = (long)(affinityMaskLow | ((ulong)affinityMaskHigh << 32)); + ulong affinityMask = affinityMaskLow | ((ulong)affinityMaskHigh << 32); return _syscall.SetThreadCoreMask(handle, preferredCore, affinityMask); } @@ -415,7 +415,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { long threadUid; - KernelResult result = _syscall.GetThreadId(handle, out threadUid); + KernelResult result = _syscall.GetThreadId(out threadUid, handle); threadUidLow = (uint)(threadUid >> 32); threadUidHigh = (uint)(threadUid & uint.MaxValue); @@ -444,7 +444,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); - return _syscall.WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex); + return _syscall.WaitSynchronization(out handleIndex, handlesPtr, handlesCount, timeout); } public KernelResult CancelSynchronization32([R(0)] int handle) diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs index fc826552b..fcb2a702f 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs @@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult ConnectToNamedPort64([R(1)] ulong namePtr, [R(1)] out int handle) { - return _syscall.ConnectToNamedPort(namePtr, out handle); + return _syscall.ConnectToNamedPort(out handle, namePtr); } public KernelResult SendSyncRequest64([R(0)] int handle) @@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(3)] int handle, [R(1)] out int doneEventHandle) { - return _syscall.SendAsyncRequestWithUserBuffer(messagePtr, messageSize, handle, out doneEventHandle); + return _syscall.SendAsyncRequestWithUserBuffer(out doneEventHandle, messagePtr, messageSize, handle); } public KernelResult CreateSession64( @@ -45,12 +45,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(1)] out int serverSessionHandle, [R(2)] out int clientSessionHandle) { - return _syscall.CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle); + return _syscall.CreateSession(out serverSessionHandle, out clientSessionHandle, isLight, namePtr); } public KernelResult AcceptSession64([R(1)] int portHandle, [R(1)] out int sessionHandle) { - return _syscall.AcceptSession(portHandle, out sessionHandle); + return _syscall.AcceptSession(out sessionHandle, portHandle); } public KernelResult ReplyAndReceive64( @@ -60,7 +60,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(4)] long timeout, [R(1)] out int handleIndex) { - return _syscall.ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex); + return _syscall.ReplyAndReceive(out handleIndex, handlesPtr, handlesCount, replyTargetHandle, timeout); } public KernelResult ReplyAndReceiveWithUserBuffer64( @@ -73,13 +73,13 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(1)] out int handleIndex) { return _syscall.ReplyAndReceiveWithUserBuffer( + out handleIndex, handlesPtr, messagePtr, messageSize, handlesCount, replyTargetHandle, - timeout, - out handleIndex); + timeout); } public KernelResult CreatePort64( @@ -89,41 +89,41 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(1)] out int serverPortHandle, [R(2)] out int clientPortHandle) { - return _syscall.CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle); + return _syscall.CreatePort(out serverPortHandle, out clientPortHandle, maxSessions, isLight, namePtr); } public KernelResult ManageNamedPort64([R(1)] ulong namePtr, [R(2)] int maxSessions, [R(1)] out int handle) { - return _syscall.ManageNamedPort(namePtr, maxSessions, out handle); + return _syscall.ManageNamedPort(out handle, namePtr, maxSessions); } public KernelResult ConnectToPort64([R(1)] int clientPortHandle, [R(1)] out int clientSessionHandle) { - return _syscall.ConnectToPort(clientPortHandle, out clientSessionHandle); + return _syscall.ConnectToPort(out clientSessionHandle, clientPortHandle); } // Memory - public KernelResult SetHeapSize64([R(1)] ulong size, [R(1)] out ulong position) + public KernelResult SetHeapSize64([R(1)] ulong size, [R(1)] out ulong address) { - return _syscall.SetHeapSize(size, out position); + return _syscall.SetHeapSize(out address, size); } public KernelResult SetMemoryPermission64( - [R(0)] ulong position, + [R(0)] ulong address, [R(1)] ulong size, [R(2)] KMemoryPermission permission) { - return _syscall.SetMemoryPermission(position, size, permission); + return _syscall.SetMemoryPermission(address, size, permission); } public KernelResult SetMemoryAttribute64( - [R(0)] ulong position, + [R(0)] ulong address, [R(1)] ulong size, [R(2)] MemoryAttribute attributeMask, [R(3)] MemoryAttribute attributeValue) { - return _syscall.SetMemoryAttribute(position, size, attributeMask, attributeValue); + return _syscall.SetMemoryAttribute(address, size, attributeMask, attributeValue); } public KernelResult MapMemory64([R(0)] ulong dst, [R(1)] ulong src, [R(2)] ulong size) @@ -136,9 +136,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.UnmapMemory(dst, src, size); } - public KernelResult QueryMemory64([R(0)] ulong infoPtr, [R(2)] ulong position, [R(1)] out ulong pageInfo) + public KernelResult QueryMemory64([R(0)] ulong infoPtr, [R(2)] ulong address, [R(1)] out ulong pageInfo) { - return _syscall.QueryMemory(infoPtr, position, out pageInfo); + return _syscall.QueryMemory(infoPtr, out pageInfo, address); } public KernelResult MapSharedMemory64([R(0)] int handle, [R(1)] ulong address, [R(2)] ulong size, [R(3)] KMemoryPermission permission) @@ -157,7 +157,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(3)] KMemoryPermission permission, [R(1)] out int handle) { - return _syscall.CreateTransferMemory(address, size, permission, out handle); + return _syscall.CreateTransferMemory(out handle, address, size, permission); } public KernelResult MapTransferMemory64([R(0)] int handle, [R(1)] ulong address, [R(2)] ulong size, [R(3)] KMemoryPermission permission) @@ -234,7 +234,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetProcessId64([R(1)] int handle, [R(1)] out long pid) { - return _syscall.GetProcessId(handle, out pid); + return _syscall.GetProcessId(out pid, handle); } public void Break64([R(0)] ulong reason, [R(1)] ulong x1, [R(2)] ulong info) @@ -247,9 +247,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall _syscall.OutputDebugString(strPtr, size); } - public KernelResult GetInfo64([R(1)] InfoType id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value) + public KernelResult GetInfo64([R(1)] InfoType id, [R(2)] int handle, [R(3)] long subId, [R(1)] out ulong value) { - return _syscall.GetInfo(id, handle, subId, out value); + return _syscall.GetInfo(out value, id, handle, subId); } public KernelResult CreateEvent64([R(1)] out int wEventHandle, [R(2)] out int rEventHandle) @@ -259,27 +259,27 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetProcessList64([R(1)] ulong address, [R(2)] int maxCount, [R(1)] out int count) { - return _syscall.GetProcessList(address, maxCount, out count); + return _syscall.GetProcessList(out count, address, maxCount); } public KernelResult GetSystemInfo64([R(1)] uint id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value) { - return _syscall.GetSystemInfo(id, handle, subId, out value); + return _syscall.GetSystemInfo(out value, id, handle, subId); } public KernelResult GetResourceLimitLimitValue64([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out long limitValue) { - return _syscall.GetResourceLimitLimitValue(handle, resource, out limitValue); + return _syscall.GetResourceLimitLimitValue(out limitValue, handle, resource); } public KernelResult GetResourceLimitCurrentValue64([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out long limitValue) { - return _syscall.GetResourceLimitCurrentValue(handle, resource, out limitValue); + return _syscall.GetResourceLimitCurrentValue(out limitValue, handle, resource); } public KernelResult GetResourceLimitPeakValue64([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out long peak) { - return _syscall.GetResourceLimitPeakValue(handle, resource, out peak); + return _syscall.GetResourceLimitPeakValue(out peak, handle, resource); } public KernelResult CreateResourceLimit64([R(1)] out int handle) @@ -302,7 +302,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [R(5)] int cpuCore, [R(1)] out int handle) { - return _syscall.CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle); + return _syscall.CreateThread(out handle, entrypoint, argsPtr, stackTop, priority, cpuCore); } public KernelResult StartThread64([R(0)] int handle) @@ -322,7 +322,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetThreadPriority64([R(1)] int handle, [R(1)] out int priority) { - return _syscall.GetThreadPriority(handle, out priority); + return _syscall.GetThreadPriority(out priority, handle); } public KernelResult SetThreadPriority64([R(0)] int handle, [R(1)] int priority) @@ -330,12 +330,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.SetThreadPriority(handle, priority); } - public KernelResult GetThreadCoreMask64([R(2)] int handle, [R(1)] out int preferredCore, [R(2)] out long affinityMask) + public KernelResult GetThreadCoreMask64([R(2)] int handle, [R(1)] out int preferredCore, [R(2)] out ulong affinityMask) { - return _syscall.GetThreadCoreMask(handle, out preferredCore, out affinityMask); + return _syscall.GetThreadCoreMask(out preferredCore, out affinityMask, handle); } - public KernelResult SetThreadCoreMask64([R(0)] int handle, [R(1)] int preferredCore, [R(2)] long affinityMask) + public KernelResult SetThreadCoreMask64([R(0)] int handle, [R(1)] int preferredCore, [R(2)] ulong affinityMask) { return _syscall.SetThreadCoreMask(handle, preferredCore, affinityMask); } @@ -347,7 +347,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetThreadId64([R(1)] int handle, [R(1)] out long threadUid) { - return _syscall.GetThreadId(handle, out threadUid); + return _syscall.GetThreadId(out threadUid, handle); } public KernelResult SetThreadActivity64([R(0)] int handle, [R(1)] bool pause) @@ -364,7 +364,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult WaitSynchronization64([R(1)] ulong handlesPtr, [R(2)] int handlesCount, [R(3)] long timeout, [R(1)] out int handleIndex) { - return _syscall.WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex); + return _syscall.WaitSynchronization(out handleIndex, handlesPtr, handlesCount, timeout); } public KernelResult CancelSynchronization64([R(0)] int handle) diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/ThreadContext.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/ThreadContext.cs new file mode 100644 index 000000000..b524406af --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/ThreadContext.cs @@ -0,0 +1,22 @@ +using ARMeilleure.State; +using Ryujinx.Common.Memory; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + struct ThreadContext + { + public Array29 Registers; + public ulong Fp; + public ulong Lr; + public ulong Sp; + public ulong Pc; + public uint Pstate; +#pragma warning disable CS0169 + private uint _padding; +#pragma warning restore CS0169 + public Array32 FpuRegisters; + public uint Fpcr; + public uint Fpsr; + public ulong Tpidr; + } +} diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs index 3fd07f90d..f53b43b3c 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs @@ -35,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KProcess currentProcess = KernelStatic.GetCurrentProcess(); - if (!KernelTransfer.UserToKernelInt32(_context, mutexAddress, out int mutexValue)) + if (!KernelTransfer.UserToKernel(out int mutexValue, mutexAddress)) { _context.CriticalSection.Leave(); @@ -88,7 +88,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KernelResult result = KernelResult.Success; - if (!KernelTransfer.KernelToUserInt32(_context, mutexAddress, mutexValue)) + if (!KernelTransfer.KernelToUser(mutexAddress, mutexValue)) { result = KernelResult.InvalidMemState; } @@ -123,9 +123,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading (int mutexValue, _) = MutexUnlock(currentThread, mutexAddress); - KernelTransfer.KernelToUserInt32(_context, condVarAddress, 1); + KernelTransfer.KernelToUser(condVarAddress, 1); - if (!KernelTransfer.KernelToUserInt32(_context, mutexAddress, mutexValue)) + if (!KernelTransfer.KernelToUser(mutexAddress, mutexValue)) { _context.CriticalSection.Leave(); @@ -201,7 +201,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (!_condVarThreads.Any(x => x.CondVarAddress == address)) { - KernelTransfer.KernelToUserInt32(_context, address, 0); + KernelTransfer.KernelToUser(address, 0); } _context.CriticalSection.Leave(); @@ -290,7 +290,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading currentThread.SignaledObj = null; currentThread.ObjSyncResult = KernelResult.TimedOut; - if (!KernelTransfer.UserToKernelInt32(_context, address, out int currentValue)) + if (!KernelTransfer.UserToKernel(out int currentValue, address)) { _context.CriticalSection.Leave(); @@ -363,7 +363,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KProcess currentProcess = KernelStatic.GetCurrentProcess(); - if (!KernelTransfer.UserToKernelInt32(_context, address, out int currentValue)) + if (!KernelTransfer.UserToKernel(out int currentValue, address)) { _context.CriticalSection.Leave(); diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index cf95b0154..16744c437 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -2,6 +2,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Cpu; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.SupervisorCall; using System; using System.Collections.Generic; using System.Numerics; @@ -27,7 +28,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public KThreadContext ThreadContext { get; private set; } public int DynamicPriority { get; set; } - public long AffinityMask { get; set; } + public ulong AffinityMask { get; set; } public long ThreadUid { get; private set; } @@ -88,7 +89,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public bool IsPinned { get; private set; } - private long _originalAffinityMask; + private ulong _originalAffinityMask; private int _originalPreferredCore; private int _originalBasePriority; private int _coreMigrationDisableCount; @@ -147,7 +148,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading ThreadContext = new KThreadContext(); PreferredCore = cpuCore; - AffinityMask |= 1L << cpuCore; + AffinityMask |= 1UL << cpuCore; SchedFlags = type == ThreadType.Dummy ? ThreadSchedState.Running @@ -629,6 +630,89 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } + public KernelResult GetThreadContext3(out ThreadContext context) + { + context = default; + + lock (ActivityOperationLock) + { + KernelContext.CriticalSection.Enter(); + + if ((_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) == 0) + { + KernelContext.CriticalSection.Leave(); + + return KernelResult.InvalidState; + } + + if (!TerminationRequested) + { + context = GetCurrentContext(); + } + + KernelContext.CriticalSection.Leave(); + } + + return KernelResult.Success; + } + + private static uint GetPsr(ARMeilleure.State.ExecutionContext context) + { + return (context.GetPstateFlag(ARMeilleure.State.PState.NFlag) ? (1U << (int)ARMeilleure.State.PState.NFlag) : 0U) | + (context.GetPstateFlag(ARMeilleure.State.PState.ZFlag) ? (1U << (int)ARMeilleure.State.PState.ZFlag) : 0U) | + (context.GetPstateFlag(ARMeilleure.State.PState.CFlag) ? (1U << (int)ARMeilleure.State.PState.CFlag) : 0U) | + (context.GetPstateFlag(ARMeilleure.State.PState.VFlag) ? (1U << (int)ARMeilleure.State.PState.VFlag) : 0U); + } + + private ThreadContext GetCurrentContext() + { + const int MaxRegistersAArch32 = 15; + const int MaxFpuRegistersAArch32 = 16; + + ThreadContext context = new ThreadContext(); + + if (Owner.Flags.HasFlag(ProcessCreationFlags.Is64Bit)) + { + for (int i = 0; i < context.Registers.Length; i++) + { + context.Registers[i] = Context.GetX(i); + } + + for (int i = 0; i < context.FpuRegisters.Length; i++) + { + context.FpuRegisters[i] = Context.GetV(i); + } + + context.Fp = Context.GetX(29); + context.Lr = Context.GetX(30); + context.Sp = Context.GetX(31); + context.Pc = (ulong)LastPc; + context.Pstate = GetPsr(Context); + context.Tpidr = (ulong)Context.Tpidr; + } + else + { + for (int i = 0; i < MaxRegistersAArch32; i++) + { + context.Registers[i] = (uint)Context.GetX(i); + } + + for (int i = 0; i < MaxFpuRegistersAArch32; i++) + { + context.FpuRegisters[i] = Context.GetV(i); + } + + context.Pc = (uint)LastPc; + context.Pstate = GetPsr(Context); + context.Tpidr = (uint)Context.Tpidr; + } + + context.Fpcr = (uint)Context.Fpcr; + context.Fpsr = (uint)Context.Fpsr; + + return context; + } + public void CancelSynchronization() { KernelContext.CriticalSection.Enter(); @@ -660,7 +744,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KernelContext.CriticalSection.Leave(); } - public KernelResult SetCoreAndAffinityMask(int newCore, long newAffinityMask) + public KernelResult SetCoreAndAffinityMask(int newCore, ulong newAffinityMask) { lock (ActivityOperationLock) { @@ -673,7 +757,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { newCore = isCoreMigrationDisabled ? _originalPreferredCore : PreferredCore; - if ((newAffinityMask & (1 << newCore)) == 0) + if ((newAffinityMask & (1UL << newCore)) == 0) { KernelContext.CriticalSection.Leave(); @@ -688,7 +772,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } else { - long oldAffinityMask = AffinityMask; + ulong oldAffinityMask = AffinityMask; PreferredCore = newCore; AffinityMask = newAffinityMask; @@ -701,7 +785,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { if (PreferredCore < 0) { - ActiveCore = sizeof(ulong) * 8 - 1 - BitOperations.LeadingZeroCount((ulong)AffinityMask); + ActiveCore = sizeof(ulong) * 8 - 1 - BitOperations.LeadingZeroCount(AffinityMask); } else { @@ -733,7 +817,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading int coreNumber = GetEffectiveRunningCore(); bool isPinnedThreadCurrentlyRunning = coreNumber >= 0; - if (isPinnedThreadCurrentlyRunning && ((1 << coreNumber) & AffinityMask) == 0) + if (isPinnedThreadCurrentlyRunning && ((1UL << coreNumber) & AffinityMask) == 0) { if (IsPinned) { @@ -1077,7 +1161,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KernelContext.ThreadReselectionRequested = true; } - private void AdjustSchedulingForNewAffinity(long oldAffinityMask, int oldCore) + private void AdjustSchedulingForNewAffinity(ulong oldAffinityMask, int oldCore) { if (SchedFlags != ThreadSchedState.Running || DynamicPriority >= KScheduler.PrioritiesCount || !IsSchedulable) { @@ -1259,7 +1343,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading ActiveCore = CurrentCore; PreferredCore = CurrentCore; - AffinityMask = 1 << CurrentCore; + AffinityMask = 1UL << CurrentCore; if (activeCore != CurrentCore || _originalAffinityMask != AffinityMask) { @@ -1282,7 +1366,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading IsPinned = false; _coreMigrationDisableCount--; - long affinityMask = AffinityMask; + ulong affinityMask = AffinityMask; int activeCore = ActiveCore; PreferredCore = _originalPreferredCore; @@ -1290,7 +1374,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (AffinityMask != affinityMask) { - if ((AffinityMask & 1 << ActiveCore) != 0) + if ((AffinityMask & 1UL << ActiveCore) != 0) { if (PreferredCore >= 0) { diff --git a/Ryujinx.HLE/HOS/Services/IpcService.cs b/Ryujinx.HLE/HOS/Services/IpcService.cs index 01ee11584..108a4f700 100644 --- a/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -210,7 +210,7 @@ namespace Ryujinx.HLE.HOS.Services } else { - context.Device.System.KernelContext.Syscall.CreateSession(false, 0, out int serverSessionHandle, out int clientSessionHandle); + context.Device.System.KernelContext.Syscall.CreateSession(out int serverSessionHandle, out int clientSessionHandle, false, 0); obj.Server.AddSessionObj(serverSessionHandle, obj); diff --git a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs index 00bc34418..b70f6cb79 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs @@ -323,7 +323,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv _clientMemory = context.Process.HandleTable.GetKProcess(clientHandle).CpuMemory; - context.Device.System.KernelContext.Syscall.GetProcessId(clientHandle, out _owner); + context.Device.System.KernelContext.Syscall.GetProcessId(out _owner, clientHandle); context.ResponseData.Write((uint)NvResult.Success); diff --git a/Ryujinx.HLE/HOS/Services/ServerBase.cs b/Ryujinx.HLE/HOS/Services/ServerBase.cs index 695394a59..cf7da2f41 100644 --- a/Ryujinx.HLE/HOS/Services/ServerBase.cs +++ b/Ryujinx.HLE/HOS/Services/ServerBase.cs @@ -87,7 +87,7 @@ namespace Ryujinx.HLE.HOS.Services if (SmObjectFactory != null) { - _context.Syscall.ManageNamedPort("sm:", 50, out int serverPortHandle); + _context.Syscall.ManageNamedPort(out int serverPortHandle, "sm:", 50); AddPort(serverPortHandle, SmObjectFactory); } @@ -96,7 +96,7 @@ namespace Ryujinx.HLE.HOS.Services KThread thread = KernelStatic.GetCurrentThread(); ulong messagePtr = thread.TlsAddress; - _context.Syscall.SetHeapSize(0x200000, out ulong heapAddr); + _context.Syscall.SetHeapSize(out ulong heapAddr, 0x200000); _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0); _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10); @@ -114,7 +114,7 @@ namespace Ryujinx.HLE.HOS.Services sessionHandles.CopyTo(handles, portHandles.Length); // We still need a timeout here to allow the service to pick up and listen new sessions... - var rc = _context.Syscall.ReplyAndReceive(handles, replyTargetHandle, 1000000L, out int signaledIndex); + var rc = _context.Syscall.ReplyAndReceive(out int signaledIndex, handles, replyTargetHandle, 1000000L); thread.HandlePostSyscall(); @@ -140,7 +140,7 @@ namespace Ryujinx.HLE.HOS.Services if (rc == KernelResult.Success) { // We got a new connection, accept the session to allow servicing future requests. - if (_context.Syscall.AcceptSession(handles[signaledIndex], out int serverSessionHandle) == KernelResult.Success) + if (_context.Syscall.AcceptSession(out int serverSessionHandle, handles[signaledIndex]) == KernelResult.Success) { IpcService obj = _ports[handles[signaledIndex]].Invoke(); @@ -247,7 +247,7 @@ namespace Ryujinx.HLE.HOS.Services case 4: int unknown = reqReader.ReadInt32(); - _context.Syscall.CreateSession(false, 0, out int dupServerSessionHandle, out int dupClientSessionHandle); + _context.Syscall.CreateSession(out int dupServerSessionHandle, out int dupClientSessionHandle, false, 0); AddSessionObj(dupServerSessionHandle, _sessions[serverSessionHandle]); From bd412afb9fdf859643e26d2668874e3dc9cd41df Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 29 Jan 2022 19:59:34 -0300 Subject: [PATCH 05/14] Fix small precision error on CPU reciprocal estimate instructions (#3061) * Fix small precision error on CPU reciprocal estimate instructions * PPTC version bump --- ARMeilleure/Instructions/InstEmitSimdArithmetic.cs | 2 +- ARMeilleure/Translation/PTC/Ptc.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs index e290e706e..9a632fd63 100644 --- a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs +++ b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs @@ -3613,7 +3613,7 @@ namespace ARMeilleure.Instructions Operand masked = context.AddIntrinsic(Intrinsic.X86Pand, value, expMask); Operand isNaNInf = context.AddIntrinsic(Intrinsic.X86Pcmpeqd, masked, expMask); - value = context.AddIntrinsic(Intrinsic.X86Paddw, value, roundMask); + value = context.AddIntrinsic(Intrinsic.X86Paddd, value, roundMask); value = context.AddIntrinsic(Intrinsic.X86Pand, value, truncMask); return context.AddIntrinsic(Intrinsic.X86Blendvps, value, oValue, isNaNInf); diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs index 85e56e491..08000979a 100644 --- a/ARMeilleure/Translation/PTC/Ptc.cs +++ b/ARMeilleure/Translation/PTC/Ptc.cs @@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0"; - private const uint InternalVersion = 3034; //! To be incremented manually for each change to the ARMeilleure project. + private const uint InternalVersion = 3061; //! To be incremented manually for each change to the ARMeilleure project. private const string ActualDir = "0"; private const string BackupDir = "1"; From 0dddcd012c48618a98db4be53da532f167cd1f8a Mon Sep 17 00:00:00 2001 From: VocalFan <45863583+Mou-Ikkai@users.noreply.github.com> Date: Sun, 30 Jan 2022 10:41:22 -0500 Subject: [PATCH 06/14] Remove Appveyor from Readme and SLN (#3026) * Replace Appveyor with Github badge. * Delete appveyor.yml * Remove Appveyor from SLN --- README.md | 4 ++-- Ryujinx.sln | 1 - appveyor.yml | 35 ----------------------------------- 3 files changed, 2 insertions(+), 38 deletions(-) delete mode 100644 appveyor.yml diff --git a/README.md b/README.md index c602d6f01..4cc8d9a36 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@

- - + diff --git a/Ryujinx.sln b/Ryujinx.sln index e0d35bdb5..dab58b64f 100644 --- a/Ryujinx.sln +++ b/Ryujinx.sln @@ -34,7 +34,6 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig - appveyor.yml = appveyor.yml EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}" diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index b56a36d01..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,35 +0,0 @@ -version: 1.0.{build} -branches: - only: - - master -image: Visual Studio 2022 -environment: - appveyor_dotnet_runtime: net6.0 - matrix: - - config: Release - config_name: '-' -build_script: -- ps: >- - dotnet --version - - dotnet publish -c $env:config -r win-x64 /p:Version=$env:APPVEYOR_BUILD_VERSION /p:DebugType=embedded --self-contained - - dotnet publish -c $env:config -r linux-x64 /p:Version=$env:APPVEYOR_BUILD_VERSION /p:DebugType=embedded --self-contained - - 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-win_x64.zip $env:APPVEYOR_BUILD_FOLDER\Ryujinx\bin\$env:config\$env:appveyor_dotnet_runtime\win-x64\publish\ - - 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar $env:APPVEYOR_BUILD_FOLDER\Ryujinx\bin\$env:config\$env:appveyor_dotnet_runtime\linux-x64\publish\ - - 7z a ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar.gz ryujinx$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar - - 7z a ryujinx-headless-sdl2$env:config_name$env:APPVEYOR_BUILD_VERSION-win_x64.zip $env:APPVEYOR_BUILD_FOLDER\Ryujinx.Headless.SDL2\bin\$env:config\$env:appveyor_dotnet_runtime\win-x64\publish\ - - 7z a ryujinx-headless-sdl2$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar $env:APPVEYOR_BUILD_FOLDER\Ryujinx.Headless.SDL2\bin\$env:config\$env:appveyor_dotnet_runtime\linux-x64\publish\ - - 7z a ryujinx-headless-sdl2$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar.gz ryujinx-headless-sdl2$env:config_name$env:APPVEYOR_BUILD_VERSION-linux_x64.tar - -artifacts: -- path: ryujinx%config_name%%APPVEYOR_BUILD_VERSION%-win_x64.zip -- path: ryujinx%config_name%%APPVEYOR_BUILD_VERSION%-linux_x64.tar.gz -- path: ryujinx-headless-sdl2%config_name%%APPVEYOR_BUILD_VERSION%-win_x64.zip -- path: ryujinx-headless-sdl2%config_name%%APPVEYOR_BUILD_VERSION%-linux_x64.tar.gz From b944941733befdfbae802c29c496fe5125f045e2 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 31 Jan 2022 00:11:43 -0300 Subject: [PATCH 07/14] Fix bug that could cause depth buffer to be missing after clear (#3067) --- .../Engine/Threed/StateUpdater.cs | 16 ++++++++-------- Ryujinx.Graphics.Gpu/Image/TextureManager.cs | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 1a9aeb442..a65fc9085 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -369,14 +369,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed if (color != null) { - if (clipRegionWidth > color.Width) + if (clipRegionWidth > color.Width / samplesInX) { - clipRegionWidth = color.Width; + clipRegionWidth = color.Width / samplesInX; } - if (clipRegionHeight > color.Height) + if (clipRegionHeight > color.Height / samplesInY) { - clipRegionHeight = color.Height; + clipRegionHeight = color.Height / samplesInY; } } } @@ -400,14 +400,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed if (depthStencil != null) { - if (clipRegionWidth > depthStencil.Width) + if (clipRegionWidth > depthStencil.Width / samplesInX) { - clipRegionWidth = depthStencil.Width; + clipRegionWidth = depthStencil.Width / samplesInX; } - if (clipRegionHeight > depthStencil.Height) + if (clipRegionHeight > depthStencil.Height / samplesInY) { - clipRegionHeight = depthStencil.Height; + clipRegionHeight = depthStencil.Height / samplesInY; } } } diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs index 90e26442b..a1c292912 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs @@ -434,6 +434,7 @@ namespace Ryujinx.Graphics.Gpu.Image { new Span(_rtHostColors).Fill(null); _rtHostColors[index] = _rtColors[index]?.HostTexture; + _rtHostDs = null; _context.Renderer.Pipeline.SetRenderTargets(_rtHostColors, null); } From 76b9041adf12e8bc692a489d0081791a93932a32 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Mon, 31 Jan 2022 10:34:21 -0700 Subject: [PATCH 08/14] Fix the pronunciation of Ryujinx (#3059) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4cc8d9a36..1cc633042 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@
Ryujinx
- (REE-YOU-JI-NX) + (REE-YOU-JINX)
From d317cfd639bde1e22970799181adec5f37573995 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Wed, 2 Feb 2022 14:49:49 -0700 Subject: [PATCH 09/14] Try to ensure save data always has a valid owner ID (#3057) - Run the extra data fix in FixExtraData on non-system saves that have no owner ID. - Set the owner ID in the dummy application control property if an application doesn't have a proper one available. --- Ryujinx.HLE/FileSystem/VirtualFileSystem.cs | 4 +++- Ryujinx.HLE/HOS/ApplicationLoader.cs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs index f2d20cb1f..9359b03c7 100644 --- a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs +++ b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs @@ -505,7 +505,9 @@ namespace Ryujinx.HLE.FileSystem bool canFixBySaveDataId = extraData.Attribute.StaticSaveDataId == 0 && info.StaticSaveDataId != 0; - if (!canFixByProgramId && !canFixBySaveDataId) + bool hasEmptyOwnerId = extraData.OwnerId == 0 && info.Type != LibHac.Fs.SaveDataType.System; + + if (!canFixByProgramId && !canFixBySaveDataId && !hasEmptyOwnerId) { wasFixNeeded = false; return Result.Success; diff --git a/Ryujinx.HLE/HOS/ApplicationLoader.cs b/Ryujinx.HLE/HOS/ApplicationLoader.cs index 8ceed5ea6..65448d5da 100644 --- a/Ryujinx.HLE/HOS/ApplicationLoader.cs +++ b/Ryujinx.HLE/HOS/ApplicationLoader.cs @@ -776,6 +776,7 @@ namespace Ryujinx.HLE.HOS // The set sizes don't actually matter as long as they're non-zero because we use directory savedata. control.UserAccountSaveDataSize = 0x4000; control.UserAccountSaveDataJournalSize = 0x4000; + control.SaveDataOwnerId = applicationId; Logger.Warning?.Print(LogClass.Application, "No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games."); From 222b1ad7da04830852664dbd465117e441211f28 Mon Sep 17 00:00:00 2001 From: merry Date: Sun, 6 Feb 2022 01:01:05 +0000 Subject: [PATCH 10/14] ARMeilleure: OpCodeTable: Add CMN (RsReg) (#3087) --- ARMeilleure/Decoders/OpCodeTable.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index be7c8c960..78537787d 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -654,6 +654,7 @@ namespace ARMeilleure.Decoders SetA32("<<<<000101101111xxxx11110001xxxx", InstName.Clz, InstEmit32.Clz, OpCode32AluReg.Create); SetA32("<<<<00110111xxxx0000xxxxxxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluImm.Create); SetA32("<<<<00010111xxxx0000xxxxxxx0xxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluRsImm.Create); + SetA32("<<<<00010111xxxx0000xxxx0xx1xxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluRsReg.Create); SetA32("<<<<00110101xxxx0000xxxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCode32AluImm.Create); SetA32("<<<<00010101xxxx0000xxxxxxx0xxxx", InstName.Cmp, InstEmit32.Cmp, OpCode32AluRsImm.Create); SetA32("<<<<00010101xxxx0000xxxx0xx1xxxx", InstName.Cmp, InstEmit32.Cmp, OpCode32AluRsReg.Create); From 88d3ffb97c9d6e29a7eb44135ccea88753ca5f61 Mon Sep 17 00:00:00 2001 From: merry Date: Sun, 6 Feb 2022 15:25:45 +0000 Subject: [PATCH 11/14] ARMeilleure: A32: Implement SHADD8 (#3086) --- ARMeilleure/Decoders/OpCodeTable.cs | 1 + ARMeilleure/Instructions/InstEmitAlu32.cs | 52 ++++++++++++++++------- ARMeilleure/Instructions/InstName.cs | 1 + Ryujinx.Tests/Cpu/CpuTestAlu32.cs | 21 ++++++++- 4 files changed, 59 insertions(+), 16 deletions(-) diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index 78537787d..d54bb5a51 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -733,6 +733,7 @@ namespace ARMeilleure.Decoders SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsReg.Create); SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCode32AluBf.Create); SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCode32AluMla.Create); + SetA32("<<<<01100011xxxxxxxx11111001xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCode32AluReg.Create); SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smla__, InstEmit32.Smla__, OpCode32AluMla.Create); SetA32("<<<<0000111xxxxxxxxxxxxx1001xxxx", InstName.Smlal, InstEmit32.Smlal, OpCode32AluUmull.Create); SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlal__, InstEmit32.Smlal__, OpCode32AluUmull.Create); diff --git a/ARMeilleure/Instructions/InstEmitAlu32.cs b/ARMeilleure/Instructions/InstEmitAlu32.cs index 5f55fcd19..9aff0261c 100644 --- a/ARMeilleure/Instructions/InstEmitAlu32.cs +++ b/ARMeilleure/Instructions/InstEmitAlu32.cs @@ -387,6 +387,11 @@ namespace ARMeilleure.Instructions EmitDiv(context, false); } + public static void Shadd8(ArmEmitterContext context) + { + EmitHadd8(context, false); + } + public static void Ssat(ArmEmitterContext context) { OpCode32Sat op = (OpCode32Sat)context.CurrOp; @@ -474,20 +479,7 @@ namespace ARMeilleure.Instructions public static void Uhadd8(ArmEmitterContext context) { - OpCode32AluReg op = (OpCode32AluReg)context.CurrOp; - - Operand m = GetIntA32(context, op.Rm); - Operand n = GetIntA32(context, op.Rn); - - Operand xor, res; - - res = context.BitwiseAnd(m, n); - xor = context.BitwiseExclusiveOr(m, n); - xor = context.ShiftRightUI(xor, Const(1)); - xor = context.BitwiseAnd(xor, Const(0x7F7F7F7Fu)); - res = context.Add(res, xor); - - SetIntA32(context, op.Rd, res); + EmitHadd8(context, true); } public static void Usat(ArmEmitterContext context) @@ -659,6 +651,36 @@ namespace ARMeilleure.Instructions context.MarkLabel(lblEnd); } + private static void EmitHadd8(ArmEmitterContext context, bool unsigned) + { + OpCode32AluReg op = (OpCode32AluReg)context.CurrOp; + + Operand m = GetIntA32(context, op.Rm); + Operand n = GetIntA32(context, op.Rn); + + Operand xor, res, carry; + + // This relies on the equality x+y == ((x&y) << 1) + (x^y). + // Note that x^y always contains the LSB of the result. + // Since we want to calculate (x+y)/2, we can instead calculate (x&y) + ((x^y)>>1). + // We mask by 0x7F to remove the LSB so that it doesn't leak into the field below. + + res = context.BitwiseAnd(m, n); + carry = context.BitwiseExclusiveOr(m, n); + xor = context.ShiftRightUI(carry, Const(1)); + xor = context.BitwiseAnd(xor, Const(0x7F7F7F7Fu)); + res = context.Add(res, xor); + + if (!unsigned) + { + // Propagates the sign bit from (x^y)>>1 upwards by one. + carry = context.BitwiseAnd(carry, Const(0x80808080u)); + res = context.BitwiseExclusiveOr(res, carry); + } + + SetIntA32(context, op.Rd, res); + } + private static void EmitSat(ArmEmitterContext context, int intMin, int intMax) { OpCode32Sat op = (OpCode32Sat)context.CurrOp; @@ -772,4 +794,4 @@ namespace ARMeilleure.Instructions EmitGenericAluStoreA32(context, op.Rd, op.SetFlags, value); } } -} \ No newline at end of file +} diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs index a520c86a3..698979b9a 100644 --- a/ARMeilleure/Instructions/InstName.cs +++ b/ARMeilleure/Instructions/InstName.cs @@ -516,6 +516,7 @@ namespace ARMeilleure.Instructions Rsb, Rsc, Sbfx, + Shadd8, Smla__, Smlal, Smlal__, diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs index 1867e27fe..7a30f138e 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs @@ -77,6 +77,25 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } + [Test, Pairwise] + public void Shadd8([Values(0u, 0xdu)] uint rd, + [Values(1u)] uint rm, + [Values(2u)] uint rn, + [Random(RndCnt)] uint w0, + [Random(RndCnt)] uint w1, + [Random(RndCnt)] uint w2) + { + uint opcode = 0xE6300F90u; // SHADD8 R0, R0, R0 + + opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); + + uint sp = TestContext.CurrentContext.Random.NextUInt(); + + SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp); + + CompareAgainstUnicorn(); + } + [Test, Pairwise] public void Ssat_Usat([ValueSource("_Ssat_Usat_")] uint opcode, [Values(0u, 0xdu)] uint rd, @@ -120,7 +139,7 @@ namespace Ryujinx.Tests.Cpu [Random(RndCnt)] uint w1, [Random(RndCnt)] uint w2) { - uint opcode = 0xE6700F90u; //UHADD8 R0, R0, R0 + uint opcode = 0xE6700F90u; // UHADD8 R0, R0, R0 opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); From 5c3112aaeb66e94571be09491349833d9f6958a2 Mon Sep 17 00:00:00 2001 From: edisionnano Date: Sun, 6 Feb 2022 17:52:39 +0200 Subject: [PATCH 12/14] Convert the bool to a lowercase string (#3080) mesa_glthread doesn't accept PascalCase input --- Ryujinx.Common/GraphicsDriver/DriverUtilities.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ryujinx.Common/GraphicsDriver/DriverUtilities.cs b/Ryujinx.Common/GraphicsDriver/DriverUtilities.cs index 60c176f83..3aabced7c 100644 --- a/Ryujinx.Common/GraphicsDriver/DriverUtilities.cs +++ b/Ryujinx.Common/GraphicsDriver/DriverUtilities.cs @@ -6,7 +6,7 @@ namespace Ryujinx.Common.GraphicsDriver { public static void ToggleOGLThreading(bool enabled) { - Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString()); + Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString().ToLower()); Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0"); try From 863c5811903d9fe1020d966028ce6a030477be92 Mon Sep 17 00:00:00 2001 From: wss445566 Date: Mon, 7 Feb 2022 18:50:51 +0800 Subject: [PATCH 13/14] fix headless sdl2 option string (#3093) --- Ryujinx.Headless.SDL2/Options.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Ryujinx.Headless.SDL2/Options.cs b/Ryujinx.Headless.SDL2/Options.cs index c8829d064..2b52dfbe1 100644 --- a/Ryujinx.Headless.SDL2/Options.cs +++ b/Ryujinx.Headless.SDL2/Options.cs @@ -100,7 +100,7 @@ namespace Ryujinx.Headless.SDL2 [Option("system-language", Required = false, Default = SystemLanguage.AmericanEnglish, HelpText = "Change System Language.")] public SystemLanguage SystemLanguage { get; set; } - [Option("system-language", Required = false, Default = RegionCode.USA, HelpText = "Change System Region.")] + [Option("system-region", Required = false, Default = RegionCode.USA, HelpText = "Change System Region.")] public RegionCode SystemRegion { get; set; } [Option("system-timezone", Required = false, Default = "UTC", HelpText = "Change System TimeZone.")] @@ -132,7 +132,7 @@ namespace Ryujinx.Headless.SDL2 [Option("enable-warning-logs", Required = false, Default = true, HelpText = "Enables printing warning log messages.")] public bool? LoggingEnableWarning { get; set; } - [Option("enable-warning-logs", Required = false, Default = true, HelpText = "Enables printing error log messages.")] + [Option("enable-error-logs", Required = false, Default = true, HelpText = "Enables printing error log messages.")] public bool? LoggingEnableError { get; set; } [Option("enable-guest-logs", Required = false, Default = true, HelpText = "Enables printing guest log messages.")] From 86b37d0ff7764ac62b1e9578b07a8b648a3bd55a Mon Sep 17 00:00:00 2001 From: merry Date: Tue, 8 Feb 2022 09:46:42 +0000 Subject: [PATCH 14/14] ARMeilleure: A32: Implement SHSUB8 and UHSUB8 (#3089) * ARMeilleure: A32: Implement UHSUB8 * ARMeilleure: A32: Implement SHSUB8 --- ARMeilleure/Decoders/OpCodeTable.cs | 2 + ARMeilleure/Instructions/InstEmitAlu32.cs | 45 +++++++++++++++++++++++ ARMeilleure/Instructions/InstName.cs | 2 + Ryujinx.Tests/Cpu/CpuTestAlu32.cs | 38 +++++++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index d54bb5a51..53328a735 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -734,6 +734,7 @@ namespace ARMeilleure.Decoders SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCode32AluBf.Create); SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCode32AluMla.Create); SetA32("<<<<01100011xxxxxxxx11111001xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCode32AluReg.Create); + SetA32("<<<<01100011xxxxxxxx11111111xxxx", InstName.Shsub8, InstEmit32.Shsub8, OpCode32AluReg.Create); SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smla__, InstEmit32.Smla__, OpCode32AluMla.Create); SetA32("<<<<0000111xxxxxxxxxxxxx1001xxxx", InstName.Smlal, InstEmit32.Smlal, OpCode32AluUmull.Create); SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlal__, InstEmit32.Smlal__, OpCode32AluUmull.Create); @@ -782,6 +783,7 @@ namespace ARMeilleure.Decoders SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCode32AluBf.Create); SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, OpCode32AluMla.Create); SetA32("<<<<01100111xxxxxxxx11111001xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCode32AluReg.Create); + SetA32("<<<<01100111xxxxxxxx11111111xxxx", InstName.Uhsub8, InstEmit32.Uhsub8, OpCode32AluReg.Create); SetA32("<<<<00000100xxxxxxxxxxxx1001xxxx", InstName.Umaal, InstEmit32.Umaal, OpCode32AluUmull.Create); SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, OpCode32AluUmull.Create); SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create); diff --git a/ARMeilleure/Instructions/InstEmitAlu32.cs b/ARMeilleure/Instructions/InstEmitAlu32.cs index 9aff0261c..66b8a8a7e 100644 --- a/ARMeilleure/Instructions/InstEmitAlu32.cs +++ b/ARMeilleure/Instructions/InstEmitAlu32.cs @@ -392,6 +392,11 @@ namespace ARMeilleure.Instructions EmitHadd8(context, false); } + public static void Shsub8(ArmEmitterContext context) + { + EmitHsub8(context, false); + } + public static void Ssat(ArmEmitterContext context) { OpCode32Sat op = (OpCode32Sat)context.CurrOp; @@ -482,6 +487,11 @@ namespace ARMeilleure.Instructions EmitHadd8(context, true); } + public static void Uhsub8(ArmEmitterContext context) + { + EmitHsub8(context, true); + } + public static void Usat(ArmEmitterContext context) { OpCode32Sat op = (OpCode32Sat)context.CurrOp; @@ -681,6 +691,41 @@ namespace ARMeilleure.Instructions SetIntA32(context, op.Rd, res); } + private static void EmitHsub8(ArmEmitterContext context, bool unsigned) + { + OpCode32AluReg op = (OpCode32AluReg)context.CurrOp; + + Operand m = GetIntA32(context, op.Rm); + Operand n = GetIntA32(context, op.Rn); + Operand left, right, carry, res; + + // This relies on the equality x-y == (x^y) - (((x^y)&y) << 1). + // Note that x^y always contains the LSB of the result. + // Since we want to calculate (x+y)/2, we can instead calculate ((x^y)>>1) - ((x^y)&y). + + carry = context.BitwiseExclusiveOr(m, n); + left = context.ShiftRightUI(carry, Const(1)); + right = context.BitwiseAnd(carry, m); + + // We must now perform a partitioned subtraction. + // We can do this because minuend contains 7 bit fields. + // We use the extra bit in minuend as a bit to borrow from; we set this bit. + // We invert this bit at the end as this tells us if that bit was borrowed from. + + res = context.BitwiseOr(left, Const(0x80808080)); + res = context.Subtract(res, right); + res = context.BitwiseExclusiveOr(res, Const(0x80808080)); + + if (!unsigned) + { + // We then sign extend the result into this bit. + carry = context.BitwiseAnd(carry, Const(0x80808080)); + res = context.BitwiseExclusiveOr(res, carry); + } + + SetIntA32(context, op.Rd, res); + } + private static void EmitSat(ArmEmitterContext context, int intMin, int intMax) { OpCode32Sat op = (OpCode32Sat)context.CurrOp; diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs index 698979b9a..3e0164958 100644 --- a/ARMeilleure/Instructions/InstName.cs +++ b/ARMeilleure/Instructions/InstName.cs @@ -80,6 +80,7 @@ namespace ARMeilleure.Instructions Sbcs, Sbfm, Sdiv, + Shsub8, Smaddl, Smsubl, Smulh, @@ -546,6 +547,7 @@ namespace ARMeilleure.Instructions Tst, Ubfx, Uhadd8, + Uhsub8, Umaal, Umlal, Umull, diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs index 7a30f138e..170bf98bd 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs @@ -96,6 +96,25 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } + [Test, Pairwise] + public void Shsub8([Values(0u, 0xdu)] uint rd, + [Values(1u)] uint rm, + [Values(2u)] uint rn, + [Random(RndCnt)] uint w0, + [Random(RndCnt)] uint w1, + [Random(RndCnt)] uint w2) + { + uint opcode = 0xE6300FF0u; // SHSUB8 R0, R0, R0 + + opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); + + uint sp = TestContext.CurrentContext.Random.NextUInt(); + + SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp); + + CompareAgainstUnicorn(); + } + [Test, Pairwise] public void Ssat_Usat([ValueSource("_Ssat_Usat_")] uint opcode, [Values(0u, 0xdu)] uint rd, @@ -149,6 +168,25 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } + + [Test, Pairwise] + public void Uhsub8([Values(0u, 0xdu)] uint rd, + [Values(1u)] uint rm, + [Values(2u)] uint rn, + [Random(RndCnt)] uint w0, + [Random(RndCnt)] uint w1, + [Random(RndCnt)] uint w2) + { + uint opcode = 0xE6700FF0u; // UHSUB8 R0, R0, R0 + + opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); + + uint sp = TestContext.CurrentContext.Random.NextUInt(); + + SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp); + + CompareAgainstUnicorn(); + } #endif } }