Compare commits

..

16 Commits

Author SHA1 Message Date
Marco Carvalho
32d21ddf17 Inheritance list should not be redundant (#5230) 2023-06-15 03:54:27 +00:00
Marco Carvalho
82f90704a0 Blocks should be synchronized on read-only fields (#5212)
* Blocks should be synchronized on read-only fields

* more readonlys

* fix alignment

* more

* Update ISelfController.cs

* simplify new

* simplify new
2023-06-15 00:34:55 +00:00
dependabot[bot]
f978d3726a nuget: bump System.Management from 7.0.1 to 7.0.2 (#5302)
Bumps [System.Management](https://github.com/dotnet/runtime) from 7.0.1 to 7.0.2.
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v7.0.1...v7.0.2)

---
updated-dependencies:
- dependency-name: System.Management
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-14 18:21:17 +02:00
Mary
6f28c4abad test: Make tests runnable on system without 4KiB page size (#5184)
* ARMeilleure: Do not hardcode 4KiB page size in JitCache

* test: Do not hardcode page size to 4KiB for Ryujinx.Tests.Memory.Tests

Fix running tests on Asahi Linux with 16KiB pages.

* test: Do not hardcode page size to 4KiB for Ryujinx.Tests.Cpu

Fix running tests on Asahi Linux.

Test runner still crash when trying to run all test suite.

* test: Do not hardcode page size to 4KiB for Ryujinx.Tests.Cpu

Fix somecrashes on Asahi Linux.

* test: Ignore Vshl test on ARM64 due to unicorn crashes

* test: Workaround hardcoded size on some tests

Change mapping of code and data in case of non 4KiB configuration.

* test: Make CpuTestT32Flow depends on code address

Fix failure with different page size.

* test: Disable CpuTestThumb.TestRandomTestCases when page size isn't 4KiB

The test data needs to be reevaluated to take different page size into account.

* Address gdkchan's comments
2023-06-14 18:02:41 +02:00
gdkchan
105c9712c1 Fix Arm32 double to int/uint conversion on Arm64 (#5292)
* Fix Arm32 double to int/uint conversion on Arm64

* PPTC version bump
2023-06-14 00:57:02 -03:00
Kurochi51
4d804ed45e Mod Loader: Stop loading mods from folders that don't exactly match titleId (#5298)
* Stop loading mods from folders that don't exactly match titleId

* What the worst that can happen?
2023-06-13 20:47:33 +02:00
Mary
4a27d29412 infra: Sync paths-ignore with release job and attempt to fix review assign 2023-06-13 11:51:22 +02:00
mmdurrant
5bd2c58ad6 UI: Correctly set 'shell/open/command; registry key for file associations (#5244)
* Correctly set 'shell/open/command; registry key for file associations

* File association fixes
* 'using' statements instead of blocks
* Idempotent unregistration
* Single "hey shell, we changed file associations" notification at the
  end instead of 1 for every operation, speeds things up greatly.

* Adapt and fix Linux specific function as well

---------

Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
2023-06-13 00:36:40 +00:00
gdkchan
cf4c78b9c8 Make LM skip instead of crashing for invalid messages (#5290) 2023-06-13 00:12:06 +00:00
TSRBerry
52aa4b6c22 Fix action version (#5299) 2023-06-12 21:57:07 +02:00
TSRBerry
5a02433080 infra: Fix PR triage workflow glob patterns (#5297)
* Use glob patterns to match file paths

* Update ignored paths for releases

* Adjust build.yml as well

* Add names to auto-assign steps

* Fix developer team name

* Allow build workflows to run if workflows changed
2023-06-12 18:42:27 +00:00
Steveice10
915a0f7173 hle: Stub IHidbusServer.GetBusHandle (#5284) 2023-06-12 17:33:13 +02:00
Mary
0cc266ff19 infra: Add PR triage action (#5293)
This is a bare minimal triage action that handle big categories.

In the future we could also label all services correctly but
I didn't felt this was required for a first iteration.
2023-06-12 12:29:41 +02:00
TSRBerry
9a1b74799d Ava: Fix OpenGL on Linux again (#5216)
* ava: Fix OpenGL on Linux again

This shouldn't be working like that, but for some reason it does.

* Apply the correct fix

* gtk: Add warning messages for caught exceptions

* ava: Handle disposing the same way as GTK does

* Address review feedback
2023-06-11 18:31:22 +02:00
Patrick Hovsepian
638f3761f3 Show/Hide UI Hotkey fix on Avalonia (#5133)
* fix show/hide ui for ava

* revert style

* unbound by default

* revert
2023-06-11 15:34:56 +02:00
gdkchan
193ca3c9a2 Implement fast path for AES crypto instructions on Arm64 (#5281)
* Implement fast path for AES crypto instructions on Arm64

* PPTC version bump

* Use AES HW feature check
2023-06-11 00:51:35 +00:00
106 changed files with 634 additions and 239 deletions

8
.github/assign/audio.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
addReviewers: true
reviewers:
- marysaka
filterLabels:
include:
- audio

11
.github/assign/cpu.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
addReviewers: true
reviewers:
- gdkchan
- riperiperi
- marysaka
- LDj3SNuD
filterLabels:
include:
- cpu

4
.github/assign/global.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
addReviewers: true
reviewers:
- Ryujinx/developers

10
.github/assign/gpu.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
addReviewers: true
reviewers:
- gdkchan
- riperiperi
- marysaka
filterLabels:
include:
- gpu

11
.github/assign/gui.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
addReviewers: true
reviewers:
- Ack77
- emmauss
- TSRBerry
- marysaka
filterLabels:
include:
- gui

11
.github/assign/horizon.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
addReviewers: true
reviewers:
- gdkchan
- Ack77
- marysaka
- TSRBerry
filterLabels:
include:
- horizon

9
.github/assign/infra.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
addReviewers: true
reviewers:
- marysaka
- TSRBerry
filterLabels:
include:
- infra

33
.github/labeler.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
audio: 'src/Ryujinx.Audio*/**'
cpu:
- 'src/ARMeilleure/**'
- 'src/Ryujinx.Cpu/**'
- 'src/Ryujinx.Memory/**'
gpu:
- 'src/Ryujinx.Graphics.*/**'
- 'src/Spv.Generator/**'
- 'src/Ryujinx.ShaderTools/**'
'graphics-backend:opengl': 'src/Ryujinx.Graphics.OpenGL/**'
'graphics-backend:vulkan':
- 'src/Ryujinx.Graphics.Vulkan/**'
- 'src/Spv.Generator/**'
gui:
- 'src/Ryujinx/**'
- 'src/Ryujinx.Ui.Common/**'
- 'src/Ryujinx.Ui.LocaleGenerator/**'
- 'src/Ryujinx.Ava/**'
horizon:
- 'src/Ryujinx.HLE/**'
- 'src/Ryujinx.Horizon*/**'
kernel: 'src/Ryujinx.HLE/HOS/Kernel/**'
infra:
- '.github/**'
- 'distribution/**'
- 'Directory.Packages.props'

View File

@@ -3,19 +3,13 @@ name: Build job
on: on:
workflow_dispatch: workflow_dispatch:
inputs: {} inputs: {}
#push:
# branches: [ master ]
# paths-ignore:
# - '.github/*'
# - '.github/ISSUE_TEMPLATE/**'
# - '*.yml'
# - 'README.md'
pull_request: pull_request:
branches: [ master ] branches: [ master ]
paths-ignore: paths-ignore:
- '.github/*' - '.github/**'
- '.github/ISSUE_TEMPLATE/**'
- '*.yml' - '*.yml'
- '*.json'
- '*.config'
- 'README.md' - 'README.md'
concurrency: concurrency:

54
.github/workflows/pr_triage.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: "Pull Request Triage"
on:
pull_request_target:
types: [opened, ready_for_review]
jobs:
triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Update labels based on changes
uses: actions/labeler@v4
with:
sync-labels: true
dot: true
- name: Auto Assign [Audio]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/audio.yml'
- name: Auto Assign [CPU]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/cpu.yml'
- name: Auto Assign [GPU]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/gpu.yml'
- name: Auto Assign [GUI]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/gui.yml'
- name: Auto Assign [Horizon]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/horizon.yml'
- name: Auto Assign [Infra]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/infra.yml'
- name: Auto Assign [Global]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/global.yml'

View File

@@ -6,9 +6,10 @@ on:
push: push:
branches: [ master ] branches: [ master ]
paths-ignore: paths-ignore:
- '.github/*' - '.github/**'
- '.github/ISSUE_TEMPLATE/**'
- '*.yml' - '*.yml'
- '*.json'
- '*.config'
- 'README.md' - 'README.md'
concurrency: release concurrency: release

View File

@@ -46,7 +46,7 @@
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" /> <PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.31.0" /> <PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.31.0" />
<PackageVersion Include="System.IO.Hashing" Version="7.0.0" /> <PackageVersion Include="System.IO.Hashing" Version="7.0.0" />
<PackageVersion Include="System.Management" Version="7.0.1" /> <PackageVersion Include="System.Management" Version="7.0.2" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.6.1" /> <PackageVersion Include="XamlNameReferenceGenerator" Version="1.6.1" />
</ItemGroup> </ItemGroup>

View File

@@ -168,8 +168,6 @@ namespace ARMeilleure.CodeGen.Arm64
Logger.StartPass(PassName.CodeGeneration); Logger.StartPass(PassName.CodeGeneration);
//Console.Error.WriteLine(IRDumper.GetDump(cfg));
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0; bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0;
CodeGenContext context = new(allocResult, maxCallArgs, cfg.Blocks.Count, relocatable); CodeGenContext context = new(allocResult, maxCallArgs, cfg.Blocks.Count, relocatable);

View File

@@ -179,6 +179,35 @@ namespace ARMeilleure.CodeGen.Arm64
(uint)operation.GetSource(2).AsInt32()); (uint)operation.GetSource(2).AsInt32());
break; break;
case IntrinsicType.Vector128Unary:
GenerateVectorUnary(
context,
1,
0,
info.Inst,
operation.Destination,
operation.GetSource(0));
break;
case IntrinsicType.Vector128Binary:
GenerateVectorBinary(
context,
1,
0,
info.Inst,
operation.Destination,
operation.GetSource(0),
operation.GetSource(1));
break;
case IntrinsicType.Vector128BinaryRd:
GenerateVectorUnary(
context,
1,
0,
info.Inst,
operation.Destination,
operation.GetSource(1));
break;
case IntrinsicType.VectorUnary: case IntrinsicType.VectorUnary:
GenerateVectorUnary( GenerateVectorUnary(
context, context,

View File

@@ -19,8 +19,8 @@ namespace ARMeilleure.CodeGen.Arm64
Add(Intrinsic.Arm64AddvV, new IntrinsicInfo(0x0e31b800u, IntrinsicType.VectorUnary)); Add(Intrinsic.Arm64AddvV, new IntrinsicInfo(0x0e31b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64AddS, new IntrinsicInfo(0x5e208400u, IntrinsicType.ScalarBinary)); Add(Intrinsic.Arm64AddS, new IntrinsicInfo(0x5e208400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64AddV, new IntrinsicInfo(0x0e208400u, IntrinsicType.VectorBinary)); Add(Intrinsic.Arm64AddV, new IntrinsicInfo(0x0e208400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128Unary)); Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128BinaryRd));
Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128Unary)); Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128BinaryRd));
Add(Intrinsic.Arm64AesimcV, new IntrinsicInfo(0x4e287800u, IntrinsicType.Vector128Unary)); Add(Intrinsic.Arm64AesimcV, new IntrinsicInfo(0x4e287800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64AesmcV, new IntrinsicInfo(0x4e286800u, IntrinsicType.Vector128Unary)); Add(Intrinsic.Arm64AesmcV, new IntrinsicInfo(0x4e286800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64AndV, new IntrinsicInfo(0x0e201c00u, IntrinsicType.VectorBinaryBitwise)); Add(Intrinsic.Arm64AndV, new IntrinsicInfo(0x0e201c00u, IntrinsicType.VectorBinaryBitwise));

View File

@@ -23,6 +23,10 @@ namespace ARMeilleure.CodeGen.Arm64
ScalarTernaryShlRd, ScalarTernaryShlRd,
ScalarTernaryShrRd, ScalarTernaryShrRd,
Vector128Unary,
Vector128Binary,
Vector128BinaryRd,
VectorUnary, VectorUnary,
VectorUnaryBitwise, VectorUnaryBitwise,
VectorUnaryByElem, VectorUnaryByElem,
@@ -50,9 +54,6 @@ namespace ARMeilleure.CodeGen.Arm64
VectorTernaryShlRd, VectorTernaryShlRd,
VectorTernaryShrRd, VectorTernaryShrRd,
Vector128Unary,
Vector128Binary,
GetRegister, GetRegister,
SetRegister SetRegister
} }

View File

@@ -746,6 +746,7 @@ namespace ARMeilleure.CodeGen.Arm64
info.Type == IntrinsicType.ScalarTernaryFPRdByElem || info.Type == IntrinsicType.ScalarTernaryFPRdByElem ||
info.Type == IntrinsicType.ScalarTernaryShlRd || info.Type == IntrinsicType.ScalarTernaryShlRd ||
info.Type == IntrinsicType.ScalarTernaryShrRd || info.Type == IntrinsicType.ScalarTernaryShrRd ||
info.Type == IntrinsicType.Vector128BinaryRd ||
info.Type == IntrinsicType.VectorBinaryRd || info.Type == IntrinsicType.VectorBinaryRd ||
info.Type == IntrinsicType.VectorInsertByElem || info.Type == IntrinsicType.VectorInsertByElem ||
info.Type == IntrinsicType.VectorTernaryRd || info.Type == IntrinsicType.VectorTernaryRd ||

View File

@@ -13,7 +13,7 @@
} }
} }
enum OpCode32SimdSelMode : int enum OpCode32SimdSelMode
{ {
Eq = 0, Eq = 0,
Vs, Vs,

View File

@@ -17,7 +17,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesdV, d, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero()); res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
} }
@@ -38,7 +42,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AeseV, d, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero()); res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
} }
@@ -58,7 +66,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesimcV, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesimc, n); res = context.AddIntrinsic(Intrinsic.X86Aesimc, n);
} }
@@ -78,7 +90,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesmcV, n);
}
else if (Optimizations.UseAesni)
{ {
Operand roundKey = context.VectorZero(); Operand roundKey = context.VectorZero();

View File

@@ -17,7 +17,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesdV, d, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero()); res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
} }
@@ -38,7 +42,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AeseV, d, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero()); res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
} }
@@ -58,7 +66,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesimcV, n);
}
else if (Optimizations.UseAesni)
{ {
res = context.AddIntrinsic(Intrinsic.X86Aesimc, n); res = context.AddIntrinsic(Intrinsic.X86Aesimc, n);
} }
@@ -78,7 +90,11 @@ namespace ARMeilleure.Instructions
Operand res; Operand res;
if (Optimizations.UseAesni) if (Optimizations.UseArm64Aes)
{
res = context.AddIntrinsic(Intrinsic.Arm64AesmcV, n);
}
else if (Optimizations.UseAesni)
{ {
Operand roundKey = context.VectorZero(); Operand roundKey = context.VectorZero();

View File

@@ -165,7 +165,7 @@ namespace ARMeilleure.Instructions
{ {
Operand m = GetVecA32(op.Vm >> 1); Operand m = GetVecA32(op.Vm >> 1);
Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, doubleSize); Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, true);
Intrinsic inst = (unsigned ? Intrinsic.Arm64FcvtzuGp : Intrinsic.Arm64FcvtzsGp) | Intrinsic.Arm64VDouble; Intrinsic inst = (unsigned ? Intrinsic.Arm64FcvtzuGp : Intrinsic.Arm64FcvtzsGp) | Intrinsic.Arm64VDouble;
@@ -175,7 +175,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, unsigned ? Intrinsic.Arm64FcvtzuS : Intrinsic.Arm64FcvtzsS); InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, unsigned ? Intrinsic.Arm64FcvtzuS : Intrinsic.Arm64FcvtzsS, false);
} }
} }
else if (!roundWithFpscr && Optimizations.UseSse41) else if (!roundWithFpscr && Optimizations.UseSse41)
@@ -260,28 +260,64 @@ namespace ARMeilleure.Instructions
if (Optimizations.UseAdvSimd) if (Optimizations.UseAdvSimd)
{ {
if (unsigned) bool doubleSize = floatSize == OperandType.FP64;
if (doubleSize)
{ {
inst = rm switch { Operand m = GetVecA32(op.Vm >> 1);
0b00 => Intrinsic.Arm64FcvtauS,
0b01 => Intrinsic.Arm64FcvtnuS, Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, true);
0b10 => Intrinsic.Arm64FcvtpuS,
0b11 => Intrinsic.Arm64FcvtmuS, if (unsigned)
_ => throw new ArgumentOutOfRangeException(nameof(rm)) {
}; inst = rm switch {
0b00 => Intrinsic.Arm64FcvtauGp,
0b01 => Intrinsic.Arm64FcvtnuGp,
0b10 => Intrinsic.Arm64FcvtpuGp,
0b11 => Intrinsic.Arm64FcvtmuGp,
_ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
else
{
inst = rm switch {
0b00 => Intrinsic.Arm64FcvtasGp,
0b01 => Intrinsic.Arm64FcvtnsGp,
0b10 => Intrinsic.Arm64FcvtpsGp,
0b11 => Intrinsic.Arm64FcvtmsGp,
_ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
Operand asInteger = context.AddIntrinsicInt(inst | Intrinsic.Arm64VDouble, toConvert);
InsertScalar(context, op.Vd, asInteger);
} }
else else
{ {
inst = rm switch { if (unsigned)
0b00 => Intrinsic.Arm64FcvtasS, {
0b01 => Intrinsic.Arm64FcvtnsS, inst = rm switch {
0b10 => Intrinsic.Arm64FcvtpsS, 0b00 => Intrinsic.Arm64FcvtauS,
0b11 => Intrinsic.Arm64FcvtmsS, 0b01 => Intrinsic.Arm64FcvtnuS,
_ => throw new ArgumentOutOfRangeException(nameof(rm)) 0b10 => Intrinsic.Arm64FcvtpuS,
}; 0b11 => Intrinsic.Arm64FcvtmuS,
} _ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
else
{
inst = rm switch {
0b00 => Intrinsic.Arm64FcvtasS,
0b01 => Intrinsic.Arm64FcvtnsS,
0b10 => Intrinsic.Arm64FcvtpsS,
0b11 => Intrinsic.Arm64FcvtmsS,
_ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst); InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst);
}
} }
else if (Optimizations.UseSse41) else if (Optimizations.UseSse41)
{ {

View File

@@ -192,11 +192,10 @@ namespace ARMeilleure.Instructions
EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(inst, d, n, m)); EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(inst, d, n, m));
} }
public static void EmitScalarUnaryOpSimd32(ArmEmitterContext context, Func1I scalarFunc) public static void EmitScalarUnaryOpSimd32(ArmEmitterContext context, Func1I scalarFunc, bool doubleSize)
{ {
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
bool doubleSize = (op.Size & 1) != 0;
int shift = doubleSize ? 1 : 2; int shift = doubleSize ? 1 : 2;
Operand m = GetVecA32(op.Vm >> shift); Operand m = GetVecA32(op.Vm >> shift);
Operand d = GetVecA32(op.Vd >> shift); Operand d = GetVecA32(op.Vd >> shift);
@@ -215,8 +214,13 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128; EmitScalarUnaryOpF32(context, inst, (op.Size & 1) != 0);
EmitScalarUnaryOpSimd32(context, (m) => (inst == 0) ? m : context.AddIntrinsic(inst, m)); }
public static void EmitScalarUnaryOpF32(ArmEmitterContext context, Intrinsic inst, bool doubleSize)
{
inst |= (doubleSize ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
EmitScalarUnaryOpSimd32(context, (m) => (inst == 0) ? m : context.AddIntrinsic(inst, m), doubleSize);
} }
public static void EmitScalarBinaryOpSimd32(ArmEmitterContext context, Func2I scalarFunc) public static void EmitScalarBinaryOpSimd32(ArmEmitterContext context, Func2I scalarFunc)

View File

@@ -13,6 +13,7 @@ namespace ARMeilleure
public static bool UseUnmanagedDispatchLoop { get; set; } = true; public static bool UseUnmanagedDispatchLoop { get; set; } = true;
public static bool UseAdvSimdIfAvailable { get; set; } = true; public static bool UseAdvSimdIfAvailable { get; set; } = true;
public static bool UseArm64AesIfAvailable { get; set; } = true;
public static bool UseArm64PmullIfAvailable { get; set; } = true; public static bool UseArm64PmullIfAvailable { get; set; } = true;
public static bool UseSseIfAvailable { get; set; } = true; public static bool UseSseIfAvailable { get; set; } = true;
@@ -41,6 +42,7 @@ namespace ARMeilleure
} }
internal static bool UseAdvSimd => UseAdvSimdIfAvailable && Arm64HardwareCapabilities.SupportsAdvSimd; internal static bool UseAdvSimd => UseAdvSimdIfAvailable && Arm64HardwareCapabilities.SupportsAdvSimd;
internal static bool UseArm64Aes => UseArm64AesIfAvailable && Arm64HardwareCapabilities.SupportsAes;
internal static bool UseArm64Pmull => UseArm64PmullIfAvailable && Arm64HardwareCapabilities.SupportsPmull; internal static bool UseArm64Pmull => UseArm64PmullIfAvailable && Arm64HardwareCapabilities.SupportsPmull;
internal static bool UseSse => UseSseIfAvailable && X86HardwareCapabilities.SupportsSse; internal static bool UseSse => UseSseIfAvailable && X86HardwareCapabilities.SupportsSse;

View File

@@ -78,7 +78,7 @@ namespace ARMeilleure.Signal
private static IntPtr _signalHandlerPtr; private static IntPtr _signalHandlerPtr;
private static IntPtr _signalHandlerHandle; private static IntPtr _signalHandlerHandle;
private static readonly object _lock = new object(); private static readonly object _lock = new();
private static bool _initialized; private static bool _initialized;
static NativeSignalHandler() static NativeSignalHandler()

View File

@@ -1,6 +1,6 @@
namespace ARMeilleure.State namespace ARMeilleure.State
{ {
enum ExecutionMode : int enum ExecutionMode
{ {
Aarch32Arm = 0, Aarch32Arm = 0,
Aarch32Thumb = 1, Aarch32Thumb = 1,

View File

@@ -2,6 +2,7 @@ using ARMeilleure.CodeGen;
using ARMeilleure.CodeGen.Unwinding; using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.Native; using ARMeilleure.Native;
using Ryujinx.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@@ -12,8 +13,8 @@ namespace ARMeilleure.Translation.Cache
{ {
static partial class JitCache static partial class JitCache
{ {
private const int PageSize = 4 * 1024; private static readonly int PageSize = (int)MemoryBlock.GetPageSize();
private const int PageMask = PageSize - 1; private static readonly int PageMask = PageSize - 1;
private const int CodeAlignment = 4; // Bytes. private const int CodeAlignment = 4; // Bytes.
private const int CacheSize = 2047 * 1024 * 1024; private const int CacheSize = 2047 * 1024 * 1024;
@@ -25,7 +26,7 @@ namespace ARMeilleure.Translation.Cache
private static readonly List<CacheEntry> _cacheEntries = new List<CacheEntry>(); private static readonly List<CacheEntry> _cacheEntries = new List<CacheEntry>();
private static readonly object _lock = new object(); private static readonly object _lock = new();
private static bool _initialized; private static bool _initialized;
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]

View File

@@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 4661; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 5292; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";

View File

@@ -17,7 +17,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
private Queue<OpenALAudioBuffer> _queuedBuffers; private Queue<OpenALAudioBuffer> _queuedBuffers;
private ulong _playedSampleCount; private ulong _playedSampleCount;
private object _lock = new object(); private readonly object _lock = new();
public OpenALHardwareDeviceSession(OpenALHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, float requestedVolume) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount) public OpenALHardwareDeviceSession(OpenALHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, float requestedVolume) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
{ {

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Audio.Backends.SoundIo.Native namespace Ryujinx.Audio.Backends.SoundIo.Native
{ {
public enum SoundIoBackend : int public enum SoundIoBackend
{ {
None = 0, None = 0,
Jack = 1, Jack = 1,

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Audio
/// <summary> /// <summary>
/// Lock used to control the waiters registration. /// Lock used to control the waiters registration.
/// </summary> /// </summary>
private object _lock = new object(); private readonly object _lock = new();
/// <summary> /// <summary>
/// Events signaled when the driver played audio buffers. /// Events signaled when the driver played audio buffers.

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Audio.Backends.Common
{ {
private const int RingBufferAlignment = 2048; private const int RingBufferAlignment = 2048;
private object _lock = new object(); private readonly object _lock = new();
private byte[] _buffer; private byte[] _buffer;
private int _size; private int _size;

View File

@@ -14,12 +14,12 @@ namespace Ryujinx.Audio.Input
/// </summary> /// </summary>
public class AudioInputManager : IDisposable public class AudioInputManager : IDisposable
{ {
private object _lock = new object(); private readonly object _lock = new();
/// <summary> /// <summary>
/// Lock used for session allocation. /// Lock used for session allocation.
/// </summary> /// </summary>
private object _sessionLock = new object(); private readonly object _sessionLock = new();
/// <summary> /// <summary>
/// The session ids allocation table. /// The session ids allocation table.

View File

@@ -48,7 +48,7 @@ namespace Ryujinx.Audio.Input
/// <summary> /// <summary>
/// The lock of the parent. /// The lock of the parent.
/// </summary> /// </summary>
private object _parentLock; private readonly object _parentLock;
/// <summary> /// <summary>
/// The dispose state. /// The dispose state.

View File

@@ -14,12 +14,12 @@ namespace Ryujinx.Audio.Output
/// </summary> /// </summary>
public class AudioOutputManager : IDisposable public class AudioOutputManager : IDisposable
{ {
private object _lock = new object(); private readonly object _lock = new();
/// <summary> /// <summary>
/// Lock used for session allocation. /// Lock used for session allocation.
/// </summary> /// </summary>
private object _sessionLock = new object(); private readonly object _sessionLock = new();
/// <summary> /// <summary>
/// The session ids allocation table. /// The session ids allocation table.

View File

@@ -48,7 +48,7 @@ namespace Ryujinx.Audio.Output
/// <summary> /// <summary>
/// THe lock of the parent. /// THe lock of the parent.
/// </summary> /// </summary>
private object _parentLock; private readonly object _parentLock;
/// <summary> /// <summary>
/// The dispose state. /// The dispose state.

View File

@@ -26,7 +26,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
public class AudioRenderSystem : IDisposable public class AudioRenderSystem : IDisposable
{ {
private object _lock = new object(); private readonly object _lock = new();
private AudioRendererRenderingDevice _renderingDevice; private AudioRendererRenderingDevice _renderingDevice;
private AudioRendererExecutionMode _executionMode; private AudioRendererExecutionMode _executionMode;

View File

@@ -19,12 +19,12 @@ namespace Ryujinx.Audio.Renderer.Server
/// <summary> /// <summary>
/// Lock used for session allocation. /// Lock used for session allocation.
/// </summary> /// </summary>
private object _sessionLock = new object(); private readonly object _sessionLock = new();
/// <summary> /// <summary>
/// Lock used to control the <see cref="AudioProcessor"/> running state. /// Lock used to control the <see cref="AudioProcessor"/> running state.
/// </summary> /// </summary>
private object _audioProcessorLock = new object(); private readonly object _audioProcessorLock = new();
/// <summary> /// <summary>
/// The session ids allocation table. /// The session ids allocation table.

View File

@@ -16,7 +16,7 @@ namespace Ryujinx.Audio.Renderer.Server.Upsampler
/// <summary> /// <summary>
/// Global lock of the object. /// Global lock of the object.
/// </summary> /// </summary>
private object Lock = new object(); private readonly object Lock = new();
/// <summary> /// <summary>
/// The upsamplers instances. /// The upsamplers instances.

View File

@@ -40,6 +40,7 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using SPB.Graphics.Exceptions;
using SPB.Graphics.Vulkan; using SPB.Graphics.Vulkan;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -475,11 +476,20 @@ namespace Ryujinx.Ava
_windowsMultimediaTimerResolution = null; _windowsMultimediaTimerResolution = null;
} }
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(); if (_rendererHost.EmbeddedWindow is EmbeddedWindowOpenGL openGlWindow)
{
// Try to bind the OpenGL context before calling the shutdown event.
openGlWindow.MakeCurrent(false, false);
Device.DisposeGpu(); Device.DisposeGpu();
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(null); // Unbind context and destroy everything.
openGlWindow.MakeCurrent(true, false);
}
else
{
Device.DisposeGpu();
}
} }
private void HideCursorState_Changed(object sender, ReactiveEventArgs<HideCursorMode> state) private void HideCursorState_Changed(object sender, ReactiveEventArgs<HideCursorMode> state)
@@ -930,7 +940,7 @@ namespace Ryujinx.Ava
_gpuDoneEvent.Set(); _gpuDoneEvent.Set();
}); });
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(null); (_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
} }
public void UpdateStatus() public void UpdateStatus()
@@ -1044,7 +1054,7 @@ namespace Ryujinx.Ava
ScreenshotRequested = true; ScreenshotRequested = true;
break; break;
case KeyboardHotkeyState.ShowUi: case KeyboardHotkeyState.ShowUi:
_viewModel.ShowMenuAndStatusBar = true; _viewModel.ShowMenuAndStatusBar = !_viewModel.ShowMenuAndStatusBar;
break; break;
case KeyboardHotkeyState.Pause: case KeyboardHotkeyState.Pause:
if (_viewModel.IsPaused) if (_viewModel.IsPaused)

View File

@@ -123,7 +123,7 @@ namespace Ryujinx.Ava.UI.Renderer
} }
else else
{ {
X11Window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100) as GLXWindow; X11Window = PlatformHelper.CreateOpenGLWindow(new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false), 0, 0, 100, 100) as GLXWindow;
} }
WindowHandle = X11Window.WindowHandle.RawHandle; WindowHandle = X11Window.WindowHandle.RawHandle;

View File

@@ -1,9 +1,11 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.OpenGL;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using SPB.Graphics; using SPB.Graphics;
using SPB.Graphics.Exceptions;
using SPB.Graphics.OpenGL; using SPB.Graphics.OpenGL;
using SPB.Platform; using SPB.Platform;
using SPB.Platform.WGL; using SPB.Platform.WGL;
@@ -18,8 +20,6 @@ namespace Ryujinx.Ava.UI.Renderer
public OpenGLContextBase Context { get; set; } public OpenGLContextBase Context { get; set; }
public EmbeddedWindowOpenGL() { }
protected override void OnWindowDestroying() protected override void OnWindowDestroying()
{ {
Context.Dispose(); Context.Dispose();
@@ -62,14 +62,21 @@ namespace Ryujinx.Ava.UI.Renderer
Context.MakeCurrent(null); Context.MakeCurrent(null);
} }
public void MakeCurrent() public void MakeCurrent(bool unbind = false, bool shouldThrow = true)
{ {
Context?.MakeCurrent(_window); try
} {
Context?.MakeCurrent(!unbind ? _window : null);
}
catch (ContextException e)
{
if (shouldThrow)
{
throw;
}
public void MakeCurrent(NativeWindowBase window) Logger.Warning?.Print(LogClass.Ui, $"Failed to {(!unbind ? "bind" : "unbind")} OpenGL context: {e}");
{ }
Context?.MakeCurrent(window);
} }
public void SwapBuffers() public void SwapBuffers()

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.Common.Configuration.Hid
// This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical // This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical
[Flags] [Flags]
[JsonConverter(typeof(TypedStringEnumConverter<ControllerType>))] [JsonConverter(typeof(TypedStringEnumConverter<ControllerType>))]
public enum ControllerType : int public enum ControllerType
{ {
None, None,
ProController = 1 << 0, ProController = 1 << 0,

View File

@@ -5,7 +5,7 @@ namespace Ryujinx.Common.Configuration.Hid
{ {
// This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical // This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical
[JsonConverter(typeof(TypedStringEnumConverter<PlayerIndex>))] [JsonConverter(typeof(TypedStringEnumConverter<PlayerIndex>))]
public enum PlayerIndex : int public enum PlayerIndex
{ {
Player1 = 0, Player1 = 0,
Player2 = 1, Player2 = 1,

View File

@@ -24,6 +24,24 @@ namespace Ryujinx.Common.Memory
return value; return value;
} }
public bool TryRead<T>(out T value) where T : unmanaged
{
int valueSize = Unsafe.SizeOf<T>();
if (valueSize > _input.Length)
{
value = default;
return false;
}
value = MemoryMarshal.Cast<byte, T>(_input)[0];
_input = _input.Slice(valueSize);
return true;
}
public ReadOnlySpan<byte> GetSpan(int size) public ReadOnlySpan<byte> GetSpan(int size)
{ {
ReadOnlySpan<byte> data = _input.Slice(0, size); ReadOnlySpan<byte> data = _input.Slice(0, size);

View File

@@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
private int _refConsumerPtr; private int _refConsumerPtr;
private Action _interruptAction; private Action _interruptAction;
private object _interruptLock = new(); private readonly object _interruptLock = new();
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured; public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;

View File

@@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
private List<BufferMigration> _sources; private List<BufferMigration> _sources;
private BufferMigration _migrationTarget; private BufferMigration _migrationTarget;
private object _lock = new object(); private readonly object _lock = new();
/// <summary> /// <summary>
/// Whether the modified range list has any entries or not. /// Whether the modified range list has any entries or not.
@@ -125,7 +125,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
BufferModifiedRange overlap = overlaps[i]; BufferModifiedRange overlap = overlaps[i];
if (overlap.Address > address) if (overlap.Address > address)
{ {
// The start of the remaining region is uncovered by this overlap. Call the action for it. // The start of the remaining region is uncovered by this overlap. Call the action for it.

View File

@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
private ulong _accumulatedCounter; private ulong _accumulatedCounter;
private int _waiterCount; private int _waiterCount;
private object _lock = new object(); private readonly object _lock = new();
private Queue<BufferedQuery> _queryPool; private Queue<BufferedQuery> _queryPool;
private AutoResetEvent _queuedEvent = new AutoResetEvent(false); private AutoResetEvent _queuedEvent = new AutoResetEvent(false);

View File

@@ -24,7 +24,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
private bool _hostAccessReserved = false; private bool _hostAccessReserved = false;
private int _refCount = 1; // Starts with a reference from the counter queue. private int _refCount = 1; // Starts with a reference from the counter queue.
private object _lock = new object(); private readonly object _lock = new();
private ulong _result = ulong.MaxValue; private ulong _result = ulong.MaxValue;
private double _divisor = 1f; private double _divisor = 1f;

View File

@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.OpenGL
{ {
private const int DisposedLiveFrames = 2; private const int DisposedLiveFrames = 2;
private readonly object _lock = new object(); private readonly object _lock = new();
private readonly Dictionary<TextureCreateInfo, List<DisposedTexture>> _textures = new Dictionary<TextureCreateInfo, List<DisposedTexture>>(); private readonly Dictionary<TextureCreateInfo, List<DisposedTexture>> _textures = new Dictionary<TextureCreateInfo, List<DisposedTexture>>();
/// <summary> /// <summary>

View File

@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Vulkan.MoltenVK namespace Ryujinx.Graphics.Vulkan.MoltenVK
{ {
enum MVKConfigLogLevel : int enum MVKConfigLogLevel
{ {
None = 0, None = 0,
Error = 1, Error = 1,
@@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Vulkan.MoltenVK
Debug = 4 Debug = 4
} }
enum MVKConfigTraceVulkanCalls : int enum MVKConfigTraceVulkanCalls
{ {
None = 0, None = 0,
Enter = 1, Enter = 1,
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Vulkan.MoltenVK
Duration = 3 Duration = 3
} }
enum MVKConfigAutoGPUCaptureScope : int enum MVKConfigAutoGPUCaptureScope
{ {
None = 0, None = 0,
Device = 1, Device = 1,
@@ -28,7 +28,7 @@ namespace Ryujinx.Graphics.Vulkan.MoltenVK
} }
[Flags] [Flags]
enum MVKConfigAdvertiseExtensions : int enum MVKConfigAdvertiseExtensions
{ {
All = 0x00000001, All = 0x00000001,
MoltenVK = 0x00000002, MoltenVK = 0x00000002,
@@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Vulkan.MoltenVK
Portability = 0x00000008 Portability = 0x00000008
} }
enum MVKVkSemaphoreSupportStyle : int enum MVKVkSemaphoreSupportStyle
{ {
MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE = 0, MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE = 0,
MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS_WHERE_SAFE = 1, MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS_WHERE_SAFE = 1,

View File

@@ -24,7 +24,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
private ulong _accumulatedCounter; private ulong _accumulatedCounter;
private int _waiterCount; private int _waiterCount;
private object _lock = new object(); private readonly object _lock = new();
private Queue<BufferedQuery> _queryPool; private Queue<BufferedQuery> _queryPool;
private AutoResetEvent _queuedEvent = new AutoResetEvent(false); private AutoResetEvent _queuedEvent = new AutoResetEvent(false);

View File

@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
private bool _hostAccessReserved = false; private bool _hostAccessReserved = false;
private int _refCount = 1; // Starts with a reference from the counter queue. private int _refCount = 1; // Starts with a reference from the counter queue.
private object _lock = new object(); private readonly object _lock = new();
private ulong _result = ulong.MaxValue; private ulong _result = ulong.MaxValue;
private double _divisor = 1f; private double _divisor = 1f;

View File

@@ -60,7 +60,7 @@ namespace Ryujinx.HLE.HOS.Applets
private bool _canAcceptController = false; private bool _canAcceptController = false;
private KeyboardInputMode _inputMode = KeyboardInputMode.ControllerAndKeyboard; private KeyboardInputMode _inputMode = KeyboardInputMode.ControllerAndKeyboard;
private object _lock = new object(); private readonly object _lock = new();
public event EventHandler AppletStateChanged; public event EventHandler AppletStateChanged;

View File

@@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
private const int TextBoxBlinkSleepMilliseconds = 100; private const int TextBoxBlinkSleepMilliseconds = 100;
private const int RendererWaitTimeoutMilliseconds = 100; private const int RendererWaitTimeoutMilliseconds = 100;
private readonly object _stateLock = new object(); private readonly object _stateLock = new();
private SoftwareKeyboardUiState _state = new SoftwareKeyboardUiState(); private SoftwareKeyboardUiState _state = new SoftwareKeyboardUiState();
private SoftwareKeyboardRendererBase _renderer; private SoftwareKeyboardRendererBase _renderer;

View File

@@ -26,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
const string CancelText = "Cancel"; const string CancelText = "Cancel";
const string ControllerToggleText = "Toggle input"; const string ControllerToggleText = "Toggle input";
private readonly object _bufferLock = new object(); private readonly object _bufferLock = new();
private RenderingSurfaceInfo _surfaceInfo = null; private RenderingSurfaceInfo _surfaceInfo = null;
private Image<Argb32> _surface = null; private Image<Argb32> _surface = null;
@@ -311,7 +311,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
private static RectangleF MeasureString(ReadOnlySpan<char> text, Font font) private static RectangleF MeasureString(ReadOnlySpan<char> text, Font font)
{ {
RendererOptions options = new RendererOptions(font); RendererOptions options = new RendererOptions(font);
if (text == "") if (text == "")
{ {
FontRectangle emptyRectangle = TextMeasurer.Measure(" ", options); FontRectangle emptyRectangle = TextMeasurer.Measure(" ", options);

View File

@@ -26,8 +26,8 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
} }
private TRef<bool> _cancelled = null; private TRef<bool> _cancelled = null;
private Thread _thread = null; private Thread _thread = null;
private object _lock = new object(); private readonly object _lock = new();
public bool IsRunning public bool IsRunning
{ {

View File

@@ -40,8 +40,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public ProcessState State { get; private set; } public ProcessState State { get; private set; }
private object _processLock; private readonly object _processLock = new();
private object _threadingLock; private readonly object _threadingLock = new();
public KAddressArbiter AddressArbiter { get; private set; } public KAddressArbiter AddressArbiter { get; private set; }
@@ -94,9 +94,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KProcess(KernelContext context, bool allowCodeMemoryForJit = false) : base(context) public KProcess(KernelContext context, bool allowCodeMemoryForJit = false) : base(context)
{ {
_processLock = new object();
_threadingLock = new object();
AddressArbiter = new KAddressArbiter(context); AddressArbiter = new KAddressArbiter(context);
_fullTlsPages = new SortedDictionary<ulong, KTlsPageInfo>(); _fullTlsPages = new SortedDictionary<ulong, KTlsPageInfo>();

View File

@@ -112,7 +112,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
public bool WaitingInArbitration { get; set; } public bool WaitingInArbitration { get; set; }
private object _activityOperationLock; private readonly object _activityOperationLock = new();
public KThread(KernelContext context) : base(context) public KThread(KernelContext context) : base(context)
{ {
@@ -123,8 +123,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_mutexWaiters = new LinkedList<KThread>(); _mutexWaiters = new LinkedList<KThread>();
_pinnedWaiters = new LinkedList<KThread>(); _pinnedWaiters = new LinkedList<KThread>();
_activityOperationLock = new object();
} }
public Result Initialize( public Result Initialize(

View File

@@ -154,7 +154,7 @@ namespace Ryujinx.HLE.HOS
} }
private static DirectoryInfo FindTitleDir(DirectoryInfo contentsDir, string titleId) private static DirectoryInfo FindTitleDir(DirectoryInfo contentsDir, string titleId)
=> contentsDir.EnumerateDirectories($"{titleId}*", DirEnumOptions).FirstOrDefault(); => contentsDir.EnumerateDirectories(titleId, DirEnumOptions).FirstOrDefault();
private static void AddModsFromDirectory(ModCache mods, DirectoryInfo dir, string titleId) private static void AddModsFromDirectory(ModCache mods, DirectoryInfo dir, string titleId)
{ {

View File

@@ -17,8 +17,8 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
private KEvent _accumulatedSuspendedTickChangedEvent; private KEvent _accumulatedSuspendedTickChangedEvent;
private int _accumulatedSuspendedTickChangedEventHandle; private int _accumulatedSuspendedTickChangedEventHandle;
private object _fatalSectionLock = new object(); private readonly object _fatalSectionLock = new();
private int _fatalSectionCount; private int _fatalSectionCount;
// TODO: Set this when the game goes in suspension (go back to home menu ect), we currently don't support that so we can keep it set to 0. // TODO: Set this when the game goes in suspension (go back to home menu ect), we currently don't support that so we can keep it set to 0.
private ulong _accumulatedSuspendedTickValue = 0; private ulong _accumulatedSuspendedTickValue = 0;
@@ -429,4 +429,4 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
return ResultCode.Success; return ResultCode.Success;
} }
} }
} }

View File

@@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
private readonly UserId _userId; private readonly UserId _userId;
private readonly FriendServicePermissionLevel _permissionLevel; private readonly FriendServicePermissionLevel _permissionLevel;
private readonly object _lock = new object(); private readonly object _lock = new();
private KEvent _notificationEvent; private KEvent _notificationEvent;
private int _notificationEventHandle = 0; private int _notificationEventHandle = 0;

View File

@@ -1,8 +1,29 @@
namespace Ryujinx.HLE.HOS.Services.Hid using Ryujinx.Common;
using Ryujinx.Common.Logging;
namespace Ryujinx.HLE.HOS.Services.Hid
{ {
[Service("hidbus")] [Service("hidbus")]
class IHidbusServer : IpcService class IHidbusServer : IpcService
{ {
public IHidbusServer(ServiceCtx context) { } public IHidbusServer(ServiceCtx context) { }
[CommandCmif(1)]
// GetBusHandle(nn::hid::NpadIdType, nn::hidbus::BusType, nn::applet::AppletResourceUserId) -> (bool HasHandle, nn::hidbus::BusHandle)
public ResultCode GetBusHandle(ServiceCtx context)
{
NpadIdType npadIdType = (NpadIdType)context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
BusType busType = (BusType)context.RequestData.ReadInt64();
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write(false);
context.ResponseData.BaseStream.Position += 7; // Padding
context.ResponseData.WriteStruct(new BusHandle());
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { npadIdType, busType, appletResourceUserId });
return ResultCode.Success;
}
} }
} }

View File

@@ -0,0 +1,14 @@
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Hid
{
[StructLayout(LayoutKind.Sequential)]
struct BusHandle
{
public int AbstractedPadId;
public byte InternalIndex;
public byte PlayerNumber;
public byte BusTypeId;
public byte IsValid;
}
}

View File

@@ -0,0 +1,9 @@
namespace Ryujinx.HLE.HOS.Services.Hid
{
public enum BusType : long
{
LeftJoyRail = 0,
RightJoyRail = 1,
InternalBus = 2
}
}

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Hid namespace Ryujinx.HLE.HOS.Services.Hid
{ {
[Flags] [Flags]
public enum ControllerType : int public enum ControllerType
{ {
None, None,
ProController = 1 << 0, ProController = 1 << 0,

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Hid namespace Ryujinx.HLE.HOS.Services.Hid
{ {
public enum NpadIdType : int public enum NpadIdType
{ {
Player1 = 0, Player1 = 0,
Player2 = 1, Player2 = 1,

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Hid namespace Ryujinx.HLE.HOS.Services.Hid
{ {
public enum PlayerIndex : int public enum PlayerIndex
{ {
Player1 = 0, Player1 = 0,
Player2 = 1, Player2 = 1,

View File

@@ -3,7 +3,7 @@
namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
{ {
[Flags] [Flags]
enum DeviceType : int enum DeviceType
{ {
None = 0, None = 0,

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
{ {
enum NpadBatteryLevel : int enum NpadBatteryLevel
{ {
Percent0, Percent0,
Percent25, Percent25,

View File

@@ -775,7 +775,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
private static ReadOnlySpan<ElementInfo> ElementInfos => MemoryMarshal.Cast<byte, ElementInfo>(ElementInfoArray); private static ReadOnlySpan<ElementInfo> ElementInfos => MemoryMarshal.Cast<byte, ElementInfo>(ElementInfoArray);
private enum ElementInfoIndex : int private enum ElementInfoIndex
{ {
HairType, HairType,
Height, Height,

View File

@@ -21,7 +21,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
}; };
[Flags] [Flags]
public enum BeardAndMustacheFlag : int public enum BeardAndMustacheFlag
{ {
Beard = 1, Beard = 1,
Mustache Mustache

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Mii.Types namespace Ryujinx.HLE.HOS.Services.Mii.Types
{ {
enum Source : int enum Source
{ {
Database, Database,
Default Default

View File

@@ -3,7 +3,7 @@
namespace Ryujinx.HLE.HOS.Services.Mii.Types namespace Ryujinx.HLE.HOS.Services.Mii.Types
{ {
[Flags] [Flags]
enum SourceFlag : int enum SourceFlag
{ {
Database = 1 << Source.Database, Database = 1 << Source.Database,
Default = 1 << Source.Default, Default = 1 << Source.Default,

View File

@@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
private NvFence _previousFailingFence; private NvFence _previousFailingFence;
private uint _failingCount; private uint _failingCount;
public readonly object Lock = new object(); public readonly object Lock = new();
/// <summary> /// <summary>
/// Max failing count until waiting on CPU. /// Max failing count until waiting on CPU.

View File

@@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
private Switch _device; private Switch _device;
private object _syncpointAllocatorLock = new object(); private readonly object _syncpointAllocatorLock = new();
public NvHostSyncpt(Switch device) public NvHostSyncpt(Switch device)
{ {

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
{ {
enum NvInternalResult : int enum NvInternalResult
{ {
Success = 0, Success = 0,
OperationNotPermitted = -1, OperationNotPermitted = -1,

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
{ {
enum NvMapHandleParam : int enum NvMapHandleParam
{ {
Size = 1, Size = 1,
Align = 2, Align = 2,

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
{ {
private static ConcurrentDictionary<ulong, BsdContext> _registry = new ConcurrentDictionary<ulong, BsdContext>(); private static ConcurrentDictionary<ulong, BsdContext> _registry = new ConcurrentDictionary<ulong, BsdContext>();
private readonly object _lock = new object(); private readonly object _lock = new();
private List<IFileDescriptor> _fds; private List<IFileDescriptor> _fds;

View File

@@ -5,7 +5,7 @@ using System.Net.Sockets;
namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
{ {
interface ISocket : IDisposable, IFileDescriptor interface ISocket : IFileDescriptor
{ {
IPEndPoint RemoteEndPoint { get; } IPEndPoint RemoteEndPoint { get; }
IPEndPoint LocalEndPoint { get; } IPEndPoint LocalEndPoint { get; }

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
private ulong _value; private ulong _value;
private readonly EventFdFlags _flags; private readonly EventFdFlags _flags;
private object _lock = new object(); private readonly object _lock = new();
public bool Blocking { get => !_flags.HasFlag(EventFdFlags.NonBlocking); set => throw new NotSupportedException(); } public bool Blocking { get => !_flags.HasFlag(EventFdFlags.NonBlocking); set => throw new NotSupportedException(); }

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Spl
{ {
private RandomNumberGenerator _rng; private RandomNumberGenerator _rng;
private object _lock = new object(); private readonly object _lock = new();
public IRandomInterface(ServiceCtx context) public IRandomInterface(ServiceCtx context)
{ {

View File

@@ -40,13 +40,13 @@ namespace Ryujinx.HLE.HOS.Services.Ssl
} }
} }
private VirtualFileSystem _virtualFileSystem; private VirtualFileSystem _virtualFileSystem;
private IntegrityCheckLevel _fsIntegrityCheckLevel; private IntegrityCheckLevel _fsIntegrityCheckLevel;
private ContentManager _contentManager; private ContentManager _contentManager;
private bool _initialized; private bool _initialized;
private Dictionary<CaCertificateId, CertStoreEntry> _certificates; private Dictionary<CaCertificateId, CertStoreEntry> _certificates;
private object _lock = new object(); private readonly object _lock = new();
private struct CertStoreFileHeader private struct CertStoreFileHeader
{ {

View File

@@ -34,7 +34,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public bool EnableExternalEvent; public bool EnableExternalEvent;
public int MaxBufferCountCached; public int MaxBufferCountCached;
public readonly object Lock = new object(); public readonly object Lock = new();
private KEvent _waitBufferFreeEvent; private KEvent _waitBufferFreeEvent;
private KEvent _frameAvailableEvent; private KEvent _frameAvailableEvent;

View File

@@ -21,7 +21,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private uint _currentCallbackTicket; private uint _currentCallbackTicket;
private uint _callbackTicket; private uint _callbackTicket;
private readonly object _callbackLock = new object(); private readonly object _callbackLock = new();
public BufferQueueProducer(BufferQueueCore core, ITickSource tickSource) public BufferQueueProducer(BufferQueueCore core, ITickSource tickSource)
{ {

View File

@@ -23,7 +23,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
protected BufferQueueConsumer Consumer; protected BufferQueueConsumer Consumer;
protected readonly object Lock = new object(); protected readonly object Lock = new();
private IConsumerListener _listener; private IConsumerListener _listener;
@@ -168,7 +168,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Slot slot = Slots[slotIndex]; Slot slot = Slots[slotIndex];
// TODO: Check this. On Android, this checks the "handle". I assume NvMapHandle is the handle, but it might not be. // TODO: Check this. On Android, this checks the "handle". I assume NvMapHandle is the handle, but it might not be.
return !slot.GraphicBuffer.IsNull && slot.GraphicBuffer.Object.Buffer.Surfaces[0].NvMapHandle == graphicBuffer.Object.Buffer.Surfaces[0].NvMapHandle; return !slot.GraphicBuffer.IsNull && slot.GraphicBuffer.Object.Buffer.Surfaces[0].NvMapHandle == graphicBuffer.Object.Buffer.Surfaces[0].NvMapHandle;
} }
} }

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {
enum NativeWindowApi : int enum NativeWindowApi
{ {
NoApi = 0, NoApi = 0,
NVN = 1, NVN = 1,

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {
enum Status : int enum Status
{ {
Success = 0, Success = 0,
WouldBlock = -11, WouldBlock = -11,

View File

@@ -37,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private int _swapInterval; private int _swapInterval;
private int _swapIntervalDelay; private int _swapIntervalDelay;
private readonly object Lock = new object(); private readonly object Lock = new();
public long RenderLayerId { get; private set; } public long RenderLayerId { get; private set; }

View File

@@ -13,14 +13,13 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
private UInt128 _timeZoneRuleVersion; private UInt128 _timeZoneRuleVersion;
private uint _totalLocationNameCount; private uint _totalLocationNameCount;
private SteadyClockTimePoint _timeZoneUpdateTimePoint; private SteadyClockTimePoint _timeZoneUpdateTimePoint;
private object _lock; private readonly object _lock = new();
public TimeZoneManager() public TimeZoneManager()
{ {
_isInitialized = false; _isInitialized = false;
_deviceLocationName = "UTC"; _deviceLocationName = "UTC";
_timeZoneRuleVersion = new UInt128(); _timeZoneRuleVersion = new UInt128();
_lock = new object();
_myRules = new Box<TimeZoneRule>(); _myRules = new Box<TimeZoneRule>();
_timeZoneUpdateTimePoint = SteadyClockTimePoint.GetRandom(); _timeZoneUpdateTimePoint = SteadyClockTimePoint.GetRandom();

View File

@@ -17,7 +17,7 @@ namespace Ryujinx.Horizon.LogManager.Ipc
private const int MessageLengthLimit = 5000; private const int MessageLengthLimit = 5000;
private readonly LogService _log; private readonly LogService _log;
private readonly ulong _pid; private readonly ulong _pid;
private LogPacket _logPacket; private LogPacket _logPacket;
@@ -74,8 +74,12 @@ namespace Ryujinx.Horizon.LogManager.Ipc
private bool LogImpl(ReadOnlySpan<byte> message) private bool LogImpl(ReadOnlySpan<byte> message)
{ {
SpanReader reader = new(message); SpanReader reader = new(message);
LogPacketHeader header = reader.Read<LogPacketHeader>();
if (!reader.TryRead(out LogPacketHeader header))
{
return true;
}
bool isHeadPacket = (header.Flags & LogPacketFlags.IsHead) != 0; bool isHeadPacket = (header.Flags & LogPacketFlags.IsHead) != 0;
bool isTailPacket = (header.Flags & LogPacketFlags.IsTail) != 0; bool isTailPacket = (header.Flags & LogPacketFlags.IsTail) != 0;
@@ -84,8 +88,10 @@ namespace Ryujinx.Horizon.LogManager.Ipc
while (reader.Length > 0) while (reader.Length > 0)
{ {
int type = ReadUleb128(ref reader); if (!TryReadUleb128(ref reader, out int type) || !TryReadUleb128(ref reader, out int size))
int size = ReadUleb128(ref reader); {
return true;
}
LogDataChunkKey key = (LogDataChunkKey)type; LogDataChunkKey key = (LogDataChunkKey)type;
@@ -101,15 +107,24 @@ namespace Ryujinx.Horizon.LogManager.Ipc
} }
else if (key == LogDataChunkKey.Line) else if (key == LogDataChunkKey.Line)
{ {
_logPacket.Line = reader.Read<int>(); if (!reader.TryRead<int>(out _logPacket.Line))
{
return true;
}
} }
else if (key == LogDataChunkKey.DropCount) else if (key == LogDataChunkKey.DropCount)
{ {
_logPacket.DropCount = reader.Read<long>(); if (!reader.TryRead<long>(out _logPacket.DropCount))
{
return true;
}
} }
else if (key == LogDataChunkKey.Time) else if (key == LogDataChunkKey.Time)
{ {
_logPacket.Time = reader.Read<long>(); if (!reader.TryRead<long>(out _logPacket.Time))
{
return true;
}
} }
else if (key == LogDataChunkKey.Message) else if (key == LogDataChunkKey.Message)
{ {
@@ -154,23 +169,25 @@ namespace Ryujinx.Horizon.LogManager.Ipc
return isTailPacket; return isTailPacket;
} }
private static int ReadUleb128(ref SpanReader reader) private static bool TryReadUleb128(ref SpanReader reader, out int result)
{ {
int result = 0; result = 0;
int count = 0; int count = 0;
byte encoded; byte encoded;
do do
{ {
encoded = reader.Read<byte>(); if (!reader.TryRead<byte>(out encoded))
{
return false;
}
result += (encoded & 0x7F) << (7 * count); result += (encoded & 0x7F) << (7 * count);
count++; count++;
} while ((encoded & 0x80) != 0); } while ((encoded & 0x80) != 0);
return result; return true;
} }
} }
} }

View File

@@ -13,7 +13,7 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl
private readonly List<MultiWaitHolderBase> _multiWaits; private readonly List<MultiWaitHolderBase> _multiWaits;
private object _lock; private readonly object _lock = new();
private int _waitingThreadHandle; private int _waitingThreadHandle;
@@ -24,8 +24,6 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl
public MultiWaitImpl() public MultiWaitImpl()
{ {
_multiWaits = new List<MultiWaitHolderBase>(); _multiWaits = new List<MultiWaitHolderBase>();
_lock = new object();
} }
public void LinkMultiWaitHolder(MultiWaitHolderBase multiWaitHolder) public void LinkMultiWaitHolder(MultiWaitHolderBase multiWaitHolder)

View File

@@ -46,7 +46,7 @@ namespace Ryujinx.Input.SDL2
SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE2, SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE2,
SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE3, SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE3,
SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE4, SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_PADDLE4,
SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_TOUCHPAD, SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_TOUCHPAD,
// Virtual buttons are invalid, ignored. // Virtual buttons are invalid, ignored.
SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_INVALID, SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_INVALID,
@@ -55,7 +55,7 @@ namespace Ryujinx.Input.SDL2
SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_INVALID, SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_INVALID,
}; };
private object _userMappingLock = new object(); private readonly object _userMappingLock = new();
private List<ButtonMappingEntry> _buttonsUserMapping; private List<ButtonMappingEntry> _buttonsUserMapping;

View File

@@ -24,7 +24,7 @@ namespace Ryujinx.Input.SDL2
} }
} }
private object _userMappingLock = new object(); private readonly object _userMappingLock = new();
private readonly SDL2KeyboardDriver _driver; private readonly SDL2KeyboardDriver _driver;
private StandardKeyboardInputConfig _configuration; private StandardKeyboardInputConfig _configuration;

View File

@@ -15,7 +15,7 @@ namespace Ryujinx.Input.HLE
{ {
private CemuHookClient _cemuHookClient; private CemuHookClient _cemuHookClient;
private object _lock = new object(); private readonly object _lock = new();
private bool _blockInputUpdates; private bool _blockInputUpdates;
@@ -271,7 +271,7 @@ namespace Ryujinx.Input.HLE
_device.Hid.Mouse.Update((int)position.X, (int)position.Y, buttons, (int)mouseInput.Scroll.X, (int)mouseInput.Scroll.Y, true); _device.Hid.Mouse.Update((int)position.X, (int)position.Y, buttons, (int)mouseInput.Scroll.X, (int)mouseInput.Scroll.Y, true);
} }
else else
{ {
_device.Hid.Mouse.Update(0, 0); _device.Hid.Mouse.Update(0, 0);
} }

View File

@@ -52,7 +52,7 @@ namespace Ryujinx.Memory.Tracking
private event Action _onDirty; private event Action _onDirty;
private object _preActionLock = new object(); private readonly object _preActionLock = new();
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access. private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
private PreciseRegionSignal _preciseAction; // Action to perform on a precise read or write. private PreciseRegionSignal _preciseAction; // Action to perform on a precise read or write.
private readonly List<VirtualRegion> _regions; private readonly List<VirtualRegion> _regions;

View File

@@ -41,7 +41,7 @@ namespace Ryujinx.SDL2.Common
private ConcurrentDictionary<uint, Action<SDL_Event>> _registeredWindowHandlers; private ConcurrentDictionary<uint, Action<SDL_Event>> _registeredWindowHandlers;
private object _lock = new object(); private readonly object _lock = new();
private SDL2Driver() {} private SDL2Driver() {}

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.Tests.Memory
{ {
public class Tests public class Tests
{ {
private const ulong MemorySize = 0x8000; private static readonly ulong MemorySize = MemoryBlock.GetPageSize() * 8;
private MemoryBlock _memoryBlock; private MemoryBlock _memoryBlock;
@@ -44,14 +44,17 @@ namespace Ryujinx.Tests.Memory
[Platform(Exclude = "MacOsX")] [Platform(Exclude = "MacOsX")]
public void Test_Alias() public void Test_Alias()
{ {
using MemoryBlock backing = new MemoryBlock(0x10000, MemoryAllocationFlags.Mirrorable); ulong pageSize = MemoryBlock.GetPageSize();
using MemoryBlock toAlias = new MemoryBlock(0x10000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible); ulong blockSize = MemoryBlock.GetPageSize() * 16;
toAlias.MapView(backing, 0x1000, 0, 0x4000); using MemoryBlock backing = new MemoryBlock(blockSize, MemoryAllocationFlags.Mirrorable);
toAlias.UnmapView(backing, 0x3000, 0x1000); using MemoryBlock toAlias = new MemoryBlock(blockSize, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
toAlias.MapView(backing, pageSize, 0, pageSize * 4);
toAlias.UnmapView(backing, pageSize * 3, pageSize);
toAlias.Write(0, 0xbadc0de); toAlias.Write(0, 0xbadc0de);
Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, 0x1000), 0xbadc0de); Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, (int)pageSize), 0xbadc0de);
} }
[Test] [Test]
@@ -59,8 +62,12 @@ namespace Ryujinx.Tests.Memory
[Platform(Exclude = "MacOsX")] [Platform(Exclude = "MacOsX")]
public void Test_AliasRandom() public void Test_AliasRandom()
{ {
using MemoryBlock backing = new MemoryBlock(0x80000, MemoryAllocationFlags.Mirrorable); ulong pageSize = MemoryBlock.GetPageSize();
using MemoryBlock toAlias = new MemoryBlock(0x80000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible); int pageBits = (int)ulong.Log2(pageSize);
ulong blockSize = MemoryBlock.GetPageSize() * 128;
using MemoryBlock backing = new MemoryBlock(blockSize, MemoryAllocationFlags.Mirrorable);
using MemoryBlock toAlias = new MemoryBlock(blockSize, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
Random rng = new Random(123); Random rng = new Random(123);
@@ -72,16 +79,16 @@ namespace Ryujinx.Tests.Memory
if ((rng.Next() & 1) != 0) if ((rng.Next() & 1) != 0)
{ {
toAlias.MapView(backing, (ulong)srcPage << 12, (ulong)dstPage << 12, (ulong)pages << 12); toAlias.MapView(backing, (ulong)srcPage << pageBits, (ulong)dstPage << pageBits, (ulong)pages << pageBits);
int offset = rng.Next(0, 0x1000 - sizeof(int)); int offset = rng.Next(0, (int)pageSize - sizeof(int));
toAlias.Write((ulong)((dstPage << 12) + offset), 0xbadc0de); toAlias.Write((ulong)((dstPage << pageBits) + offset), 0xbadc0de);
Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, (srcPage << 12) + offset), 0xbadc0de); Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, (srcPage << pageBits) + offset), 0xbadc0de);
} }
else else
{ {
toAlias.UnmapView(backing, (ulong)dstPage << 12, (ulong)pages << 12); toAlias.UnmapView(backing, (ulong)dstPage << pageBits, (ulong)pages << pageBits);
} }
} }
} }
@@ -91,7 +98,7 @@ namespace Ryujinx.Tests.Memory
[Platform(Exclude = "MacOsX")] [Platform(Exclude = "MacOsX")]
public void Test_AliasMapLeak() public void Test_AliasMapLeak()
{ {
ulong pageSize = 4096; ulong pageSize = MemoryBlock.GetPageSize();
ulong size = 100000 * pageSize; // The mappings limit on Linux is usually around 65K, so let's make sure we are above that. ulong size = 100000 * pageSize; // The mappings limit on Linux is usually around 65K, so let's make sure we are above that.
using MemoryBlock backing = new MemoryBlock(pageSize, MemoryAllocationFlags.Mirrorable); using MemoryBlock backing = new MemoryBlock(pageSize, MemoryAllocationFlags.Mirrorable);

View File

@@ -13,9 +13,9 @@ namespace Ryujinx.Tests.Cpu
[TestFixture] [TestFixture]
public class CpuTest public class CpuTest
{ {
protected const ulong Size = 0x1000; protected static readonly ulong Size = MemoryBlock.GetPageSize();
protected const ulong CodeBaseAddress = 0x1000; protected static ulong CodeBaseAddress = Size;
protected const ulong DataBaseAddress = CodeBaseAddress + Size; protected static ulong DataBaseAddress = CodeBaseAddress + Size;
private static bool Ignore_FpcrFz = false; private static bool Ignore_FpcrFz = false;
private static bool Ignore_FpcrDn = false; private static bool Ignore_FpcrDn = false;
@@ -39,12 +39,24 @@ namespace Ryujinx.Tests.Cpu
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_currAddress = CodeBaseAddress; int pageBits = (int)ulong.Log2(Size);
_ram = new MemoryBlock(Size * 2); _ram = new MemoryBlock(Size * 2);
_memory = new MemoryManager(_ram, 1ul << 16); _memory = new MemoryManager(_ram, 1ul << (pageBits + 4));
_memory.IncrementReferenceCount(); _memory.IncrementReferenceCount();
_memory.Map(CodeBaseAddress, 0, Size * 2, MemoryMapFlags.Private);
// Some tests depends on hardcoded address that were computed for 4KiB.
// We change the layout on non 4KiB platforms to keep compat here.
if (Size > 0x1000)
{
DataBaseAddress = 0;
CodeBaseAddress = Size;
}
_currAddress = CodeBaseAddress;
_memory.Map(CodeBaseAddress, 0, Size, MemoryMapFlags.Private);
_memory.Map(DataBaseAddress, Size, Size, MemoryMapFlags.Private);
_context = CpuContext.CreateExecutionContext(); _context = CpuContext.CreateExecutionContext();
Translator.IsReadyForTranslation.Set(); Translator.IsReadyForTranslation.Set();

View File

@@ -13,9 +13,9 @@ namespace Ryujinx.Tests.Cpu
[TestFixture] [TestFixture]
public class CpuTest32 public class CpuTest32
{ {
protected const uint Size = 0x1000; protected static readonly uint Size = (uint)MemoryBlock.GetPageSize();
protected const uint CodeBaseAddress = 0x1000; protected static uint CodeBaseAddress = Size;
protected const uint DataBaseAddress = CodeBaseAddress + Size; protected static uint DataBaseAddress = CodeBaseAddress + Size;
private uint _currAddress; private uint _currAddress;
@@ -33,12 +33,24 @@ namespace Ryujinx.Tests.Cpu
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_currAddress = CodeBaseAddress; int pageBits = (int)ulong.Log2(Size);
_ram = new MemoryBlock(Size * 2); _ram = new MemoryBlock(Size * 2);
_memory = new MemoryManager(_ram, 1ul << 16); _memory = new MemoryManager(_ram, 1ul << (pageBits + 4));
_memory.IncrementReferenceCount(); _memory.IncrementReferenceCount();
_memory.Map(CodeBaseAddress, 0, Size * 2, MemoryMapFlags.Private);
// Some tests depends on hardcoded address that were computed for 4KiB.
// We change the layout on non 4KiB platforms to keep compat here.
if (Size > 0x1000)
{
DataBaseAddress = 0;
CodeBaseAddress = Size;
}
_currAddress = CodeBaseAddress;
_memory.Map(CodeBaseAddress, 0, Size, MemoryMapFlags.Private);
_memory.Map(DataBaseAddress, Size, Size, MemoryMapFlags.Private);
_context = CpuContext.CreateExecutionContext(); _context = CpuContext.CreateExecutionContext();
_context.IsAarch32 = true; _context.IsAarch32 = true;

View File

@@ -1,6 +1,7 @@
#define SimdMemory32 #define SimdMemory32
using ARMeilleure.State; using ARMeilleure.State;
using Ryujinx.Memory;
using NUnit.Framework; using NUnit.Framework;
using System; using System;
@@ -9,6 +10,7 @@ namespace Ryujinx.Tests.Cpu
[Category("SimdMemory32")] [Category("SimdMemory32")]
public sealed class CpuTestSimdMemory32 : CpuTest32 public sealed class CpuTestSimdMemory32 : CpuTest32
{ {
private static readonly uint TestOffset = DataBaseAddress + 0x500;
#if SimdMemory32 #if SimdMemory32
private uint[] _ldStModes = private uint[] _ldStModes =
@@ -42,7 +44,7 @@ namespace Ryujinx.Tests.Cpu
[Range(0u, 3u)] uint n, [Range(0u, 3u)] uint n,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xf4a00000u; // VLD1.8 {D0[0]}, [R0], R0 uint opcode = 0xf4a00000u; // VLD1.8 {D0[0]}, [R0], R0
@@ -58,7 +60,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc. opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -72,7 +74,7 @@ namespace Ryujinx.Tests.Cpu
[Values] bool t, [Values] bool t,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xf4a00c00u; // VLD1.8 {D0[0]}, [R0], R0 uint opcode = 0xf4a00c00u; // VLD1.8 {D0[0]}, [R0], R0
@@ -85,7 +87,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc. opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
if (t) opcode |= 1 << 5; if (t) opcode |= 1 << 5;
SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -98,7 +100,7 @@ namespace Ryujinx.Tests.Cpu
[Range(0u, 10u)] uint mode, [Range(0u, 10u)] uint mode,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xf4200000u; // VLD4.8 {D0, D1, D2, D3}, [R0], R0 uint opcode = 0xf4200000u; // VLD4.8 {D0, D1, D2, D3}, [R0], R0
@@ -114,7 +116,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -128,7 +130,7 @@ namespace Ryujinx.Tests.Cpu
[Range(0u, 3u)] uint n, [Range(0u, 3u)] uint n,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
(V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors(); (V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors();
@@ -146,7 +148,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc. opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc.
SingleOpcode(opcode, r0: 0x2500, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -159,7 +161,7 @@ namespace Ryujinx.Tests.Cpu
[Range(0u, 10u)] uint mode, [Range(0u, 10u)] uint mode,
[Values(0x0u)] uint offset) [Values(0x0u)] uint offset)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
(V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors(); (V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors();
@@ -177,7 +179,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); opcode |= ((vd & 0xf) << 12);
SingleOpcode(opcode, r0: 0x2500, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -189,7 +191,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0x1u, 0x32u)] uint regs, [Values(0x1u, 0x32u)] uint regs,
[Values] bool single) [Values] bool single)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xec100a00u; // VST4.8 {D0, D1, D2, D3}, [R0], R0 uint opcode = 0xec100a00u; // VST4.8 {D0, D1, D2, D3}, [R0], R0
@@ -225,7 +227,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= regs & 0xff; opcode |= regs & 0xff;
SingleOpcode(opcode, r0: 0x2500, sp: 0x2500); SingleOpcode(opcode, r0: TestOffset, sp: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -237,7 +239,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0x0u)] uint imm, [Values(0x0u)] uint imm,
[Values] bool sub) [Values] bool sub)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xed900a00u; // VLDR.32 S0, [R0, #0] uint opcode = 0xed900a00u; // VLDR.32 S0, [R0, #0]
@@ -260,7 +262,7 @@ namespace Ryujinx.Tests.Cpu
} }
opcode |= imm & 0xff; opcode |= imm & 0xff;
SingleOpcode(opcode, r0: 0x2500); SingleOpcode(opcode, r0: TestOffset);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@@ -272,7 +274,7 @@ namespace Ryujinx.Tests.Cpu
[Values(0x0u)] uint imm, [Values(0x0u)] uint imm,
[Values] bool sub) [Values] bool sub)
{ {
var data = GenerateVectorSequence(0x1000); var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
SetWorkingMemory(0, data); SetWorkingMemory(0, data);
uint opcode = 0xed800a00u; // VSTR.32 S0, [R0, #0] uint opcode = 0xed800a00u; // VSTR.32 S0, [R0, #0]
@@ -297,7 +299,7 @@ namespace Ryujinx.Tests.Cpu
(V128 vec1, V128 vec2, _, _) = GenerateTestVectors(); (V128 vec1, V128 vec2, _, _) = GenerateTestVectors();
SingleOpcode(opcode, r0: 0x2500, v0: vec1, v1: vec2); SingleOpcode(opcode, r0: TestOffset, v0: vec1, v1: vec2);
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }

Some files were not shown because too many files have changed in this diff Show More