fix revert conflicts
This commit is contained in:
parent
76cfded3a4
commit
8bc9631366
@ -3,13 +3,13 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia" Version="11.0.10" />
|
<PackageVersion Include="Avalonia" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" />
|
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.13" />
|
||||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" />
|
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.19" />
|
||||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" />
|
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.19" />
|
||||||
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
|
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
|
||||||
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
|
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
|
||||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
@ -17,7 +17,8 @@
|
|||||||
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
|
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
|
||||||
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
|
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
|
||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="Concentus" Version="2.2.0" />
|
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
|
||||||
|
<PackageVersion Include="Concentus" Version="2.2.2" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||||
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
||||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
||||||
@ -25,7 +26,7 @@
|
|||||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.1.2" />
|
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.3.0" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
||||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||||
@ -41,15 +42,16 @@
|
|||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||||
<PackageVersion Include="Gommon" Version="2.6.8" />
|
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
|
<PackageVersion Include="Sep" Version="0.6.0" />
|
||||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.22.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
|
||||||
<PackageVersion Include="SkiaSharp" Version="2.88.7" />
|
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.7" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
|
<PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
|
||||||
<PackageVersion Include="System.Management" Version="9.0.0" />
|
<PackageVersion Include="System.Management" Version="9.0.0" />
|
||||||
|
@ -57,14 +57,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "src\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Headless.SDL2", "src\Ryujinx.Headless.SDL2\Ryujinx.Headless.SDL2.csproj", "{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.Common", "src\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
|
||||||
@ -206,10 +202,6 @@ Global
|
|||||||
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
@ -3,6 +3,7 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
using DiscordRPC;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
using LibHac.Tools.FsSystem;
|
using LibHac.Tools.FsSystem;
|
||||||
@ -19,11 +20,15 @@ using Ryujinx.Ava.UI.Models;
|
|||||||
using Ryujinx.Ava.UI.Renderer;
|
using Ryujinx.Ava.UI.Renderer;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
|
using Ryujinx.Ava.Utilities;
|
||||||
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.SystemInterop;
|
using Ryujinx.Common.SystemInterop;
|
||||||
|
using Ryujinx.Common.UI;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading;
|
using Ryujinx.Graphics.GAL.Multithreading;
|
||||||
@ -37,11 +42,6 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
|
|||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using Ryujinx.UI.App.Common;
|
|
||||||
using Ryujinx.UI.Common;
|
|
||||||
using Ryujinx.UI.Common.Configuration;
|
|
||||||
using Ryujinx.UI.Common.Helper;
|
|
||||||
using Silk.NET.Vulkan;
|
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
using SPB.Graphics.Vulkan;
|
using SPB.Graphics.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
@ -238,10 +238,10 @@ namespace Ryujinx.Ava
|
|||||||
_lastCursorMoveTime = Stopwatch.GetTimestamp();
|
_lastCursorMoveTime = Stopwatch.GetTimestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
var point = e.GetCurrentPoint(window).Position;
|
Point point = e.GetCurrentPoint(window).Position;
|
||||||
var bounds = RendererHost.EmbeddedWindow.Bounds;
|
Rect bounds = RendererHost.EmbeddedWindow.Bounds;
|
||||||
var windowYOffset = bounds.Y + window.MenuBarHeight;
|
double windowYOffset = bounds.Y + window.MenuBarHeight;
|
||||||
var windowYLimit = (int)window.Bounds.Height - window.StatusBarHeight - 1;
|
double windowYLimit = (int)window.Bounds.Height - window.StatusBarHeight - 1;
|
||||||
|
|
||||||
if (!_viewModel.ShowMenuAndStatusBar)
|
if (!_viewModel.ShowMenuAndStatusBar)
|
||||||
{
|
{
|
||||||
@ -265,10 +265,10 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
if (sender is MainWindow window)
|
if (sender is MainWindow window)
|
||||||
{
|
{
|
||||||
var point = e.GetCurrentPoint(window).Position;
|
Point point = e.GetCurrentPoint(window).Position;
|
||||||
var bounds = RendererHost.EmbeddedWindow.Bounds;
|
Rect bounds = RendererHost.EmbeddedWindow.Bounds;
|
||||||
var windowYOffset = bounds.Y + window.MenuBarHeight;
|
double windowYOffset = bounds.Y + window.MenuBarHeight;
|
||||||
var windowYLimit = (int)window.Bounds.Height - window.StatusBarHeight - 1;
|
double windowYLimit = (int)window.Bounds.Height - window.StatusBarHeight - 1;
|
||||||
|
|
||||||
if (!_viewModel.ShowMenuAndStatusBar)
|
if (!_viewModel.ShowMenuAndStatusBar)
|
||||||
{
|
{
|
||||||
@ -287,19 +287,19 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
|
private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
|
||||||
{
|
{
|
||||||
_renderer.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
|
_renderer.Window?.SetScalingFilter(ConfigurationState.Instance.Graphics.ScalingFilter);
|
||||||
_renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
|
_renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateScalingFilter(object sender, ReactiveEventArgs<ScalingFilter> e)
|
private void UpdateScalingFilter(object sender, ReactiveEventArgs<ScalingFilter> e)
|
||||||
{
|
{
|
||||||
_renderer.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
|
_renderer.Window?.SetScalingFilter(ConfigurationState.Instance.Graphics.ScalingFilter);
|
||||||
_renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
|
_renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateColorSpacePassthrough(object sender, ReactiveEventArgs<bool> e)
|
private void UpdateColorSpacePassthrough(object sender, ReactiveEventArgs<bool> e)
|
||||||
{
|
{
|
||||||
_renderer.Window?.SetColorSpacePassthrough((bool)ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Value);
|
_renderer.Window?.SetColorSpacePassthrough(ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateVSyncMode(object sender, ReactiveEventArgs<VSyncMode> e)
|
public void UpdateVSyncMode(object sender, ReactiveEventArgs<VSyncMode> e)
|
||||||
@ -309,39 +309,21 @@ namespace Ryujinx.Ava
|
|||||||
Device.VSyncMode = e.NewValue;
|
Device.VSyncMode = e.NewValue;
|
||||||
Device.UpdateVSyncInterval();
|
Device.UpdateVSyncInterval();
|
||||||
}
|
}
|
||||||
_renderer.Window?.ChangeVSyncMode((Ryujinx.Graphics.GAL.VSyncMode)e.NewValue);
|
|
||||||
|
|
||||||
_viewModel.ShowCustomVSyncIntervalPicker = (e.NewValue == VSyncMode.Custom);
|
_renderer.Window?.ChangeVSyncMode(e.NewValue);
|
||||||
|
|
||||||
|
_viewModel.UpdateVSyncIntervalPicker();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void VSyncModeToggle()
|
public void VSyncModeToggle()
|
||||||
{
|
{
|
||||||
VSyncMode oldVSyncMode = Device.VSyncMode;
|
VSyncMode oldVSyncMode = Device.VSyncMode;
|
||||||
VSyncMode newVSyncMode = VSyncMode.Switch;
|
|
||||||
bool customVSyncIntervalEnabled = ConfigurationState.Instance.Graphics.EnableCustomVSyncInterval.Value;
|
bool customVSyncIntervalEnabled = ConfigurationState.Instance.Graphics.EnableCustomVSyncInterval.Value;
|
||||||
|
|
||||||
switch (oldVSyncMode)
|
UpdateVSyncMode(this, new ReactiveEventArgs<VSyncMode>(
|
||||||
{
|
oldVSyncMode,
|
||||||
case VSyncMode.Switch:
|
oldVSyncMode.Next(customVSyncIntervalEnabled))
|
||||||
newVSyncMode = VSyncMode.Unbounded;
|
);
|
||||||
break;
|
|
||||||
case VSyncMode.Unbounded:
|
|
||||||
if (customVSyncIntervalEnabled)
|
|
||||||
{
|
|
||||||
newVSyncMode = VSyncMode.Custom;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newVSyncMode = VSyncMode.Switch;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case VSyncMode.Custom:
|
|
||||||
newVSyncMode = VSyncMode.Switch;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateVSyncMode(this, new ReactiveEventArgs<VSyncMode>(oldVSyncMode, newVSyncMode));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCustomVSyncIntervalValue(object sender, ReactiveEventArgs<int> e)
|
private void UpdateCustomVSyncIntervalValue(object sender, ReactiveEventArgs<int> e)
|
||||||
@ -434,7 +416,7 @@ namespace Ryujinx.Ava
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var colorType = e.IsBgra ? SKColorType.Bgra8888 : SKColorType.Rgba8888;
|
SKColorType colorType = e.IsBgra ? SKColorType.Bgra8888 : SKColorType.Rgba8888;
|
||||||
using SKBitmap bitmap = new(new SKImageInfo(e.Width, e.Height, colorType, SKAlphaType.Premul));
|
using SKBitmap bitmap = new(new SKImageInfo(e.Width, e.Height, colorType, SKAlphaType.Premul));
|
||||||
|
|
||||||
Marshal.Copy(e.Data, 0, bitmap.GetPixels(), e.Data.Length);
|
Marshal.Copy(e.Data, 0, bitmap.GetPixels(), e.Data.Length);
|
||||||
@ -447,7 +429,7 @@ namespace Ryujinx.Ava
|
|||||||
float scaleX = e.FlipX ? -1 : 1;
|
float scaleX = e.FlipX ? -1 : 1;
|
||||||
float scaleY = e.FlipY ? -1 : 1;
|
float scaleY = e.FlipY ? -1 : 1;
|
||||||
|
|
||||||
var matrix = SKMatrix.CreateScale(scaleX, scaleY, bitmap.Width / 2f, bitmap.Height / 2f);
|
SKMatrix matrix = SKMatrix.CreateScale(scaleX, scaleY, bitmap.Width / 2f, bitmap.Height / 2f);
|
||||||
|
|
||||||
canvas.SetMatrix(matrix);
|
canvas.SetMatrix(matrix);
|
||||||
canvas.DrawBitmap(bitmap, SKPoint.Empty);
|
canvas.DrawBitmap(bitmap, SKPoint.Empty);
|
||||||
@ -466,8 +448,8 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private static void SaveBitmapAsPng(SKBitmap bitmap, string path)
|
private static void SaveBitmapAsPng(SKBitmap bitmap, string path)
|
||||||
{
|
{
|
||||||
using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
|
using SKData data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
|
||||||
using var stream = File.OpenWrite(path);
|
using FileStream stream = File.OpenWrite(path);
|
||||||
|
|
||||||
data.SaveTo(stream);
|
data.SaveTo(stream);
|
||||||
}
|
}
|
||||||
@ -488,7 +470,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version);
|
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar);
|
||||||
});
|
});
|
||||||
|
|
||||||
_viewModel.SetUiProgressHandlers(Device);
|
_viewModel.SetUiProgressHandlers(Device);
|
||||||
@ -501,6 +483,8 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
_viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
|
_viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
|
||||||
|
|
||||||
|
Rainbow.Enable();
|
||||||
|
|
||||||
MainLoop();
|
MainLoop();
|
||||||
|
|
||||||
Exit();
|
Exit();
|
||||||
@ -524,7 +508,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private void UpdateAntiAliasing(object sender, ReactiveEventArgs<AntiAliasing> e)
|
private void UpdateAntiAliasing(object sender, ReactiveEventArgs<AntiAliasing> e)
|
||||||
{
|
{
|
||||||
_renderer?.Window?.SetAntiAliasing((Graphics.GAL.AntiAliasing)e.NewValue);
|
_renderer?.Window?.SetAntiAliasing(e.NewValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateDockedModeState(object sender, ReactiveEventArgs<bool> e)
|
private void UpdateDockedModeState(object sender, ReactiveEventArgs<bool> e)
|
||||||
@ -532,7 +516,7 @@ namespace Ryujinx.Ava
|
|||||||
Device?.System.ChangeDockedModeState(e.NewValue);
|
Device?.System.ChangeDockedModeState(e.NewValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAudioVolumeState(object sender, ReactiveEventArgs<float> e)
|
public void UpdateAudioVolumeState(object sender, ReactiveEventArgs<float> e)
|
||||||
{
|
{
|
||||||
Device?.SetVolume(e.NewValue);
|
Device?.SetVolume(e.NewValue);
|
||||||
|
|
||||||
@ -575,7 +559,6 @@ namespace Ryujinx.Ava
|
|||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
_isActive = false;
|
_isActive = false;
|
||||||
DiscordIntegrationModule.SwitchToMainState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Exit()
|
private void Exit()
|
||||||
@ -587,6 +570,17 @@ namespace Ryujinx.Ava
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads())
|
||||||
|
{
|
||||||
|
gamepad?.ClearLed();
|
||||||
|
gamepad?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscordIntegrationModule.GuestAppStartedAt = null;
|
||||||
|
|
||||||
|
Rainbow.Disable();
|
||||||
|
Rainbow.Reset();
|
||||||
|
|
||||||
_isStopped = true;
|
_isStopped = true;
|
||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
@ -674,7 +668,9 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
public async Task<bool> LoadGuestApplication(BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
public async Task<bool> LoadGuestApplication(BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
||||||
{
|
{
|
||||||
InitializeSwitchInstance();
|
DiscordIntegrationModule.GuestAppStartedAt = Timestamps.Now;
|
||||||
|
|
||||||
|
InitEmulatedSwitch();
|
||||||
MainWindow.UpdateGraphicsConfig();
|
MainWindow.UpdateGraphicsConfig();
|
||||||
|
|
||||||
SystemVersion firmwareVersion = ContentManager.GetCurrentFirmwareVersion();
|
SystemVersion firmwareVersion = ContentManager.GetCurrentFirmwareVersion();
|
||||||
@ -758,6 +754,8 @@ namespace Ryujinx.Ava
|
|||||||
romFsFiles = Directory.GetFiles(ApplicationPath, "*.romfs");
|
romFsFiles = Directory.GetFiles(ApplicationPath, "*.romfs");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.Notice.Print(LogClass.Application, $"Loading unpacked content archive from '{ApplicationPath}'.");
|
||||||
|
|
||||||
if (romFsFiles.Length > 0)
|
if (romFsFiles.Length > 0)
|
||||||
{
|
{
|
||||||
Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS.");
|
Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS.");
|
||||||
@ -783,6 +781,8 @@ namespace Ryujinx.Ava
|
|||||||
}
|
}
|
||||||
else if (File.Exists(ApplicationPath))
|
else if (File.Exists(ApplicationPath))
|
||||||
{
|
{
|
||||||
|
Logger.Notice.Print(LogClass.Application, $"Loading content archive from '{ApplicationPath}'.");
|
||||||
|
|
||||||
switch (Path.GetExtension(ApplicationPath).ToLowerInvariant())
|
switch (Path.GetExtension(ApplicationPath).ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case ".xci":
|
case ".xci":
|
||||||
@ -860,12 +860,10 @@ namespace Ryujinx.Ava
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationMetadata appMeta = ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
|
ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
|
||||||
appMetadata => appMetadata.UpdatePreGame()
|
appMetadata => appMetadata.UpdatePreGame()
|
||||||
);
|
);
|
||||||
|
|
||||||
DiscordIntegrationModule.SwitchToPlayingState(appMeta, Device.Processes.ActiveApplication);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -874,7 +872,7 @@ namespace Ryujinx.Ava
|
|||||||
Device?.System.TogglePauseEmulation(false);
|
Device?.System.TogglePauseEmulation(false);
|
||||||
|
|
||||||
_viewModel.IsPaused = false;
|
_viewModel.IsPaused = false;
|
||||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version);
|
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar);
|
||||||
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
|
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,26 +881,30 @@ namespace Ryujinx.Ava
|
|||||||
Device?.System.TogglePauseEmulation(true);
|
Device?.System.TogglePauseEmulation(true);
|
||||||
|
|
||||||
_viewModel.IsPaused = true;
|
_viewModel.IsPaused = true;
|
||||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, LocaleManager.Instance[LocaleKeys.Paused]);
|
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowTitleBar, LocaleManager.Instance[LocaleKeys.Paused]);
|
||||||
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
|
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeSwitchInstance()
|
private void InitEmulatedSwitch()
|
||||||
{
|
{
|
||||||
// Initialize KeySet.
|
// Initialize KeySet.
|
||||||
VirtualFileSystem.ReloadKeySet();
|
VirtualFileSystem.ReloadKeySet();
|
||||||
|
|
||||||
// Initialize Renderer.
|
// Initialize Renderer.
|
||||||
IRenderer renderer = ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.OpenGl
|
GraphicsBackend backend = TitleIDs.SelectGraphicsBackend(ApplicationId.ToString("X16"), ConfigurationState.Instance.Graphics.GraphicsBackend);
|
||||||
? new OpenGLRenderer()
|
|
||||||
: VulkanRenderer.Create(
|
IRenderer renderer = backend switch
|
||||||
|
{
|
||||||
|
GraphicsBackend.Vulkan => VulkanRenderer.Create(
|
||||||
ConfigurationState.Instance.Graphics.PreferredGpu,
|
ConfigurationState.Instance.Graphics.PreferredGpu,
|
||||||
(RendererHost.EmbeddedWindow as EmbeddedWindowVulkan)!.CreateSurface,
|
(RendererHost.EmbeddedWindow as EmbeddedWindowVulkan)!.CreateSurface,
|
||||||
VulkanHelper.GetRequiredInstanceExtensions);
|
VulkanHelper.GetRequiredInstanceExtensions),
|
||||||
|
_ => new OpenGLRenderer()
|
||||||
|
};
|
||||||
|
|
||||||
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
||||||
|
|
||||||
var isGALThreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
bool isGALThreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
||||||
if (isGALThreaded)
|
if (isGALThreaded)
|
||||||
{
|
{
|
||||||
renderer = new ThreadedRenderer(renderer);
|
renderer = new ThreadedRenderer(renderer);
|
||||||
@ -911,9 +913,9 @@ namespace Ryujinx.Ava
|
|||||||
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALThreaded}");
|
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALThreaded}");
|
||||||
|
|
||||||
// Initialize Configuration.
|
// Initialize Configuration.
|
||||||
var memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value;
|
MemoryConfiguration memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value;
|
||||||
|
|
||||||
Device = new HLE.Switch(new HLEConfiguration(
|
Device = new Switch(new HLEConfiguration(
|
||||||
VirtualFileSystem,
|
VirtualFileSystem,
|
||||||
_viewModel.LibHacHorizonManager,
|
_viewModel.LibHacHorizonManager,
|
||||||
ContentManager,
|
ContentManager,
|
||||||
@ -931,7 +933,9 @@ namespace Ryujinx.Ava
|
|||||||
ConfigurationState.Instance.System.EnableInternetAccess,
|
ConfigurationState.Instance.System.EnableInternetAccess,
|
||||||
ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||||
ConfigurationState.Instance.System.FsGlobalAccessLogMode,
|
ConfigurationState.Instance.System.FsGlobalAccessLogMode,
|
||||||
ConfigurationState.Instance.System.SystemTimeOffset,
|
ConfigurationState.Instance.System.MatchSystemTime
|
||||||
|
? 0
|
||||||
|
: ConfigurationState.Instance.System.SystemTimeOffset,
|
||||||
ConfigurationState.Instance.System.TimeZone,
|
ConfigurationState.Instance.System.TimeZone,
|
||||||
ConfigurationState.Instance.System.MemoryManagerMode,
|
ConfigurationState.Instance.System.MemoryManagerMode,
|
||||||
ConfigurationState.Instance.System.IgnoreMissingServices,
|
ConfigurationState.Instance.System.IgnoreMissingServices,
|
||||||
@ -942,19 +946,20 @@ namespace Ryujinx.Ava
|
|||||||
ConfigurationState.Instance.Multiplayer.Mode,
|
ConfigurationState.Instance.Multiplayer.Mode,
|
||||||
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
||||||
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
||||||
ConfigurationState.Instance.Multiplayer.LdnServer,
|
ConfigurationState.Instance.Multiplayer.GetLdnServer(),
|
||||||
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value));
|
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
|
||||||
|
ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IHardwareDeviceDriver InitializeAudio()
|
private static IHardwareDeviceDriver InitializeAudio()
|
||||||
{
|
{
|
||||||
var availableBackends = new List<AudioBackend>
|
List<AudioBackend> availableBackends =
|
||||||
{
|
[
|
||||||
AudioBackend.SDL2,
|
AudioBackend.SDL2,
|
||||||
AudioBackend.SoundIo,
|
AudioBackend.SoundIo,
|
||||||
AudioBackend.OpenAl,
|
AudioBackend.OpenAl,
|
||||||
AudioBackend.Dummy,
|
AudioBackend.Dummy
|
||||||
};
|
];
|
||||||
|
|
||||||
AudioBackend preferredBackend = ConfigurationState.Instance.System.AudioBackend.Value;
|
AudioBackend preferredBackend = ConfigurationState.Instance.System.AudioBackend.Value;
|
||||||
|
|
||||||
@ -1031,9 +1036,10 @@ namespace Ryujinx.Ava
|
|||||||
if (_viewModel.StartGamesInFullscreen)
|
if (_viewModel.StartGamesInFullscreen)
|
||||||
{
|
{
|
||||||
_viewModel.WindowState = WindowState.FullScreen;
|
_viewModel.WindowState = WindowState.FullScreen;
|
||||||
|
_viewModel.Window.TitleBar.ExtendsContentIntoTitleBar = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_viewModel.WindowState is WindowState.FullScreen)
|
if (_viewModel.WindowState is WindowState.FullScreen || _viewModel.StartGamesWithoutUI)
|
||||||
{
|
{
|
||||||
_viewModel.ShowMenuAndStatusBar = false;
|
_viewModel.ShowMenuAndStatusBar = false;
|
||||||
}
|
}
|
||||||
@ -1047,10 +1053,10 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
||||||
|
|
||||||
_renderer?.Window?.SetAntiAliasing((Graphics.GAL.AntiAliasing)ConfigurationState.Instance.Graphics.AntiAliasing.Value);
|
_renderer?.Window?.SetAntiAliasing(ConfigurationState.Instance.Graphics.AntiAliasing);
|
||||||
_renderer?.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
|
_renderer?.Window?.SetScalingFilter(ConfigurationState.Instance.Graphics.ScalingFilter);
|
||||||
_renderer?.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
|
_renderer?.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel);
|
||||||
_renderer?.Window?.SetColorSpacePassthrough(ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Value);
|
_renderer?.Window?.SetColorSpacePassthrough(ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough);
|
||||||
|
|
||||||
Width = (int)RendererHost.Bounds.Width;
|
Width = (int)RendererHost.Bounds.Width;
|
||||||
Height = (int)RendererHost.Bounds.Height;
|
Height = (int)RendererHost.Bounds.Height;
|
||||||
@ -1064,7 +1070,7 @@ namespace Ryujinx.Ava
|
|||||||
Device.Gpu.SetGpuThread();
|
Device.Gpu.SetGpuThread();
|
||||||
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
||||||
|
|
||||||
_renderer.Window.ChangeVSyncMode((Ryujinx.Graphics.GAL.VSyncMode)Device.VSyncMode);
|
_renderer.Window.ChangeVSyncMode(Device.VSyncMode);
|
||||||
|
|
||||||
while (_isActive)
|
while (_isActive)
|
||||||
{
|
{
|
||||||
@ -1111,7 +1117,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
public void InitStatus()
|
public void InitStatus()
|
||||||
{
|
{
|
||||||
_viewModel.BackendText = ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch
|
_viewModel.BackendText = RendererHost.Backend switch
|
||||||
{
|
{
|
||||||
GraphicsBackend.Vulkan => "Vulkan",
|
GraphicsBackend.Vulkan => "Vulkan",
|
||||||
GraphicsBackend.OpenGl => "OpenGL",
|
GraphicsBackend.OpenGl => "OpenGL",
|
||||||
@ -1139,8 +1145,8 @@ namespace Ryujinx.Ava
|
|||||||
LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%",
|
LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%",
|
||||||
dockedMode,
|
dockedMode,
|
||||||
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
|
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
|
||||||
$"{Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
Device.Statistics.FormatGameFrameRate(),
|
||||||
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
|
Device.Statistics.FormatFifoPercent(),
|
||||||
_displayCount));
|
_displayCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,6 @@ using Ryujinx.Common.Logging;
|
|||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading;
|
using Ryujinx.Graphics.GAL.Multithreading;
|
||||||
using Ryujinx.Graphics.Metal;
|
|
||||||
using Ryujinx.Graphics.OpenGL;
|
using Ryujinx.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.Vulkan;
|
using Ryujinx.Graphics.Vulkan;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
@ -310,11 +309,6 @@ namespace Ryujinx.Headless
|
|||||||
preferredGpuId);
|
preferredGpuId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.GraphicsBackend == GraphicsBackend.Metal && window is MetalWindow metalWindow && OperatingSystem.IsMacOS())
|
|
||||||
{
|
|
||||||
return new MetalRenderer(metalWindow.GetLayer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new OpenGLRenderer();
|
return new OpenGLRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
using CommandLine;
|
using CommandLine;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using LibHac.Tools.FsSystem;
|
using Ryujinx.Ava;
|
||||||
using Ryujinx.Audio.Backends.SDL2;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
|
||||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
|
||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Logging.Targets;
|
using Ryujinx.Common.Logging.Targets;
|
||||||
@ -15,14 +13,9 @@ using Ryujinx.Common.SystemInterop;
|
|||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading;
|
|
||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.Graphics.Gpu.Shader;
|
using Ryujinx.Graphics.Gpu.Shader;
|
||||||
using Ryujinx.Graphics.OpenGL;
|
|
||||||
using Ryujinx.Graphics.Vulkan;
|
|
||||||
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
||||||
using Ryujinx.Headless.SDL2.OpenGL;
|
|
||||||
using Ryujinx.Headless.SDL2.Vulkan;
|
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
@ -31,22 +24,16 @@ using Ryujinx.Input;
|
|||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using Ryujinx.Input.SDL2;
|
using Ryujinx.Input.SDL2;
|
||||||
using Ryujinx.SDL2.Common;
|
using Ryujinx.SDL2.Common;
|
||||||
using Silk.NET.Vulkan;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Json;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
|
||||||
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
|
||||||
using Key = Ryujinx.Common.Configuration.Hid.Key;
|
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
class Program
|
public partial class HeadlessRyujinx
|
||||||
{
|
{
|
||||||
public static string Version { get; private set; }
|
|
||||||
|
|
||||||
private static VirtualFileSystem _virtualFileSystem;
|
private static VirtualFileSystem _virtualFileSystem;
|
||||||
private static ContentManager _contentManager;
|
private static ContentManager _contentManager;
|
||||||
private static AccountManager _accountManager;
|
private static AccountManager _accountManager;
|
||||||
@ -56,20 +43,18 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
private static Switch _emulationContext;
|
private static Switch _emulationContext;
|
||||||
private static WindowBase _window;
|
private static WindowBase _window;
|
||||||
private static WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
|
private static WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
|
||||||
private static List<InputConfig> _inputConfiguration;
|
private static List<InputConfig> _inputConfiguration = [];
|
||||||
private static bool _enableKeyboard;
|
private static bool _enableKeyboard;
|
||||||
private static bool _enableMouse;
|
private static bool _enableMouse;
|
||||||
|
|
||||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
static void Main(string[] args)
|
public static void Entrypoint(string[] args)
|
||||||
{
|
{
|
||||||
Version = ReleaseInformation.Version;
|
|
||||||
|
|
||||||
// Make process DPI aware for proper window sizing on high-res screens.
|
// Make process DPI aware for proper window sizing on high-res screens.
|
||||||
ForceDpiAware.Windows();
|
ForceDpiAware.Windows();
|
||||||
|
|
||||||
Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
|
Console.Title = $"HeadlessRyujinx Console {Program.Version}";
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
|
if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
|
||||||
{
|
{
|
||||||
@ -97,7 +82,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
}
|
}
|
||||||
|
|
||||||
Parser.Default.ParseArguments<Options>(args)
|
Parser.Default.ParseArguments<Options>(args)
|
||||||
.WithParsed(Load)
|
.WithParsed(options => Load(args, options))
|
||||||
.WithNotParsed(errors =>
|
.WithNotParsed(errors =>
|
||||||
{
|
{
|
||||||
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");
|
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");
|
||||||
@ -106,238 +91,85 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
public static void ReloadConfig(string customConfigPath = null)
|
||||||
{
|
{
|
||||||
if (inputId == null)
|
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||||
{
|
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||||
if (index == PlayerIndex.Player1)
|
|
||||||
{
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"{index} not configured, defaulting to default keyboard.");
|
|
||||||
|
|
||||||
// Default to keyboard
|
string configurationPath = null;
|
||||||
inputId = "0";
|
|
||||||
|
// Now load the configuration as the other subsystems are now registered
|
||||||
|
if (customConfigPath != null && File.Exists(customConfigPath))
|
||||||
|
{
|
||||||
|
configurationPath = customConfigPath;
|
||||||
|
}
|
||||||
|
else if (File.Exists(localConfigurationPath))
|
||||||
|
{
|
||||||
|
configurationPath = localConfigurationPath;
|
||||||
|
}
|
||||||
|
else if (File.Exists(appDataConfigurationPath))
|
||||||
|
{
|
||||||
|
configurationPath = appDataConfigurationPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configurationPath == null)
|
||||||
|
{
|
||||||
|
// No configuration, we load the default values and save it to disk
|
||||||
|
configurationPath = appDataConfigurationPath;
|
||||||
|
Logger.Notice.Print(LogClass.Application, $"No configuration file found. Saving default configuration to: {configurationPath}");
|
||||||
|
|
||||||
|
ConfigurationState.Instance.LoadDefault();
|
||||||
|
ConfigurationState.Instance.ToFileFormat().SaveConfig(configurationPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger.Info?.Print(LogClass.Application, $"{index} not configured");
|
Logger.Notice.Print(LogClass.Application, $"Loading configuration from: {configurationPath}");
|
||||||
|
|
||||||
return null;
|
if (ConfigurationFileFormat.TryLoad(configurationPath, out ConfigurationFileFormat configurationFileFormat))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(inputId);
|
|
||||||
|
|
||||||
bool isKeyboard = true;
|
|
||||||
|
|
||||||
if (gamepad == null)
|
|
||||||
{
|
{
|
||||||
gamepad = _inputManager.GamepadDriver.GetGamepad(inputId);
|
ConfigurationState.Instance.Load(configurationFileFormat, configurationPath);
|
||||||
isKeyboard = false;
|
|
||||||
|
|
||||||
if (gamepad == null)
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, $"{index} gamepad not found (\"{inputId}\")");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string gamepadName = gamepad.Name;
|
|
||||||
|
|
||||||
gamepad.Dispose();
|
|
||||||
|
|
||||||
InputConfig config;
|
|
||||||
|
|
||||||
if (inputProfileName == null || inputProfileName.Equals("default"))
|
|
||||||
{
|
|
||||||
if (isKeyboard)
|
|
||||||
{
|
|
||||||
config = new StandardKeyboardInputConfig
|
|
||||||
{
|
|
||||||
Version = InputConfig.CurrentVersion,
|
|
||||||
Backend = InputBackendType.WindowKeyboard,
|
|
||||||
Id = null,
|
|
||||||
ControllerType = ControllerType.JoyconPair,
|
|
||||||
LeftJoycon = new LeftJoyconCommonConfig<Key>
|
|
||||||
{
|
|
||||||
DpadUp = Key.Up,
|
|
||||||
DpadDown = Key.Down,
|
|
||||||
DpadLeft = Key.Left,
|
|
||||||
DpadRight = Key.Right,
|
|
||||||
ButtonMinus = Key.Minus,
|
|
||||||
ButtonL = Key.E,
|
|
||||||
ButtonZl = Key.Q,
|
|
||||||
ButtonSl = Key.Unbound,
|
|
||||||
ButtonSr = Key.Unbound,
|
|
||||||
},
|
|
||||||
|
|
||||||
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
|
||||||
{
|
|
||||||
StickUp = Key.W,
|
|
||||||
StickDown = Key.S,
|
|
||||||
StickLeft = Key.A,
|
|
||||||
StickRight = Key.D,
|
|
||||||
StickButton = Key.F,
|
|
||||||
},
|
|
||||||
|
|
||||||
RightJoycon = new RightJoyconCommonConfig<Key>
|
|
||||||
{
|
|
||||||
ButtonA = Key.Z,
|
|
||||||
ButtonB = Key.X,
|
|
||||||
ButtonX = Key.C,
|
|
||||||
ButtonY = Key.V,
|
|
||||||
ButtonPlus = Key.Plus,
|
|
||||||
ButtonR = Key.U,
|
|
||||||
ButtonZr = Key.O,
|
|
||||||
ButtonSl = Key.Unbound,
|
|
||||||
ButtonSr = Key.Unbound,
|
|
||||||
},
|
|
||||||
|
|
||||||
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
|
||||||
{
|
|
||||||
StickUp = Key.I,
|
|
||||||
StickDown = Key.K,
|
|
||||||
StickLeft = Key.J,
|
|
||||||
StickRight = Key.L,
|
|
||||||
StickButton = Key.H,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool isNintendoStyle = gamepadName.Contains("Nintendo");
|
Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location: {configurationPath}");
|
||||||
|
|
||||||
config = new StandardControllerInputConfig
|
ConfigurationState.Instance.LoadDefault();
|
||||||
{
|
|
||||||
Version = InputConfig.CurrentVersion,
|
|
||||||
Backend = InputBackendType.GamepadSDL2,
|
|
||||||
Id = null,
|
|
||||||
ControllerType = ControllerType.JoyconPair,
|
|
||||||
DeadzoneLeft = 0.1f,
|
|
||||||
DeadzoneRight = 0.1f,
|
|
||||||
RangeLeft = 1.0f,
|
|
||||||
RangeRight = 1.0f,
|
|
||||||
TriggerThreshold = 0.5f,
|
|
||||||
LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
|
|
||||||
{
|
|
||||||
DpadUp = ConfigGamepadInputId.DpadUp,
|
|
||||||
DpadDown = ConfigGamepadInputId.DpadDown,
|
|
||||||
DpadLeft = ConfigGamepadInputId.DpadLeft,
|
|
||||||
DpadRight = ConfigGamepadInputId.DpadRight,
|
|
||||||
ButtonMinus = ConfigGamepadInputId.Minus,
|
|
||||||
ButtonL = ConfigGamepadInputId.LeftShoulder,
|
|
||||||
ButtonZl = ConfigGamepadInputId.LeftTrigger,
|
|
||||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
|
||||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
|
||||||
},
|
|
||||||
|
|
||||||
LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
|
||||||
{
|
|
||||||
Joystick = ConfigStickInputId.Left,
|
|
||||||
StickButton = ConfigGamepadInputId.LeftStick,
|
|
||||||
InvertStickX = false,
|
|
||||||
InvertStickY = false,
|
|
||||||
Rotate90CW = false,
|
|
||||||
},
|
|
||||||
|
|
||||||
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
|
||||||
{
|
|
||||||
ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
|
|
||||||
ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
|
|
||||||
ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
|
|
||||||
ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
|
|
||||||
ButtonPlus = ConfigGamepadInputId.Plus,
|
|
||||||
ButtonR = ConfigGamepadInputId.RightShoulder,
|
|
||||||
ButtonZr = ConfigGamepadInputId.RightTrigger,
|
|
||||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
|
||||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
|
||||||
},
|
|
||||||
|
|
||||||
RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
|
||||||
{
|
|
||||||
Joystick = ConfigStickInputId.Right,
|
|
||||||
StickButton = ConfigGamepadInputId.RightStick,
|
|
||||||
InvertStickX = false,
|
|
||||||
InvertStickY = false,
|
|
||||||
Rotate90CW = false,
|
|
||||||
},
|
|
||||||
|
|
||||||
Motion = new StandardMotionConfigController
|
|
||||||
{
|
|
||||||
MotionBackend = MotionInputBackendType.GamepadDriver,
|
|
||||||
EnableMotion = true,
|
|
||||||
Sensitivity = 100,
|
|
||||||
GyroDeadzone = 1,
|
|
||||||
},
|
|
||||||
Rumble = new RumbleConfigController
|
|
||||||
{
|
|
||||||
StrongRumble = 1f,
|
|
||||||
WeakRumble = 1f,
|
|
||||||
EnableRumble = false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
string profileBasePath;
|
|
||||||
|
|
||||||
if (isKeyboard)
|
|
||||||
{
|
|
||||||
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "keyboard");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "controller");
|
|
||||||
}
|
|
||||||
|
|
||||||
string path = Path.Combine(profileBasePath, inputProfileName + ".json");
|
|
||||||
|
|
||||||
if (!File.Exists(path))
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" not found for \"{inputId}\"");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
|
|
||||||
}
|
|
||||||
catch (JsonException)
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" parsing failed for \"{inputId}\"");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Id = inputId;
|
static void Load(string[] originalArgs, Options option)
|
||||||
config.PlayerIndex = index;
|
|
||||||
|
|
||||||
string inputTypeName = isKeyboard ? "Keyboard" : "Gamepad";
|
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} configured with {inputTypeName} \"{config.Id}\"");
|
|
||||||
|
|
||||||
// If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0.
|
|
||||||
if (config is StandardControllerInputConfig controllerConfig)
|
|
||||||
{
|
{
|
||||||
if (controllerConfig.RangeLeft <= 0.0f && controllerConfig.RangeRight <= 0.0f)
|
Initialize();
|
||||||
{
|
|
||||||
controllerConfig.RangeLeft = 1.0f;
|
|
||||||
controllerConfig.RangeRight = 1.0f;
|
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} stick range reset. Save the profile now to update your configuration");
|
bool useLastUsedProfile = false;
|
||||||
}
|
|
||||||
|
if (option.InheritConfig)
|
||||||
|
{
|
||||||
|
option.InheritMainConfig(originalArgs, ConfigurationState.Instance, out useLastUsedProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Load(Options option)
|
|
||||||
{
|
|
||||||
AppDataManager.Initialize(option.BaseDataDir);
|
AppDataManager.Initialize(option.BaseDataDir);
|
||||||
|
|
||||||
|
if (useLastUsedProfile && AccountSaveDataManager.GetLastUsedUser().TryGet(out UserProfile profile))
|
||||||
|
option.UserProfile = profile.Name;
|
||||||
|
|
||||||
|
// Check if keys exists.
|
||||||
|
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
||||||
|
{
|
||||||
|
if (!(AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "prod.keys"))))
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, "Keys not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReloadConfig();
|
||||||
|
|
||||||
|
if (option.InheritConfig)
|
||||||
|
{
|
||||||
|
option.InheritMainConfigInput(originalArgs, ConfigurationState.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
_virtualFileSystem = VirtualFileSystem.CreateInstance();
|
_virtualFileSystem = VirtualFileSystem.CreateInstance();
|
||||||
_libHacHorizonManager = new LibHacHorizonManager();
|
_libHacHorizonManager = new LibHacHorizonManager();
|
||||||
|
|
||||||
@ -352,7 +184,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
|
|
||||||
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
|
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
|
||||||
|
|
||||||
GraphicsConfig.EnableShaderCache = true;
|
GraphicsConfig.EnableShaderCache = !option.DisableShaderCache;
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS())
|
if (OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
@ -363,15 +195,13 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IGamepad gamepad;
|
|
||||||
|
|
||||||
if (option.ListInputIds)
|
if (option.ListInputIds)
|
||||||
{
|
{
|
||||||
Logger.Info?.Print(LogClass.Application, "Input Ids:");
|
Logger.Info?.Print(LogClass.Application, "Input Ids:");
|
||||||
|
|
||||||
foreach (string id in _inputManager.KeyboardDriver.GamepadsIds)
|
foreach (string id in _inputManager.KeyboardDriver.GamepadsIds)
|
||||||
{
|
{
|
||||||
gamepad = _inputManager.KeyboardDriver.GetGamepad(id);
|
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(id);
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
||||||
|
|
||||||
@ -380,7 +210,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
|
|
||||||
foreach (string id in _inputManager.GamepadDriver.GamepadsIds)
|
foreach (string id in _inputManager.GamepadDriver.GamepadsIds)
|
||||||
{
|
{
|
||||||
gamepad = _inputManager.GamepadDriver.GetGamepad(id);
|
IGamepad gamepad = _inputManager.GamepadDriver.GetGamepad(id);
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
||||||
|
|
||||||
@ -397,20 +227,10 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_inputConfiguration = new List<InputConfig>();
|
_inputConfiguration ??= [];
|
||||||
_enableKeyboard = option.EnableKeyboard;
|
_enableKeyboard = option.EnableKeyboard;
|
||||||
_enableMouse = option.EnableMouse;
|
_enableMouse = option.EnableMouse;
|
||||||
|
|
||||||
static void LoadPlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
|
||||||
{
|
|
||||||
InputConfig inputConfig = HandlePlayerConfiguration(inputProfileName, inputId, index);
|
|
||||||
|
|
||||||
if (inputConfig != null)
|
|
||||||
{
|
|
||||||
_inputConfiguration.Add(inputConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
||||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||||
LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3);
|
LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3);
|
||||||
@ -431,7 +251,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub);
|
Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub);
|
||||||
Logger.SetEnable(LogLevel.Info, !option.LoggingDisableInfo);
|
Logger.SetEnable(LogLevel.Info, !option.LoggingDisableInfo);
|
||||||
Logger.SetEnable(LogLevel.Warning, !option.LoggingDisableWarning);
|
Logger.SetEnable(LogLevel.Warning, !option.LoggingDisableWarning);
|
||||||
Logger.SetEnable(LogLevel.Error, option.LoggingEnableError);
|
Logger.SetEnable(LogLevel.Error, !option.LoggingDisableError);
|
||||||
Logger.SetEnable(LogLevel.Trace, option.LoggingEnableTrace);
|
Logger.SetEnable(LogLevel.Trace, option.LoggingEnableTrace);
|
||||||
Logger.SetEnable(LogLevel.Guest, !option.LoggingDisableGuest);
|
Logger.SetEnable(LogLevel.Guest, !option.LoggingDisableGuest);
|
||||||
Logger.SetEnable(LogLevel.AccessLog, option.LoggingEnableFsAccessLog);
|
Logger.SetEnable(LogLevel.AccessLog, option.LoggingEnableFsAccessLog);
|
||||||
@ -469,6 +289,10 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
|
|
||||||
DriverUtilities.InitDriverConfig(option.BackendThreading == BackendThreading.Off);
|
DriverUtilities.InitDriverConfig(option.BackendThreading == BackendThreading.Off);
|
||||||
|
|
||||||
|
if (_inputConfiguration.OfType<StandardControllerInputConfig>()
|
||||||
|
.Any(ic => ic?.Led?.UseRainbow ?? false))
|
||||||
|
Rainbow.Enable();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
LoadApplication(option);
|
LoadApplication(option);
|
||||||
@ -481,7 +305,28 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
_userChannelPersistence.ShouldRestart = false;
|
_userChannelPersistence.ShouldRestart = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
_inputManager.Dispose();
|
_inputManager.Dispose();
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
void LoadPlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
||||||
|
{
|
||||||
|
if (index == PlayerIndex.Handheld && _inputConfiguration.Count > 0)
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Configuration, "Skipping handheld configuration as there are already other players configured.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputConfig inputConfig = option.InheritedInputConfigs[index] ?? HandlePlayerConfiguration(inputProfileName, inputId, index);
|
||||||
|
|
||||||
|
if (inputConfig != null)
|
||||||
|
{
|
||||||
|
_inputConfiguration.Add(inputConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetupProgressHandler()
|
private static void SetupProgressHandler()
|
||||||
@ -500,96 +345,21 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
{
|
{
|
||||||
string label = state switch
|
string label = state switch
|
||||||
{
|
{
|
||||||
LoadState => $"PTC : {current}/{total}",
|
LoadState => "PTC",
|
||||||
ShaderCacheState => $"Shaders : {current}/{total}",
|
ShaderCacheState => "Shaders",
|
||||||
_ => throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}"),
|
_ => throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}")
|
||||||
};
|
};
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, label);
|
Logger.Info?.Print(LogClass.Application, $"{label} : {current}/{total}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static WindowBase CreateWindow(Options options)
|
private static WindowBase CreateWindow(Options options)
|
||||||
{
|
{
|
||||||
return options.GraphicsBackend == GraphicsBackend.Vulkan
|
return options.GraphicsBackend switch
|
||||||
? new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet)
|
|
||||||
: new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IRenderer CreateRenderer(Options options, WindowBase window)
|
|
||||||
{
|
{
|
||||||
if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
|
GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet),
|
||||||
{
|
_ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet)
|
||||||
string preferredGpuId = string.Empty;
|
};
|
||||||
Vk api = Vk.GetApi();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(options.PreferredGPUVendor))
|
|
||||||
{
|
|
||||||
string preferredGpuVendor = options.PreferredGPUVendor.ToLowerInvariant();
|
|
||||||
var devices = VulkanRenderer.GetPhysicalDevices(api);
|
|
||||||
|
|
||||||
foreach (var device in devices)
|
|
||||||
{
|
|
||||||
if (device.Vendor.ToLowerInvariant() == preferredGpuVendor)
|
|
||||||
{
|
|
||||||
preferredGpuId = device.Id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new VulkanRenderer(
|
|
||||||
api,
|
|
||||||
(instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))),
|
|
||||||
vulkanWindow.GetRequiredInstanceExtensions,
|
|
||||||
preferredGpuId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new OpenGLRenderer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
|
|
||||||
{
|
|
||||||
BackendThreading threadingMode = options.BackendThreading;
|
|
||||||
|
|
||||||
bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
|
||||||
|
|
||||||
if (threadedGAL)
|
|
||||||
{
|
|
||||||
renderer = new ThreadedRenderer(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
HLEConfiguration configuration = new(_virtualFileSystem,
|
|
||||||
_libHacHorizonManager,
|
|
||||||
_contentManager,
|
|
||||||
_accountManager,
|
|
||||||
_userChannelPersistence,
|
|
||||||
renderer,
|
|
||||||
new SDL2HardwareDeviceDriver(),
|
|
||||||
options.DramSize,
|
|
||||||
window,
|
|
||||||
options.SystemLanguage,
|
|
||||||
options.SystemRegion,
|
|
||||||
options.VSyncMode,
|
|
||||||
!options.DisableDockedMode,
|
|
||||||
!options.DisablePTC,
|
|
||||||
options.EnableInternetAccess,
|
|
||||||
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
|
||||||
options.FsGlobalAccessLogMode,
|
|
||||||
options.SystemTimeOffset,
|
|
||||||
options.SystemTimeZone,
|
|
||||||
options.MemoryManagerMode,
|
|
||||||
options.IgnoreMissingServices,
|
|
||||||
options.AspectRatio,
|
|
||||||
options.AudioVolume,
|
|
||||||
options.UseHypervisor ?? true,
|
|
||||||
options.MultiplayerLanInterfaceId,
|
|
||||||
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
|
||||||
false,
|
|
||||||
string.Empty,
|
|
||||||
string.Empty,
|
|
||||||
options.CustomVSyncInterval);
|
|
||||||
|
|
||||||
return new Switch(configuration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ExecutionEntrypoint()
|
private static void ExecutionEntrypoint()
|
||||||
|
@ -49,6 +49,9 @@
|
|||||||
<PackageReference Include="Avalonia.Svg.Skia" />
|
<PackageReference Include="Avalonia.Svg.Skia" />
|
||||||
<PackageReference Include="DynamicData" />
|
<PackageReference Include="DynamicData" />
|
||||||
<PackageReference Include="FluentAvaloniaUI" />
|
<PackageReference Include="FluentAvaloniaUI" />
|
||||||
|
<PackageReference Include="CommandLineParser" />
|
||||||
|
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||||
|
<PackageReference Include="DiscordRichPresence" />
|
||||||
<PackageReference Include="Projektanker.Icons.Avalonia" />
|
<PackageReference Include="Projektanker.Icons.Avalonia" />
|
||||||
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" />
|
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" />
|
||||||
<PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" />
|
<PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" />
|
||||||
@ -56,6 +59,8 @@
|
|||||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
||||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
|
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
|
||||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
|
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
|
||||||
|
<PackageReference Include="securifybv.ShellLink" />
|
||||||
|
<PackageReference Include="Sep" />
|
||||||
<PackageReference Include="Silk.NET.Vulkan" />
|
<PackageReference Include="Silk.NET.Vulkan" />
|
||||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" />
|
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" />
|
||||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" />
|
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" />
|
||||||
@ -75,7 +80,6 @@
|
|||||||
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
|
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
<ProjectReference Include="..\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Media;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Renderer
|
namespace Ryujinx.Ava.UI.Renderer
|
||||||
{
|
{
|
||||||
public partial class RendererHost : UserControl, IDisposable
|
public class RendererHost : UserControl, IDisposable
|
||||||
{
|
{
|
||||||
public readonly EmbeddedWindow EmbeddedWindow;
|
public readonly EmbeddedWindow EmbeddedWindow;
|
||||||
|
|
||||||
@ -15,20 +18,54 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||||||
|
|
||||||
public RendererHost()
|
public RendererHost()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
Focusable = true;
|
||||||
|
FlowDirection = FlowDirection.LeftToRight;
|
||||||
|
|
||||||
if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.OpenGl)
|
EmbeddedWindow = ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch
|
||||||
{
|
{
|
||||||
EmbeddedWindow = new EmbeddedWindowOpenGL();
|
GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(),
|
||||||
}
|
GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(),
|
||||||
else
|
_ => throw new NotSupportedException()
|
||||||
{
|
};
|
||||||
EmbeddedWindow = new EmbeddedWindowVulkan();
|
|
||||||
}
|
|
||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GraphicsBackend Backend =>
|
||||||
|
EmbeddedWindow switch
|
||||||
|
{
|
||||||
|
EmbeddedWindowVulkan => GraphicsBackend.Vulkan,
|
||||||
|
EmbeddedWindowOpenGL => GraphicsBackend.OpenGl,
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
|
||||||
|
public RendererHost(string titleId)
|
||||||
|
{
|
||||||
|
Focusable = true;
|
||||||
|
FlowDirection = FlowDirection.LeftToRight;
|
||||||
|
|
||||||
|
EmbeddedWindow =
|
||||||
|
#pragma warning disable CS8509
|
||||||
|
TitleIDs.SelectGraphicsBackend(titleId, ConfigurationState.Instance.Graphics.GraphicsBackend) switch
|
||||||
|
#pragma warning restore CS8509
|
||||||
|
{
|
||||||
|
GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(),
|
||||||
|
GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(),
|
||||||
|
};
|
||||||
|
|
||||||
|
string backendText = EmbeddedWindow switch
|
||||||
|
{
|
||||||
|
EmbeddedWindowVulkan => "Vulkan",
|
||||||
|
EmbeddedWindowOpenGL => "OpenGL",
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend ({ConfigurationState.Instance.Graphics.GraphicsBackend.Value}): {backendText}");
|
||||||
|
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated;
|
EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user