Compare commits

..

11 Commits

Author SHA1 Message Date
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
31 changed files with 393 additions and 76 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

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

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

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

@@ -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 = 5281; //! 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

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

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

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

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

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

@@ -11,10 +11,10 @@ namespace Ryujinx.Ui.Common.Helper
{ {
public static partial class FileAssociationHelper public static partial class FileAssociationHelper
{ {
private static string[] _fileExtensions = new string[] { ".nca", ".nro", ".nso", ".nsp", ".xci" }; private static readonly string[] _fileExtensions = { ".nca", ".nro", ".nso", ".nsp", ".xci" };
[SupportedOSPlatform("linux")] [SupportedOSPlatform("linux")]
private static string _mimeDbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "mime"); private static readonly string _mimeDbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "mime");
private const int SHCNE_ASSOCCHANGED = 0x8000000; private const int SHCNE_ASSOCCHANGED = 0x8000000;
private const int SHCNF_FLUSH = 0x1000; private const int SHCNF_FLUSH = 0x1000;
@@ -32,7 +32,7 @@ namespace Ryujinx.Ui.Common.Helper
{ {
string installKeyword = uninstall ? "uninstall" : "install"; string installKeyword = uninstall ? "uninstall" : "install";
if (!AreMimeTypesRegisteredLinux()) if ((uninstall && AreMimeTypesRegisteredLinux()) || (!uninstall && !AreMimeTypesRegisteredLinux()))
{ {
string mimeTypesFile = Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "mime", "Ryujinx.xml"); string mimeTypesFile = Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "mime", "Ryujinx.xml");
string additionalArgs = !uninstall ? "--novendor" : ""; string additionalArgs = !uninstall ? "--novendor" : "";
@@ -81,9 +81,9 @@ namespace Ryujinx.Ui.Common.Helper
return false; return false;
} }
key.OpenSubKey(@"shell\open\command"); var openCmd = key.OpenSubKey(@"shell\open\command");
string keyValue = (string)key.GetValue(""); string keyValue = (string)openCmd.GetValue("");
return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName)); return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName));
} }
@@ -107,30 +107,31 @@ namespace Ryujinx.Ui.Common.Helper
if (uninstall) if (uninstall)
{ {
// If the types don't already exist, there's nothing to do and we can call this operation successful.
if (!AreMimeTypesRegisteredWindows()) if (!AreMimeTypesRegisteredWindows())
{ {
return false; return true;
} }
Logger.Debug?.Print(LogClass.Application, $"Removing type association {ext}");
Registry.CurrentUser.DeleteSubKeyTree(keyString); Registry.CurrentUser.DeleteSubKeyTree(keyString);
Logger.Debug?.Print(LogClass.Application, $"Removed type association {ext}");
} }
else else
{ {
RegistryKey key = Registry.CurrentUser.CreateSubKey(keyString); using var key = Registry.CurrentUser.CreateSubKey(keyString);
if (key is null) if (key is null)
{ {
return false; return false;
} }
key.CreateSubKey(@"shell\open\command"); Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}");
using var openCmd = key.CreateSubKey(@"shell\open\command");
openCmd.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\"");
Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}");
key.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\"");
key.Close();
} }
// Notify Explorer the file association has been changed.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
return true; return true;
} }
@@ -141,6 +142,9 @@ namespace Ryujinx.Ui.Common.Helper
registered |= RegisterExtension(ext, uninstall); registered |= RegisterExtension(ext, uninstall);
} }
// Notify Explorer the file association has been changed.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
return registered; return registered;
} }

View File

@@ -1,8 +1,10 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.OpenGL;
using Ryujinx.Input.HLE; using Ryujinx.Input.HLE;
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.GLX; using SPB.Platform.GLX;
@@ -112,24 +114,30 @@ namespace Ryujinx.Ui
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
// Try to bind the OpenGL context before calling the shutdown event // Try to bind the OpenGL context before calling the shutdown event.
try try
{ {
_openGLContext?.MakeCurrent(_nativeWindow); _openGLContext?.MakeCurrent(_nativeWindow);
} }
catch (Exception) { } catch (ContextException e)
{
Logger.Warning?.Print(LogClass.Ui, $"Failed to bind OpenGL context: {e}");
}
Device?.DisposeGpu(); Device?.DisposeGpu();
NpadManager.Dispose(); NpadManager.Dispose();
// Unbind context and destroy everything // Unbind context and destroy everything.
try try
{ {
_openGLContext?.MakeCurrent(null); _openGLContext?.MakeCurrent(null);
} }
catch (Exception) { } catch (ContextException e)
{
Logger.Warning?.Print(LogClass.Ui, $"Failed to unbind OpenGL context: {e}");
}
_openGLContext?.Dispose(); _openGLContext?.Dispose();
} }
} }
} }