Compare commits

...

22 Commits

Author SHA1 Message Date
ab5d77c0c4 amadeus: Fix limiter correctness (#3126)
This fixes missing audio on Nintendo Switch Sports Online Play Test.
2022-02-16 21:38:45 +01:00
7bfb5f79b8 When copying linear textures, DMA should ignore region X/Y (#3121) 2022-02-16 11:13:45 +01:00
8cc2479825 Adjusting how deadzones are calculated (#3079)
* Making deadzones feel nice and smooth + adding rider files to .gitignore

* removing unnecessary parentheses and fixing possibility of divide by 0

* formatting :)

* fixing up ClampAxis

* fixing up ClampAxis
2022-02-16 11:06:52 +01:00
8f35345729 Use Enum and Delegate.CreateDelegate generic overloads (#3111)
* Use Enum generic overloads

* Remove EnumExtensions.cs

* Use Delegate.CreateDelegate generic overloads
2022-02-13 10:50:07 -03:00
ce71f9144e InstEmitMemory32: Literal loads always have word-aligned PC (#3104) 2022-02-11 17:51:03 -03:00
f861f0bca2 Fix missing geometry shader passthrough inputs (#3106)
* Fix missing geometry shader passthrough inputs

* Shader cache version bump
2022-02-11 19:52:20 +01:00
571496d243 Ship SoundIO library only for the specified runtime (#3103)
* Add RuntimeIdentifers properties

For Linux, Windows and OS X x86-64
This ensures that the SoundIO project gets this property when built as a subproject

* Address gdkchan's nit

Merge tags into one
2022-02-11 00:15:13 +01:00
c3c3914ed3 Add a limit on the number of uses a constant may have (#3097) 2022-02-09 17:42:47 -03:00
6dffe0fad4 misc: Make PID unsigned long instead of long (#3043) 2022-02-09 17:18:07 -03:00
86b37d0ff7 ARMeilleure: A32: Implement SHSUB8 and UHSUB8 (#3089)
* ARMeilleure: A32: Implement UHSUB8

* ARMeilleure: A32: Implement SHSUB8
2022-02-08 10:46:42 +01:00
863c581190 fix headless sdl2 option string (#3093) 2022-02-07 11:50:51 +01:00
5c3112aaeb Convert the bool to a lowercase string (#3080)
mesa_glthread doesn't accept PascalCase input
2022-02-06 12:52:39 -03:00
88d3ffb97c ARMeilleure: A32: Implement SHADD8 (#3086) 2022-02-06 12:25:45 -03:00
222b1ad7da ARMeilleure: OpCodeTable: Add CMN (RsReg) (#3087) 2022-02-06 02:01:05 +01:00
d317cfd639 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.
2022-02-02 14:49:49 -07:00
76b9041adf Fix the pronunciation of Ryujinx (#3059) 2022-01-31 18:34:21 +01:00
b944941733 Fix bug that could cause depth buffer to be missing after clear (#3067) 2022-01-31 00:11:43 -03:00
0dddcd012c Remove Appveyor from Readme and SLN (#3026)
* Replace Appveyor with Github badge.

* Delete appveyor.yml

* Remove Appveyor from SLN
2022-01-30 16:41:22 +01:00
bd412afb9f Fix small precision error on CPU reciprocal estimate instructions (#3061)
* Fix small precision error on CPU reciprocal estimate instructions

* PPTC version bump
2022-01-29 23:59:34 +01:00
20ce37dee6 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
2022-01-29 22:18:03 +01:00
c52158b733 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.
2022-01-27 22:50:32 +01:00
fd6d3ec88f 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.
2022-01-27 14:17:13 -03:00
99 changed files with 823 additions and 593 deletions

3
.gitignore vendored
View File

@ -74,6 +74,9 @@ _TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Rider is a Visual Studio alternative
.idea/*
# NCrunch
*.ncrunch*
.*crunch*.local.xml

View File

@ -9,13 +9,17 @@ namespace ARMeilleure.CodeGen.X86
{
static class X86Optimizer
{
private const int MaxConstantUses = 10000;
public static void RunPass(ControlFlowGraph cfg)
{
var constants = new Dictionary<ulong, Operand>();
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
{
if (!constants.TryGetValue(source.Value, out var constant))
// If the constant has many uses, we also force a new constant mov to be added, in order
// to avoid overflow of the counts field (that is limited to 16 bits).
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses)
{
constant = Local(source.Type);
@ -23,7 +27,7 @@ namespace ARMeilleure.CodeGen.X86
block.Operations.AddBefore(operation, copyOp);
constants.Add(source.Value, constant);
constants[source.Value] = constant;
}
return constant;

View File

@ -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);
@ -732,6 +733,8 @@ 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("<<<<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);
@ -780,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);

View File

@ -387,6 +387,16 @@ namespace ARMeilleure.Instructions
EmitDiv(context, false);
}
public static void Shadd8(ArmEmitterContext context)
{
EmitHadd8(context, false);
}
public static void Shsub8(ArmEmitterContext context)
{
EmitHsub8(context, false);
}
public static void Ssat(ArmEmitterContext context)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
@ -474,20 +484,12 @@ namespace ARMeilleure.Instructions
public static void Uhadd8(ArmEmitterContext context)
{
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
EmitHadd8(context, true);
}
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);
public static void Uhsub8(ArmEmitterContext context)
{
EmitHsub8(context, true);
}
public static void Usat(ArmEmitterContext context)
@ -659,6 +661,71 @@ 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 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;
@ -772,4 +839,4 @@ namespace ARMeilleure.Instructions
EmitGenericAluStoreA32(context, op.Rd, op.SetFlags, value);
}
}
}
}

View File

@ -47,6 +47,20 @@ namespace ARMeilleure.Instructions
}
}
public static Operand GetIntA32AlignedPC(ArmEmitterContext context, int regIndex)
{
if (regIndex == RegisterAlias.Aarch32Pc)
{
OpCode32 op = (OpCode32)context.CurrOp;
return Const((int)(op.GetPc() & 0xfffffffc));
}
else
{
return Register(GetRegisterAlias(context.Mode, regIndex), RegisterType.Integer, OperandType.I32);
}
}
public static Operand GetVecA32(int regIndex)
{
return Register(regIndex, RegisterType.Vector, OperandType.V128);

View File

@ -153,7 +153,7 @@ namespace ARMeilleure.Instructions
{
OpCode32Mem op = (OpCode32Mem)context.CurrOp;
Operand n = context.Copy(GetIntA32(context, op.Rn));
Operand n = context.Copy(GetIntA32AlignedPC(context, op.Rn));
Operand m = GetMemM(context, setCarry: false);
Operand temp = default;

View File

@ -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);

View File

@ -80,6 +80,7 @@ namespace ARMeilleure.Instructions
Sbcs,
Sbfm,
Sdiv,
Shsub8,
Smaddl,
Smsubl,
Smulh,
@ -516,6 +517,7 @@ namespace ARMeilleure.Instructions
Rsb,
Rsc,
Sbfx,
Shadd8,
Smla__,
Smlal,
Smlal__,
@ -545,6 +547,7 @@ namespace ARMeilleure.Instructions
Tst,
Ubfx,
Uhadd8,
Uhsub8,
Umaal,
Umlal,
Umull,

View File

@ -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";

View File

@ -5,7 +5,7 @@
<br>
<b>Ryujinx</b>
<br>
<sub><sup><b>(REE-YOU-JI-NX)</b></sup></sub>
<sub><sup><b>(REE-YOU-JINX)</b></sup></sub>
<br>
</h1>
@ -17,8 +17,8 @@
</p>
<p align="center">
<a href="https://ci.appveyor.com/project/gdkchan/ryujinx?branch=master">
<img src="https://ci.appveyor.com/api/projects/status/ssg4jwu6ve3k594s/branch/master?svg=true"
<a href="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml">
<img src="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml/badge.svg"
alt="">
</a>
<a href="https://discord.com/invite/VkQYXAZ">

View File

@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
</PropertyGroup>
<ItemGroup>

View File

@ -100,9 +100,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
{
float inputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
float sampleInputMax = Math.Abs(inputSample * Parameter.InputGain);
float inputSample = (rawInputSample / short.MaxValue) * Parameter.InputGain;
float sampleInputMax = Math.Abs(inputSample);
float inputCoefficient = Parameter.ReleaseCoefficient;
@ -131,7 +133,9 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
*((float*)outputBuffers[channelIndex] + sampleIndex) = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
float outputSample = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
delayedSample = inputSample;

View File

@ -111,9 +111,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
{
float inputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
float rawInputSample = *((float*)inputBuffers[channelIndex] + sampleIndex);
float sampleInputMax = Math.Abs(inputSample * Parameter.InputGain);
float inputSample = (rawInputSample / short.MaxValue) * Parameter.InputGain;
float sampleInputMax = Math.Abs(inputSample);
float inputCoefficient = Parameter.ReleaseCoefficient;
@ -142,7 +144,9 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
*((float*)outputBuffers[channelIndex] + sampleIndex) = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
float outputSample = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
delayedSample = inputSample;

View File

@ -37,6 +37,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
DectectorAverage.AsSpan().Fill(0.0f);
CompressionGain.AsSpan().Fill(1.0f);
DelayedSampleBufferPosition.AsSpan().Fill(0);
DelayedSampleBuffer.AsSpan().Fill(0.0f);
UpdateParameter(ref parameter);
}

View File

@ -558,7 +558,16 @@ namespace Ryujinx.Audio.Renderer.Server
if (_rendererContext.BehaviourContext.IsEffectInfoVersion2Supported())
{
Memory<EffectResultState> dspResultState = _effectContext.GetDspStateMemory(effectId);
Memory<EffectResultState> dspResultState;
if (effect.Parameter.StatisticsEnabled)
{
dspResultState = _effectContext.GetDspStateMemory(effectId);
}
else
{
dspResultState = Memory<EffectResultState>.Empty;
}
_commandBuffer.GenerateLimiterEffectVersion2(bufferOffset, effect.Parameter, effect.State, dspResultState, effect.IsEnabled, workBuffer, nodeId);
}

View File

@ -1,12 +0,0 @@
using System;
namespace Ryujinx.Common
{
public static class EnumExtensions
{
public static T[] GetValues<T>()
{
return (T[])Enum.GetValues(typeof(T));
}
}
}

View File

@ -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

View File

@ -94,7 +94,7 @@ namespace Ryujinx.Common.Logging
static Logger()
{
m_EnabledClasses = new bool[Enum.GetNames(typeof(LogClass)).Length];
m_EnabledClasses = new bool[Enum.GetNames<LogClass>().Length];
for (int index = 0; index < m_EnabledClasses.Length; index++)
{

View File

@ -85,9 +85,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
}
int alignWidth = Constants.StrideAlignment / bpp;
return tex.RegionX == 0 &&
tex.RegionY == 0 &&
stride / bpp == BitUtils.AlignUp(xCount, alignWidth);
return stride / bpp == BitUtils.AlignUp(xCount, alignWidth);
}
else
{
@ -115,7 +113,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);
}
}
}
@ -160,6 +159,20 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
var dst = Unsafe.As<uint, DmaTexture>(ref _state.State.SetDstBlockSize);
var src = Unsafe.As<uint, DmaTexture>(ref _state.State.SetSrcBlockSize);
int srcRegionX = 0, srcRegionY = 0, dstRegionX = 0, dstRegionY = 0;
if (!srcLinear)
{
srcRegionX = src.RegionX;
srcRegionY = src.RegionY;
}
if (!dstLinear)
{
dstRegionX = dst.RegionX;
dstRegionY = dst.RegionY;
}
int srcStride = (int)_state.State.PitchIn;
int dstStride = (int)_state.State.PitchOut;
@ -181,8 +194,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
dst.MemoryLayout.UnpackGobBlocksInZ(),
dstBpp);
(int srcBaseOffset, int srcSize) = srcCalculator.GetRectangleRange(src.RegionX, src.RegionY, xCount, yCount);
(int dstBaseOffset, int dstSize) = dstCalculator.GetRectangleRange(dst.RegionX, dst.RegionY, xCount, yCount);
(int srcBaseOffset, int srcSize) = srcCalculator.GetRectangleRange(srcRegionX, srcRegionY, xCount, yCount);
(int dstBaseOffset, int dstSize) = dstCalculator.GetRectangleRange(dstRegionX, dstRegionY, xCount, yCount);
if (srcLinear && srcStride < 0)
{
@ -271,13 +284,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
for (int y = 0; y < yCount; y++)
{
srcCalculator.SetY(src.RegionY + y);
dstCalculator.SetY(dst.RegionY + y);
srcCalculator.SetY(srcRegionY + y);
dstCalculator.SetY(dstRegionY + y);
for (int x = 0; x < xCount; x++)
{
int srcOffset = srcCalculator.GetOffset(src.RegionX + x);
int dstOffset = dstCalculator.GetOffset(dst.RegionX + x);
int srcOffset = srcCalculator.GetOffset(srcRegionX + x);
int dstOffset = dstCalculator.GetOffset(dstRegionX + x);
*(T*)(dstBase + dstOffset) = *(T*)(srcBase + srcOffset);
}

View File

@ -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)
{

View File

@ -112,7 +112,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
_ilGen.Emit(OpCodes.Ret);
}
return (MacroExecute)_meth.CreateDelegate(typeof(MacroExecute));
return _meth.CreateDelegate<MacroExecute>();
}
/// <summary>

View File

@ -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
/// </summary>
class SemaphoreUpdater
{
private const int NsToTicksFractionNumerator = 384;
private const int NsToTicksFractionDenominator = 625;
/// <summary>
/// GPU semaphore operation.
/// </summary>
@ -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);
}
/// <summary>
/// Converts a nanoseconds timestamp value to Maxwell time ticks.
/// </summary>
/// <remarks>
/// The frequency is 614400000 Hz.
/// </remarks>
/// <param name="nanoseconds">Timestamp in nanoseconds</param>
/// <returns>Maxwell ticks</returns>
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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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
/// </summary>
public sealed class GpuContext : IDisposable
{
private const int NsToTicksFractionNumerator = 384;
private const int NsToTicksFractionDenominator = 625;
/// <summary>
/// Event signaled when the host emulation context is ready to be used by the gpu context.
/// </summary>
@ -73,7 +77,7 @@ namespace Ryujinx.Graphics.Gpu
/// <summary>
/// Registry with physical memories that can be used with this GPU context, keyed by owner process ID.
/// </summary>
internal ConcurrentDictionary<long, PhysicalMemory> PhysicalMemoryRegistry { get; }
internal ConcurrentDictionary<ulong, PhysicalMemory> PhysicalMemoryRegistry { get; }
/// <summary>
/// Host hardware capabilities.
@ -122,7 +126,7 @@ namespace Ryujinx.Graphics.Gpu
DeferredActions = new Queue<Action>();
PhysicalMemoryRegistry = new ConcurrentDictionary<long, PhysicalMemory>();
PhysicalMemoryRegistry = new ConcurrentDictionary<ulong, PhysicalMemory>();
}
/// <summary>
@ -140,7 +144,7 @@ namespace Ryujinx.Graphics.Gpu
/// <param name="pid">ID of the process that owns the memory manager</param>
/// <returns>The memory manager</returns>
/// <exception cref="ArgumentException">Thrown when <paramref name="pid"/> is invalid</exception>
public MemoryManager CreateMemoryManager(long pid)
public MemoryManager CreateMemoryManager(ulong pid)
{
if (!PhysicalMemoryRegistry.TryGetValue(pid, out var physicalMemory))
{
@ -156,7 +160,7 @@ namespace Ryujinx.Graphics.Gpu
/// <param name="pid">ID of the process that owns <paramref name="cpuMemory"/></param>
/// <param name="cpuMemory">Virtual memory owned by the process</param>
/// <exception cref="ArgumentException">Thrown if <paramref name="pid"/> was already registered</exception>
public void RegisterProcess(long pid, Cpu.IVirtualMemoryManagerTracked cpuMemory)
public void RegisterProcess(ulong pid, Cpu.IVirtualMemoryManagerTracked cpuMemory)
{
var physicalMemory = new PhysicalMemory(this, cpuMemory);
if (!PhysicalMemoryRegistry.TryAdd(pid, physicalMemory))
@ -171,7 +175,7 @@ namespace Ryujinx.Graphics.Gpu
/// Unregisters a process, indicating that its memory will no longer be used, and that caches can be freed.
/// </summary>
/// <param name="pid">ID of the process</param>
public void UnregisterProcess(long pid)
public void UnregisterProcess(ulong pid)
{
if (PhysicalMemoryRegistry.TryRemove(pid, out var physicalMemory))
{
@ -180,6 +184,46 @@ namespace Ryujinx.Graphics.Gpu
}
}
/// <summary>
/// Converts a nanoseconds timestamp value to Maxwell time ticks.
/// </summary>
/// <remarks>
/// The frequency is 614400000 Hz.
/// </remarks>
/// <param name="nanoseconds">Timestamp in nanoseconds</param>
/// <returns>Maxwell ticks</returns>
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;
}
/// <summary>
/// Gets the value of the GPU timer.
/// </summary>
/// <returns>The current GPU timestamp</returns>
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;
}
/// <summary>
/// Shader cache state update handler.
/// </summary>

View File

@ -49,6 +49,7 @@ namespace Ryujinx.Graphics.Gpu.Image
private readonly float[] _scales;
private bool _scaleChanged;
private int _lastFragmentTotal;
/// <summary>
/// Constructs a new instance of the texture bindings manager.
@ -288,26 +289,30 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary>
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;

View File

@ -434,6 +434,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
new Span<ITexture>(_rtHostColors).Fill(null);
_rtHostColors[index] = _rtColors[index]?.HostTexture;
_rtHostDs = null;
_context.Renderer.Pipeline.SetRenderTargets(_rtHostColors, null);
}

View File

@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <summary>
/// Version of the codegen (to be changed when codegen or guest format change).
/// </summary>
private const ulong ShaderCodeGenVersion = 3012;
private const ulong ShaderCodeGenVersion = 3106;
// Progress reporting helpers
private volatile int _shaderCount;

View File

@ -122,7 +122,7 @@ namespace Ryujinx.Graphics.Gpu
/// <param name="userObj">User defined object passed to the release callback</param>
/// <exception cref="ArgumentException">Thrown when <paramref name="pid"/> is invalid</exception>
public void EnqueueFrameThreadSafe(
long pid,
ulong pid,
ulong address,
int width,
int height,

View File

@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.OpenGL
static FormatTable()
{
int tableSize = Enum.GetNames(typeof(Format)).Length;
int tableSize = Enum.GetNames<Format>().Length;
Table = new FormatInfo[tableSize];
TableImage = new SizedInternalFormat[tableSize];

View File

@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
public Counters()
{
int count = Enum.GetNames(typeof(CounterType)).Length;
int count = Enum.GetNames<CounterType>().Length;
_counterQueues = new CounterQueue[count];
}

View File

@ -490,7 +490,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
else
{
int usedAttributes = context.Config.UsedInputAttributes;
int usedAttributes = context.Config.UsedInputAttributes | context.Config.PassthroughAttributes;
while (usedAttributes != 0)
{
int index = BitOperations.TrailingZeroCount(usedAttributes);

View File

@ -102,7 +102,7 @@ namespace Ryujinx.HLE.FileSystem.Content
_contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>();
_locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>();
foreach (StorageId storageId in Enum.GetValues(typeof(StorageId)))
foreach (StorageId storageId in Enum.GetValues<StorageId>())
{
string contentDirectory = null;
string contentPathString = null;

View File

@ -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;

View File

@ -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.");

View File

@ -9,14 +9,14 @@ namespace Ryujinx.HLE.HOS
{
class ArmProcessContext<T> : IProcessContext where T : class, IVirtualMemoryManagerTracked, IMemoryManager
{
private readonly long _pid;
private readonly ulong _pid;
private readonly GpuContext _gpuContext;
private readonly CpuContext _cpuContext;
private T _memoryManager;
public IVirtualMemoryManager AddressSpace => _memoryManager;
public ArmProcessContext(long pid, GpuContext gpuContext, T memoryManager, bool for64Bit)
public ArmProcessContext(ulong pid, GpuContext gpuContext, T memoryManager, bool for64Bit)
{
if (memoryManager is IRefCounted rc)
{

View File

@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS
_gpu = gpu;
}
public IProcessContext Create(KernelContext context, long pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
{
MemoryManagerMode mode = context.Device.Configuration.MemoryManagerMode;

View File

@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Ipc
{
public bool HasPId { get; private set; }
public long PId { get; private set; }
public ulong PId { get; private set; }
public int[] ToCopy { get; private set; }
public int[] ToMove { get; private set; }
@ -21,7 +21,7 @@ namespace Ryujinx.HLE.HOS.Ipc
ToCopy = new int[(word >> 1) & 0xf];
ToMove = new int[(word >> 5) & 0xf];
PId = HasPId ? reader.ReadInt64() : 0;
PId = HasPId ? reader.ReadUInt64() : 0;
for (int index = 0; index < ToCopy.Length; index++)
{
@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Ipc
ToMove = move ?? throw new ArgumentNullException(nameof(move));
}
public IpcHandleDesc(int[] copy, int[] move, long pId) : this(copy, move)
public IpcHandleDesc(int[] copy, int[] move, ulong pId) : this(copy, move)
{
PId = pId;

View File

@ -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<T>(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<T>()))
{
value = currentProcess.CpuMemory.Read<int>(address);
value = currentProcess.CpuMemory.Read<T>(address);
return true;
}
value = 0;
value = default;
return false;
}
public static bool UserToKernelInt32Array(KernelContext context, ulong address, Span<int> values)
public static bool UserToKernelArray<T>(ulong address, Span<T> values) where T : unmanaged
{
KProcess currentProcess = KernelStatic.GetCurrentProcess();
for (int index = 0; index < values.Length; index++, address += 4)
Span<byte> data = MemoryMarshal.Cast<T, byte>(values);
if (currentProcess.CpuMemory.IsRangeMapped(address, (ulong)data.Length))
{
if (currentProcess.CpuMemory.IsMapped(address) &&
currentProcess.CpuMemory.IsMapped(address + 3))
{
values[index]= currentProcess.CpuMemory.Read<int>(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<T>(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<T>()))
{
currentProcess.CpuMemory.Write(address, value);

View File

@ -42,14 +42,14 @@ namespace Ryujinx.HLE.HOS.Kernel
public KSynchronization Synchronization { get; }
public KContextIdManager ContextIdManager { get; }
public ConcurrentDictionary<long, KProcess> Processes { get; }
public ConcurrentDictionary<ulong, KProcess> Processes { get; }
public ConcurrentDictionary<string, KAutoObject> AutoObjectNames { get; }
public bool ThreadReselectionRequested { get; set; }
private long _kipId;
private long _processId;
private long _threadUid;
private ulong _kipId;
private ulong _processId;
private ulong _threadUid;
public KernelContext(
Switch device,
@ -98,7 +98,7 @@ namespace Ryujinx.HLE.HOS.Kernel
KernelInitialized = true;
Processes = new ConcurrentDictionary<long, KProcess>();
Processes = new ConcurrentDictionary<ulong, KProcess>();
AutoObjectNames = new ConcurrentDictionary<string, KAutoObject>();
_kipId = KernelConstants.InitialKipId;
@ -115,17 +115,17 @@ namespace Ryujinx.HLE.HOS.Kernel
new Thread(PreemptionThreadStart) { Name = "HLE.PreemptionThread" }.Start();
}
public long NewThreadUid()
public ulong NewThreadUid()
{
return Interlocked.Increment(ref _threadUid) - 1;
}
public long NewKipId()
public ulong NewKipId()
{
return Interlocked.Increment(ref _kipId) - 1;
}
public long NewProcessId()
public ulong NewProcessId()
{
return Interlocked.Increment(ref _processId) - 1;
}

View File

@ -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)

View File

@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
{
private readonly SharedMemoryStorage _storage;
private readonly long _ownerPid;
private readonly ulong _ownerPid;
private readonly KMemoryPermission _ownerPermission;
private readonly KMemoryPermission _userPermission;
@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public KSharedMemory(
KernelContext context,
SharedMemoryStorage storage,
long ownerPid,
ulong ownerPid,
KMemoryPermission ownerPermission,
KMemoryPermission userPermission) : base(context)
{

View File

@ -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,

View File

@ -26,6 +26,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
KernelStack = 0x00002013,
CodeReadOnly = 0x00402214,
CodeWritable = 0x00402015,
UserMask = 0xff,
Mask = 0xffffffff,
PermissionChangeAllowed = 1 << 8,

View File

@ -4,6 +4,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
interface IProcessContextFactory
{
IProcessContext Create(KernelContext context, long pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit);
IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit);
}
}

View File

@ -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;
@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public ulong TitleId { get; private set; }
public bool IsApplication { get; private set; }
public long Pid { get; private set; }
public ulong Pid { get; private set; }
private long _creationTimestamp;
private ulong _entrypoint;
@ -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.
@ -131,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
Pid = KernelContext.NewKipId();
if (Pid == 0 || (ulong)Pid >= KernelConstants.InitialProcessId)
if (Pid == 0 || Pid >= KernelConstants.InitialProcessId)
{
throw new InvalidOperationException($"Invalid KIP Id {Pid}.");
}
@ -239,7 +239,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
Pid = KernelContext.NewProcessId();
if (Pid == -1 || (ulong)Pid < KernelConstants.InitialProcessId)
if (Pid == ulong.MaxValue || Pid < KernelConstants.InitialProcessId)
{
throw new InvalidOperationException($"Invalid Process Id {Pid}.");
}
@ -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()

View File

@ -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<int> 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;
}

View File

@ -4,7 +4,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
class ProcessContextFactory : IProcessContextFactory
{
public IProcessContext Create(KernelContext context, long pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
{
return new ProcessContext(new AddressSpaceManager(addressSpaceSize));
}

View File

@ -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) { }
}

View File

@ -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;
}
}
}

View File

@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
// Process
public KernelResult GetProcessId(int handle, out long pid)
public KernelResult GetProcessId(out ulong 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<int> 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<int>(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<int> handles, int replyTargetHandle, long timeout, out int handleIndex)
public KernelResult ReplyAndReceive(out int handleIndex, ReadOnlySpan<int> 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<int>(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 ulong 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<int> handles = new Span<int>(currentThread.WaitSyncHandles).Slice(0, handlesCount);
if (!KernelTransfer.UserToKernelInt32Array(_context, handlesPtr, handles))
if (!KernelTransfer.UserToKernelArray(handlesPtr, handles))
{
return KernelResult.UserCopyFailed;
}

View File

@ -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)
@ -235,12 +235,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
resultHigh = (uint)(result >> 32);
}
public KernelResult GetProcessId32([R(1)] int handle, [R(1)] out int pidLow, [R(2)] out int pidHigh)
public KernelResult GetProcessId32([R(1)] int handle, [R(1)] out uint pidLow, [R(2)] out uint pidHigh)
{
KernelResult result = _syscall.GetProcessId(handle, out long pid);
KernelResult result = _syscall.GetProcessId(out ulong pid, handle);
pidLow = (int)(pid & uint.MaxValue);
pidHigh = (int)(pid >> 32);
pidLow = (uint)(pid & uint.MaxValue);
pidHigh = (uint)(pid >> 32);
return result;
}
@ -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);
}
@ -413,9 +413,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
public KernelResult GetThreadId32([R(1)] int handle, [R(1)] out uint threadUidLow, [R(2)] out uint threadUidHigh)
{
long threadUid;
ulong 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)

View File

@ -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)
@ -232,9 +232,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return _syscall.GetSystemTick();
}
public KernelResult GetProcessId64([R(1)] int handle, [R(1)] out long pid)
public KernelResult GetProcessId64([R(1)] int handle, [R(1)] out ulong 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);
}
@ -345,9 +345,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return _syscall.GetCurrentProcessorNumber();
}
public KernelResult GetThreadId64([R(1)] int handle, [R(1)] out long threadUid)
public KernelResult GetThreadId64([R(1)] int handle, [R(1)] out ulong 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)

View File

@ -433,7 +433,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
generator.Emit(OpCodes.Ret);
return (Action<T, ExecutionContext>)method.CreateDelegate(typeof(Action<T, ExecutionContext>));
return method.CreateDelegate<Action<T, ExecutionContext>>();
}
private static void CheckIfTypeIsSupported(Type type, string svcName)

View File

@ -0,0 +1,22 @@
using ARMeilleure.State;
using Ryujinx.Common.Memory;
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{
struct ThreadContext
{
public Array29<ulong> 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<V128> FpuRegisters;
public uint Fpcr;
public uint Fpsr;
public ulong Tpidr;
}
}

View File

@ -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();

View File

@ -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,9 +28,9 @@ 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; }
public ulong ThreadUid { get; private set; }
private long _totalTimeRunning;
@ -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)
{

View File

@ -5,9 +5,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
{
class ILibraryAppletProxy : IpcService
{
private readonly long _pid;
private readonly ulong _pid;
public ILibraryAppletProxy(long pid)
public ILibraryAppletProxy(ulong pid)
{
_pid = pid;
}

View File

@ -4,9 +4,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
{
class ISystemAppletProxy : IpcService
{
private readonly long _pid;
private readonly ulong _pid;
public ISystemAppletProxy(long pid)
public ISystemAppletProxy(ulong pid)
{
_pid = pid;
}

View File

@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
{
class ISelfController : IpcService
{
private readonly long _pid;
private readonly ulong _pid;
private KEvent _libraryAppletLaunchableEvent;
private int _libraryAppletLaunchableEventHandle;
@ -35,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
private uint _screenShotImageOrientation = 0;
private uint _idleTimeDetectionExtension = 0;
public ISelfController(ServiceCtx context, long pid)
public ISelfController(ServiceCtx context, ulong pid)
{
_libraryAppletLaunchableEvent = new KEvent(context.Device.System.KernelContext);
_pid = pid;

View File

@ -4,9 +4,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
{
class IWindowController : IpcService
{
private readonly long _pid;
private readonly ulong _pid;
public IWindowController(long pid)
public IWindowController(ulong pid)
{
_pid = pid;
}

View File

@ -5,9 +5,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
{
class IApplicationProxy : IpcService
{
private readonly long _pid;
private readonly ulong _pid;
public IApplicationProxy(long pid)
public IApplicationProxy(ulong pid)
{
_pid = pid;
}

View File

@ -318,7 +318,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
// Pid placeholder
context.RequestData.ReadInt64();
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
ulong playHistoryRegistrationKeyPosition = context.Request.PtrBuff[0].Position;
ulong PlayHistoryRegistrationKeySize = context.Request.PtrBuff[0].Size;

View File

@ -1021,7 +1021,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
HidVibrationDeviceType vibrationDeviceType = HidVibrationDeviceType.None;
if (Enum.IsDefined(typeof(NpadStyleIndex), deviceType))
if (Enum.IsDefined<NpadStyleIndex>(deviceType))
{
vibrationDeviceType = HidVibrationDeviceType.LinearResonantActuator;
}

View File

@ -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);

View File

@ -44,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// CountAddOnContent(pid) -> u32
public ResultCode CountAddOnContent(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -55,7 +55,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// ListAddOnContent(u32 start_index, u32 buffer_size, pid) -> (u32 count, buffer<u32>)
public ResultCode ListAddOnContent(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -75,7 +75,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// GetAddOnContentBaseId(pid) -> u64
public ResultCode GetAddOnContentBaseId(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -95,7 +95,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// PrepareAddOnContent(u32 index, pid)
public ResultCode PrepareAddOnContent(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -123,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// GetAddOnContentListChangedEventWithProcessId(pid) -> handle<copy>
public ResultCode GetAddOnContentListChangedEventWithProcessId(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -142,7 +142,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// NotifyMountAddOnContent(pid, u64 title_id)
public ResultCode NotifyMountAddOnContent(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -160,7 +160,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// NotifyUnmountAddOnContent(pid, u64 title_id)
public ResultCode NotifyUnmountAddOnContent(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
@ -175,7 +175,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
// CheckAddOnContentMountStatus(pid)
public ResultCode CheckAddOnContentMountStatus(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
// NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
// Then it does some internal checks and returns InvalidBufferSize if they fail.

View File

@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
public NvMemoryAllocator MemoryAllocator { get; }
public Host1xDevice Host1x { get;}
public Host1xContext(GpuContext gpu, long pid)
public Host1xContext(GpuContext gpu, ulong pid)
{
MemoryAllocator = new NvMemoryAllocator();
Host1x = new Host1xDevice(gpu.Synchronization);

View File

@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
public static IdDictionary DeviceFileIdRegistry = new IdDictionary();
private IVirtualMemoryManager _clientMemory;
private long _owner;
private ulong _owner;
private bool _transferMemInitialized = false;
@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
{
if (_deviceFileRegistry.TryGetValue(path, out Type deviceFileClass))
{
ConstructorInfo constructor = deviceFileClass.GetConstructor(new Type[] { typeof(ServiceCtx), typeof(IVirtualMemoryManager), typeof(long) });
ConstructorInfo constructor = deviceFileClass.GetConstructor(new Type[] { typeof(ServiceCtx), typeof(IVirtualMemoryManager), typeof(ulong) });
NvDeviceFile deviceFile = (NvDeviceFile)constructor.Invoke(new object[] { context, _clientMemory, _owner });
@ -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);

View File

@ -11,11 +11,11 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
abstract class NvDeviceFile
{
public readonly ServiceCtx Context;
public readonly long Owner;
public readonly ulong Owner;
public string Path;
public NvDeviceFile(ServiceCtx context, long owner)
public NvDeviceFile(ServiceCtx context, ulong owner)
{
Context = context;
Owner = owner;

View File

@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
private readonly AddressSpaceContext _asContext;
private readonly NvMemoryAllocator _memoryAllocator;
public NvHostAsGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner)
public NvHostAsGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{
_asContext = new AddressSpaceContext(context.Device.Gpu.CreateMemoryManager(owner));
_memoryAllocator = new NvMemoryAllocator();

View File

@ -15,7 +15,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
{
class NvHostChannelDeviceFile : NvDeviceFile
{
private static readonly ConcurrentDictionary<long, Host1xContext> _host1xContextRegistry = new();
private static readonly ConcurrentDictionary<ulong, Host1xContext> _host1xContextRegistry = new();
private const uint MaxModuleSyncpoint = 16;
@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
private NvFence _channelSyncpoint;
public NvHostChannelDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner)
public NvHostChannelDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{
_device = context.Device;
_memory = memory;
@ -556,9 +556,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
_channelSyncpoint.Id = 0;
}
private static Host1xContext GetHost1XContext(GpuContext gpu, long pid)
private static Host1xContext GetHost1XContext(GpuContext gpu, ulong pid)
{
return _host1xContextRegistry.GetOrAdd(pid, (long key) => new Host1xContext(gpu, key));
return _host1xContextRegistry.GetOrAdd(pid, (ulong key) => new Host1xContext(gpu, key));
}
public static void Destroy()

View File

@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
private int _smExceptionBptPauseReportEventHandle;
private int _errorNotifierEventHandle;
public NvHostGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, memory, owner)
public NvHostGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, memory, owner)
{
_smExceptionBptIntReportEvent = CreateEvent(context, out _smExceptionBptIntReportEventHandle);
_smExceptionBptPauseReportEvent = CreateEvent(context, out _smExceptionBptPauseReportEventHandle);

View File

@ -20,7 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
private Switch _device;
private NvHostEvent[] _events;
public NvHostCtrlDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner)
public NvHostCtrlDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{
if (NxSettings.Settings.TryGetValue("nv!rmos_set_production_mode", out object productionModeSetting))
{

View File

@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu
private KEvent _errorEvent;
private KEvent _unknownEvent;
public NvHostCtrlGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner)
public NvHostCtrlGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{
_errorEvent = new KEvent(context.Device.System.KernelContext);
_unknownEvent = new KEvent(context.Device.System.KernelContext);

View File

@ -11,9 +11,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
{
private const int FlagNotFreedYet = 1;
private static ConcurrentDictionary<long, IdDictionary> _maps = new ConcurrentDictionary<long, IdDictionary>();
private static ConcurrentDictionary<ulong, IdDictionary> _maps = new ConcurrentDictionary<ulong, IdDictionary>();
public NvMapDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner)
public NvMapDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{
IdDictionary dict = _maps.GetOrAdd(Owner, (key) => new IdDictionary());
@ -237,7 +237,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
return dict.Add(map);
}
private static bool DeleteMapWithHandle(long pid, int handle)
private static bool DeleteMapWithHandle(ulong pid, int handle)
{
if (_maps.TryGetValue(pid, out IdDictionary dict))
{
@ -247,12 +247,12 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
return false;
}
public static void IncrementMapRefCount(long pid, int handle)
public static void IncrementMapRefCount(ulong pid, int handle)
{
GetMapFromHandle(pid, handle)?.IncrementRefCount();
}
public static bool DecrementMapRefCount(long pid, int handle)
public static bool DecrementMapRefCount(ulong pid, int handle)
{
NvMapHandle map = GetMapFromHandle(pid, handle);
@ -275,7 +275,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
}
}
public static NvMapHandle GetMapFromHandle(long pid, int handle)
public static NvMapHandle GetMapFromHandle(ulong pid, int handle)
{
if (_maps.TryGetValue(pid, out IdDictionary dict))
{

View File

@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl
// CreateService(u64, pid) -> object<nn::pctl::detail::ipc::IParentalControlService>
public ResultCode CreateService(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
MakeObject(context, new IParentalControlService(context, pid, true, _permissionFlag));
@ -30,7 +30,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl
// CreateServiceWithoutInitialize(u64, pid) -> object<nn::pctl::detail::ipc::IParentalControlService>
public ResultCode CreateServiceWithoutInitialize(ServiceCtx context)
{
long pid = context.Request.HandleDesc.PId;
ulong pid = context.Request.HandleDesc.PId;
MakeObject(context, new IParentalControlService(context, pid, false, _permissionFlag));

View File

@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
{
class IParentalControlService : IpcService
{
private long _pid;
private ulong _pid;
private int _permissionFlag;
private ulong _titleId;
private ParentalControlFlagValue _parentalControlFlag;
@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
private bool _stereoVisionRestrictionConfigurable = true;
private bool _stereoVisionRestriction = false;
public IParentalControlService(ServiceCtx context, long pid, bool withInitialize, int permissionFlag)
public IParentalControlService(ServiceCtx context, ulong pid, bool withInitialize, int permissionFlag)
{
_pid = pid;
_permissionFlag = permissionFlag;

View File

@ -11,7 +11,7 @@
{
// FIXME: This is wrong but needed to make hb loader works
// TODO: Change this when we will have a way to process via a PM like interface.
long pid = context.Process.Pid;
ulong pid = context.Process.Pid;
context.ResponseData.Write(pid);

View File

@ -418,7 +418,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
return (ResultCode)result;
}
private ResultCode IsInitialized(long pid)
private ResultCode IsInitialized(ulong pid)
{
if (_owner != null && _owner.Pid == pid)
{

View File

@ -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]);

View File

@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
{
class BsdContext
{
private static ConcurrentDictionary<long, BsdContext> _registry = new ConcurrentDictionary<long, BsdContext>();
private static ConcurrentDictionary<ulong, BsdContext> _registry = new ConcurrentDictionary<ulong, BsdContext>();
private readonly object _lock = new object();
@ -123,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
return LinuxError.SUCCESS;
}
public static BsdContext GetOrRegister(long processId)
public static BsdContext GetOrRegister(ulong processId)
{
BsdContext context = GetContext(processId);
@ -137,7 +137,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
return context;
}
public static BsdContext GetContext(long processId)
public static BsdContext GetContext(ulong processId)
{
if (!_registry.TryGetValue(processId, out BsdContext processContext))
{

View File

@ -23,11 +23,11 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService
private ISslConnectionBase _connection;
private BsdContext _bsdContext;
private readonly long _processId;
private readonly ulong _processId;
private byte[] _nextAplnProto;
public ISslConnection(long processId, SslVersion sslVersion)
public ISslConnection(ulong processId, SslVersion sslVersion)
{
_processId = processId;
_sslVersion = sslVersion;

View File

@ -1,5 +1,4 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Sockets.Bsd;
using Ryujinx.HLE.HOS.Services.Ssl.Types;
using System.Text;
@ -9,12 +8,12 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService
{
private uint _connectionCount;
private readonly long _processId;
private readonly ulong _processId;
private readonly SslVersion _sslVersion;
private ulong _serverCertificateId;
private ulong _clientCertificateId;
public ISslContext(long processId, SslVersion sslVersion)
public ISslContext(ulong processId, SslVersion sslVersion)
{
_processId = processId;
_sslVersion = sslVersion;

View File

@ -2,7 +2,7 @@
{
static class BufferQueue
{
public static BufferQueueCore CreateBufferQueue(Switch device, long pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer)
public static BufferQueueCore CreateBufferQueue(Switch device, ulong pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer)
{
BufferQueueCore core = new BufferQueueCore(device, pid);

View File

@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private KEvent _waitBufferFreeEvent;
private KEvent _frameAvailableEvent;
public long Owner { get; }
public ulong Owner { get; }
public bool Active { get; private set; }
@ -48,7 +48,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public event Action BufferQueued;
public BufferQueueCore(Switch device, long pid)
public BufferQueueCore(Switch device, ulong pid)
{
Slots = new BufferSlotArray();
IsAbandoned = false;

View File

@ -44,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public IGraphicBufferProducer Producer;
public BufferItemConsumer Consumer;
public BufferQueueCore Core;
public long Owner;
public ulong Owner;
}
private class TextureCallbackInformation
@ -92,7 +92,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
}
}
public IGraphicBufferProducer OpenLayer(long pid, long layerId)
public IGraphicBufferProducer OpenLayer(ulong pid, long layerId)
{
bool needCreate;
@ -109,7 +109,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return GetProducerByLayerId(layerId);
}
public IGraphicBufferProducer CreateLayer(long pid, out long layerId)
public IGraphicBufferProducer CreateLayer(ulong pid, out long layerId)
{
layerId = 1;
@ -129,7 +129,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return GetProducerByLayerId(layerId);
}
private void CreateLayerFromId(long pid, long layerId)
private void CreateLayerFromId(ulong pid, long layerId)
{
lock (Lock)
{

View File

@ -42,7 +42,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Buffer = parcel.ReadUnmanagedType<NvGraphicBuffer>();
}
public void IncrementNvMapHandleRefCount(long pid)
public void IncrementNvMapHandleRefCount(ulong pid)
{
NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.NvMapId);
@ -52,7 +52,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
}
}
public void DecrementNvMapHandleRefCount(long pid)
public void DecrementNvMapHandleRefCount(ulong pid)
{
NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.NvMapId);

View File

@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService
long displayId = context.RequestData.ReadInt64();
long appletResourceUserId = context.RequestData.ReadInt64();
long pid = context.Device.System.AppletState.AppletResourceUserIds.GetData<long>((int)appletResourceUserId);
ulong pid = context.Device.System.AppletState.AppletResourceUserIds.GetData<ulong>((int)appletResourceUserId);
context.Device.System.SurfaceFlinger.CreateLayer(pid, out long layerId);
context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);

View File

@ -60,7 +60,7 @@ namespace Ryujinx.HLE.HOS.SystemState
SystemLanguage.TraditionalChinese => TitleLanguage.Taiwanese,
SystemLanguage.Chinese or
SystemLanguage.SimplifiedChinese => TitleLanguage.Chinese,
_ => Enum.Parse<TitleLanguage>(Enum.GetName(typeof(SystemLanguage), language)),
_ => Enum.Parse<TitleLanguage>(Enum.GetName<SystemLanguage>(language)),
};
}

View File

@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS
Activate();
}
private bool CanInstallOnPid(long pid)
private bool CanInstallOnPid(ulong pid)
{
// Do not allow tampering of kernel processes.
if (pid < KernelConstants.InitialProcessId)

View File

@ -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.")]

View File

@ -391,24 +391,29 @@ namespace Ryujinx.Input.HLE
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static JoystickPosition ApplyDeadzone(float x, float y, float deadzone)
{
return new JoystickPosition
float magnitudeClamped = Math.Min(MathF.Sqrt(x * x + y * y), 1f);
if (magnitudeClamped <= deadzone)
{
Dx = ClampAxis(MathF.Abs(x) > deadzone ? x : 0.0f),
Dy = ClampAxis(MathF.Abs(y) > deadzone ? y : 0.0f)
return new JoystickPosition() {Dx = 0, Dy = 0};
}
return new JoystickPosition()
{
Dx = ClampAxis((x / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone))),
Dy = ClampAxis((y / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone)))
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static short ClampAxis(float value)
{
if (value <= -short.MaxValue)
if (Math.Sign(value) < 0)
{
return -short.MaxValue;
}
else
{
return (short)(value * short.MaxValue);
return (short)Math.Max(value * -short.MinValue, short.MinValue);
}
return (short)Math.Min(value * short.MaxValue, short.MaxValue);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@ -27,8 +27,8 @@ namespace Ryujinx.Input.Motion.CemuHook
private readonly Dictionary<int, Dictionary<int, MotionInput>> _motionData;
private readonly Dictionary<int, UdpClient> _clients;
private readonly bool[] _clientErrorStatus = new bool[Enum.GetValues(typeof(PlayerIndex)).Length];
private readonly long[] _clientRetryTimer = new long[Enum.GetValues(typeof(PlayerIndex)).Length];
private readonly bool[] _clientErrorStatus = new bool[Enum.GetValues<PlayerIndex>().Length];
private readonly long[] _clientRetryTimer = new long[Enum.GetValues<PlayerIndex>().Length];
private NpadManager _npadManager;
public Client(NpadManager npadManager)

View File

@ -77,6 +77,44 @@ 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 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,
@ -120,7 +158,26 @@ 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);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
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);

View File

@ -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}"

View File

@ -58,7 +58,7 @@ namespace Ryujinx.Configuration
{
bool noFilter = e.NewValue.Length == 0;
foreach (var logClass in EnumExtensions.GetValues<LogClass>())
foreach (var logClass in Enum.GetValues<LogClass>())
{
Logger.SetEnable(logClass, noFilter);
}

View File

@ -150,7 +150,7 @@ namespace Ryujinx.Input.GTK3
static GTK3MappingHelper()
{
var inputKeys = Enum.GetValues(typeof(Key));
var inputKeys = Enum.GetValues<Key>();
// GtkKey is not contiguous and quite large, so use a dictionary instead of an array.
_gtkKeyMapping = new Dictionary<GtkKey, Key>();

View File

@ -1209,7 +1209,7 @@ namespace Ryujinx.Ui
{
AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
ConfigurationState.Instance.Graphics.AspectRatio.Value = ((int)aspectRatio + 1) > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
ConfigurationState.Instance.Graphics.AspectRatio.Value = ((int)aspectRatio + 1) > Enum.GetNames<AspectRatio>().Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
}
private void Row_Clicked(object sender, ButtonReleaseEventArgs args)

View File

@ -181,7 +181,7 @@ namespace Ryujinx.Ui.Windows
_fsAccessLogToggle.Click();
}
foreach (GraphicsDebugLevel level in Enum.GetValues(typeof(GraphicsDebugLevel)))
foreach (GraphicsDebugLevel level in Enum.GetValues<GraphicsDebugLevel>())
{
_graphicsDebugLevel.Append(level.ToString(), level.ToString());
}

View File

@ -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