mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2024-12-22 13:05:45 +00:00
ava: Cleanup AppHost (#4240)
* ava: Cleanup AppHost This PR cleaned up the AppHost file a bit (adding the infamous extra spaces to improve readability), resorting private vars, remove useless vars, and improve the code here and there, like the AudioBackend check. Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com> * Remove 'renderer" * Revert currentTime * revert if condition Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com>
This commit is contained in:
parent
3e455a90a1
commit
a16854e55a
4 changed files with 189 additions and 250 deletions
|
@ -15,6 +15,8 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||||
{
|
{
|
||||||
private IHardwareDeviceDriver _realDriver;
|
private IHardwareDeviceDriver _realDriver;
|
||||||
|
|
||||||
|
public static bool IsSupported => true;
|
||||||
|
|
||||||
public CompatLayerHardwareDeviceDriver(IHardwareDeviceDriver realDevice)
|
public CompatLayerHardwareDeviceDriver(IHardwareDeviceDriver realDevice)
|
||||||
{
|
{
|
||||||
_realDriver = realDevice;
|
_realDriver = realDevice;
|
||||||
|
|
|
@ -12,6 +12,8 @@ namespace Ryujinx.Audio.Backends.Dummy
|
||||||
private ManualResetEvent _updateRequiredEvent;
|
private ManualResetEvent _updateRequiredEvent;
|
||||||
private ManualResetEvent _pauseEvent;
|
private ManualResetEvent _pauseEvent;
|
||||||
|
|
||||||
|
public static bool IsSupported => true;
|
||||||
|
|
||||||
public DummyHardwareDeviceDriver()
|
public DummyHardwareDeviceDriver()
|
||||||
{
|
{
|
||||||
_updateRequiredEvent = new ManualResetEvent(false);
|
_updateRequiredEvent = new ManualResetEvent(false);
|
||||||
|
|
|
@ -26,6 +26,8 @@ namespace Ryujinx.Audio.Integration
|
||||||
bool SupportsSampleFormat(SampleFormat sampleFormat);
|
bool SupportsSampleFormat(SampleFormat sampleFormat);
|
||||||
bool SupportsChannelCount(uint channelCount);
|
bool SupportsChannelCount(uint channelCount);
|
||||||
|
|
||||||
|
static abstract bool IsSupported { get; }
|
||||||
|
|
||||||
IHardwareDeviceDriver GetRealDeviceDriver()
|
IHardwareDeviceDriver GetRealDeviceDriver()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -41,6 +41,7 @@ using SixLabors.ImageSharp.PixelFormats;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
using SPB.Graphics.Vulkan;
|
using SPB.Graphics.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
@ -57,95 +58,96 @@ namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
internal class AppHost
|
internal class AppHost
|
||||||
{
|
{
|
||||||
private const int CursorHideIdleTime = 8; // Hide Cursor seconds
|
private const int CursorHideIdleTime = 8; // Hide Cursor seconds.
|
||||||
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
|
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
|
||||||
private const int TargetFps = 60;
|
private const int TargetFps = 60;
|
||||||
|
private const float VolumeDelta = 0.05f;
|
||||||
|
|
||||||
private const float VolumeDelta = 0.05f;
|
private static readonly Cursor InvisibleCursor = new(StandardCursorType.None);
|
||||||
|
|
||||||
private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None);
|
private readonly long _ticksPerFrame;
|
||||||
|
|
||||||
private readonly long _ticksPerFrame;
|
|
||||||
private readonly Stopwatch _chrono;
|
private readonly Stopwatch _chrono;
|
||||||
private readonly AccountManager _accountManager;
|
private long _ticks;
|
||||||
|
|
||||||
|
private readonly AccountManager _accountManager;
|
||||||
private readonly UserChannelPersistence _userChannelPersistence;
|
private readonly UserChannelPersistence _userChannelPersistence;
|
||||||
private readonly InputManager _inputManager;
|
private readonly InputManager _inputManager;
|
||||||
|
|
||||||
private readonly MainWindowViewModel _viewModel;
|
private readonly MainWindowViewModel _viewModel;
|
||||||
private readonly IKeyboard _keyboardInterface;
|
private readonly IKeyboard _keyboardInterface;
|
||||||
|
private readonly TopLevel _topLevel;
|
||||||
|
|
||||||
private readonly GraphicsDebugLevel _glLogLevel;
|
private readonly GraphicsDebugLevel _glLogLevel;
|
||||||
|
private float _newVolume;
|
||||||
|
private KeyboardHotkeyState _prevHotkeyState;
|
||||||
|
|
||||||
private bool _hideCursorOnIdle;
|
private bool _hideCursorOnIdle;
|
||||||
|
private long _lastCursorMoveTime;
|
||||||
|
private bool _isCursorInRenderer;
|
||||||
|
|
||||||
private bool _isStopped;
|
private bool _isStopped;
|
||||||
private bool _isActive;
|
private bool _isActive;
|
||||||
private long _lastCursorMoveTime;
|
|
||||||
private float _newVolume;
|
|
||||||
private long _ticks = 0;
|
|
||||||
|
|
||||||
private KeyboardHotkeyState _prevHotkeyState;
|
|
||||||
|
|
||||||
private IRenderer _renderer;
|
|
||||||
private readonly Thread _renderingThread;
|
|
||||||
|
|
||||||
private bool _isMouseInRenderer;
|
|
||||||
private bool _renderingStarted;
|
private bool _renderingStarted;
|
||||||
private bool _dialogShown;
|
|
||||||
|
|
||||||
|
private IRenderer _renderer;
|
||||||
|
private readonly Thread _renderingThread;
|
||||||
|
private readonly CancellationTokenSource _gpuCancellationTokenSource;
|
||||||
private WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
|
private WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
|
||||||
|
|
||||||
private readonly CancellationTokenSource _gpuCancellationTokenSource;
|
private bool _dialogShown;
|
||||||
|
private readonly bool _isFirmwareTitle;
|
||||||
|
|
||||||
|
private readonly object _lockObject = new();
|
||||||
|
|
||||||
public event EventHandler AppExit;
|
public event EventHandler AppExit;
|
||||||
public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
|
public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
|
||||||
|
|
||||||
public RendererHost Renderer { get; }
|
public RendererHost Renderer { get; }
|
||||||
public VirtualFileSystem VirtualFileSystem { get; }
|
public VirtualFileSystem VirtualFileSystem { get; }
|
||||||
public ContentManager ContentManager { get; }
|
public ContentManager ContentManager { get; }
|
||||||
public Switch Device { get; set; }
|
public NpadManager NpadManager { get; }
|
||||||
public NpadManager NpadManager { get; }
|
|
||||||
public TouchScreenManager TouchScreenManager { get; }
|
public TouchScreenManager TouchScreenManager { get; }
|
||||||
|
public Switch Device { get; set; }
|
||||||
|
|
||||||
public int Width { get; private set; }
|
public int Width { get; private set; }
|
||||||
public int Height { get; private set; }
|
public int Height { get; private set; }
|
||||||
public string ApplicationPath { get; private set; }
|
public string ApplicationPath { get; private set; }
|
||||||
|
public bool ScreenshotRequested { get; set; }
|
||||||
|
|
||||||
private bool _isFirmwareTitle;
|
|
||||||
|
|
||||||
public bool ScreenshotRequested { get; set; }
|
|
||||||
|
|
||||||
private object _lockObject = new();
|
|
||||||
private TopLevel _topLevel;
|
|
||||||
|
|
||||||
public AppHost(
|
public AppHost(
|
||||||
RendererHost renderer,
|
RendererHost renderer,
|
||||||
InputManager inputManager,
|
InputManager inputManager,
|
||||||
string applicationPath,
|
string applicationPath,
|
||||||
VirtualFileSystem virtualFileSystem,
|
VirtualFileSystem virtualFileSystem,
|
||||||
ContentManager contentManager,
|
ContentManager contentManager,
|
||||||
AccountManager accountManager,
|
AccountManager accountManager,
|
||||||
UserChannelPersistence userChannelPersistence,
|
UserChannelPersistence userChannelPersistence,
|
||||||
MainWindowViewModel viewmodel,
|
MainWindowViewModel viewmodel,
|
||||||
TopLevel topLevel)
|
TopLevel topLevel)
|
||||||
{
|
{
|
||||||
_viewModel = viewmodel;
|
_viewModel = viewmodel;
|
||||||
_inputManager = inputManager;
|
_inputManager = inputManager;
|
||||||
_accountManager = accountManager;
|
_accountManager = accountManager;
|
||||||
_userChannelPersistence = userChannelPersistence;
|
_userChannelPersistence = userChannelPersistence;
|
||||||
_renderingThread = new Thread(RenderLoop, 1 * 1024 * 1024) { Name = "GUI.RenderThread" };
|
_renderingThread = new Thread(RenderLoop, 1 * 1024 * 1024) { Name = "GUI.RenderThread" };
|
||||||
_hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
|
_hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
|
||||||
_lastCursorMoveTime = Stopwatch.GetTimestamp();
|
_lastCursorMoveTime = Stopwatch.GetTimestamp();
|
||||||
_glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
|
_glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
|
||||||
_topLevel = topLevel;
|
_topLevel = topLevel;
|
||||||
|
|
||||||
_inputManager.SetMouseDriver(new AvaloniaMouseDriver(_topLevel, renderer));
|
_inputManager.SetMouseDriver(new AvaloniaMouseDriver(_topLevel, renderer));
|
||||||
|
|
||||||
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
|
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
|
||||||
|
|
||||||
NpadManager = _inputManager.CreateNpadManager();
|
NpadManager = _inputManager.CreateNpadManager();
|
||||||
TouchScreenManager = _inputManager.CreateTouchScreenManager();
|
TouchScreenManager = _inputManager.CreateTouchScreenManager();
|
||||||
Renderer = renderer;
|
Renderer = renderer;
|
||||||
ApplicationPath = applicationPath;
|
ApplicationPath = applicationPath;
|
||||||
VirtualFileSystem = virtualFileSystem;
|
VirtualFileSystem = virtualFileSystem;
|
||||||
ContentManager = contentManager;
|
ContentManager = contentManager;
|
||||||
|
|
||||||
_chrono = new Stopwatch();
|
_chrono = new Stopwatch();
|
||||||
_ticksPerFrame = Stopwatch.Frequency / TargetFps;
|
_ticksPerFrame = Stopwatch.Frequency / TargetFps;
|
||||||
|
|
||||||
if (ApplicationPath.StartsWith("@SystemContent"))
|
if (ApplicationPath.StartsWith("@SystemContent"))
|
||||||
|
@ -161,9 +163,9 @@ namespace Ryujinx.Ava
|
||||||
_topLevel.PointerMoved += TopLevel_PointerMoved;
|
_topLevel.PointerMoved += TopLevel_PointerMoved;
|
||||||
|
|
||||||
ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState;
|
ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState;
|
||||||
ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState;
|
ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState;
|
||||||
ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState;
|
ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState;
|
||||||
ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState;
|
ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState;
|
||||||
|
|
||||||
_gpuCancellationTokenSource = new CancellationTokenSource();
|
_gpuCancellationTokenSource = new CancellationTokenSource();
|
||||||
}
|
}
|
||||||
|
@ -173,15 +175,17 @@ namespace Ryujinx.Ava
|
||||||
if (sender is Control visual)
|
if (sender is Control visual)
|
||||||
{
|
{
|
||||||
_lastCursorMoveTime = Stopwatch.GetTimestamp();
|
_lastCursorMoveTime = Stopwatch.GetTimestamp();
|
||||||
|
|
||||||
var point = e.GetCurrentPoint(visual).Position;
|
var point = e.GetCurrentPoint(visual).Position;
|
||||||
_isMouseInRenderer = Equals(visual.InputHitTest(point), Renderer);
|
|
||||||
|
_isCursorInRenderer = Equals(visual.InputHitTest(point), Renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TopLevel_PointerLeave(object sender, PointerEventArgs e)
|
private void TopLevel_PointerLeave(object sender, PointerEventArgs e)
|
||||||
{
|
{
|
||||||
_isMouseInRenderer = false;
|
_isCursorInRenderer = false;
|
||||||
_viewModel.Cursor = Cursor.Default;
|
_viewModel.Cursor = Cursor.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetRendererWindowSize(Size size)
|
private void SetRendererWindowSize(Size size)
|
||||||
|
@ -189,6 +193,7 @@ namespace Ryujinx.Ava
|
||||||
if (_renderer != null)
|
if (_renderer != null)
|
||||||
{
|
{
|
||||||
double scale = _topLevel.PlatformImpl.RenderScaling;
|
double scale = _topLevel.PlatformImpl.RenderScaling;
|
||||||
|
|
||||||
_renderer.Window?.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
|
_renderer.Window?.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,12 +206,13 @@ namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
lock (_lockObject)
|
lock (_lockObject)
|
||||||
{
|
{
|
||||||
var currentTime = DateTime.Now;
|
DateTime currentTime = DateTime.Now;
|
||||||
string filename = $"ryujinx_capture_{currentTime.Year}-{currentTime.Month:D2}-{currentTime.Day:D2}_{currentTime.Hour:D2}-{currentTime.Minute:D2}-{currentTime.Second:D2}.png";
|
string filename = $"ryujinx_capture_{currentTime}-{currentTime:D2}-{currentTime:D2}_{currentTime:D2}-{currentTime:D2}-{currentTime:D2}.png";
|
||||||
|
|
||||||
string directory = AppDataManager.Mode switch
|
string directory = AppDataManager.Mode switch
|
||||||
{
|
{
|
||||||
AppDataManager.LaunchMode.Portable => Path.Combine(AppDataManager.BaseDirPath, "screenshots"),
|
AppDataManager.LaunchMode.Portable => Path.Combine(AppDataManager.BaseDirPath, "screenshots"),
|
||||||
_ => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx")
|
_ => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx")
|
||||||
};
|
};
|
||||||
|
|
||||||
string path = Path.Combine(directory, filename);
|
string path = Path.Combine(directory, filename);
|
||||||
|
@ -266,21 +272,10 @@ namespace Ryujinx.Ava
|
||||||
|
|
||||||
_viewModel.IsGameRunning = true;
|
_viewModel.IsGameRunning = true;
|
||||||
|
|
||||||
string titleNameSection = string.IsNullOrWhiteSpace(Device.Application.TitleName)
|
string titleNameSection = string.IsNullOrWhiteSpace(Device.Application.TitleName) ? string.Empty : $" - {Device.Application.TitleName}";
|
||||||
? string.Empty
|
string titleVersionSection = string.IsNullOrWhiteSpace(Device.Application.DisplayVersion) ? string.Empty : $" v{Device.Application.DisplayVersion}";
|
||||||
: $" - {Device.Application.TitleName}";
|
string titleIdSection = string.IsNullOrWhiteSpace(Device.Application.TitleIdText) ? string.Empty : $" ({Device.Application.TitleIdText.ToUpper()})";
|
||||||
|
string titleArchSection = Device.Application.TitleIs64Bit ? " (64-bit)" : " (32-bit)";
|
||||||
string titleVersionSection = string.IsNullOrWhiteSpace(Device.Application.DisplayVersion)
|
|
||||||
? string.Empty
|
|
||||||
: $" v{Device.Application.DisplayVersion}";
|
|
||||||
|
|
||||||
string titleIdSection = string.IsNullOrWhiteSpace(Device.Application.TitleIdText)
|
|
||||||
? string.Empty
|
|
||||||
: $" ({Device.Application.TitleIdText.ToUpper()})";
|
|
||||||
|
|
||||||
string titleArchSection = Device.Application.TitleIs64Bit
|
|
||||||
? " (64-bit)"
|
|
||||||
: " (32-bit)";
|
|
||||||
|
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
|
@ -326,9 +321,9 @@ namespace Ryujinx.Ava
|
||||||
private void UpdateAudioVolumeState(object sender, ReactiveEventArgs<float> e)
|
private void UpdateAudioVolumeState(object sender, ReactiveEventArgs<float> e)
|
||||||
{
|
{
|
||||||
Device?.SetVolume(e.NewValue);
|
Device?.SetVolume(e.NewValue);
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
var value = e.NewValue;
|
|
||||||
_viewModel.Volume = e.NewValue;
|
_viewModel.Volume = e.NewValue;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -348,7 +343,7 @@ namespace Ryujinx.Ava
|
||||||
}
|
}
|
||||||
|
|
||||||
_isStopped = true;
|
_isStopped = true;
|
||||||
_isActive = false;
|
_isActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeContext()
|
public void DisposeContext()
|
||||||
|
@ -381,9 +376,9 @@ namespace Ryujinx.Ava
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState;
|
ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState;
|
||||||
ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState;
|
ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState;
|
||||||
ConfigurationState.Instance.System.EnableDockedMode.Event -= UpdateDockedModeState;
|
ConfigurationState.Instance.System.EnableDockedMode.Event -= UpdateDockedModeState;
|
||||||
ConfigurationState.Instance.System.AudioVolume.Event -= UpdateAudioVolumeState;
|
ConfigurationState.Instance.System.AudioVolume.Event -= UpdateAudioVolumeState;
|
||||||
|
|
||||||
_topLevel.PointerLeave -= TopLevel_PointerLeave;
|
_topLevel.PointerLeave -= TopLevel_PointerLeave;
|
||||||
_topLevel.PointerMoved -= TopLevel_PointerMoved;
|
_topLevel.PointerMoved -= TopLevel_PointerMoved;
|
||||||
|
@ -597,19 +592,23 @@ namespace Ryujinx.Ava
|
||||||
internal void Resume()
|
internal void Resume()
|
||||||
{
|
{
|
||||||
Device?.System.TogglePauseEmulation(false);
|
Device?.System.TogglePauseEmulation(false);
|
||||||
|
|
||||||
_viewModel.IsPaused = false;
|
_viewModel.IsPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Pause()
|
internal void Pause()
|
||||||
{
|
{
|
||||||
Device?.System.TogglePauseEmulation(true);
|
Device?.System.TogglePauseEmulation(true);
|
||||||
|
|
||||||
_viewModel.IsPaused = true;
|
_viewModel.IsPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeSwitchInstance()
|
private void InitializeSwitchInstance()
|
||||||
{
|
{
|
||||||
|
// Initialize KeySet.
|
||||||
VirtualFileSystem.ReloadKeySet();
|
VirtualFileSystem.ReloadKeySet();
|
||||||
|
|
||||||
|
// Initialize Renderer.
|
||||||
IRenderer renderer;
|
IRenderer renderer;
|
||||||
|
|
||||||
if (Renderer.IsVulkan)
|
if (Renderer.IsVulkan)
|
||||||
|
@ -623,12 +622,9 @@ namespace Ryujinx.Ava
|
||||||
renderer = new OpenGLRenderer();
|
renderer = new OpenGLRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
IHardwareDeviceDriver deviceDriver = new DummyHardwareDeviceDriver();
|
|
||||||
|
|
||||||
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
||||||
|
|
||||||
var isGALthreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
var isGALthreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
||||||
|
|
||||||
if (isGALthreaded)
|
if (isGALthreaded)
|
||||||
{
|
{
|
||||||
renderer = new ThreadedRenderer(renderer);
|
renderer = new ThreadedRenderer(renderer);
|
||||||
|
@ -636,159 +632,104 @@ namespace Ryujinx.Ava
|
||||||
|
|
||||||
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALthreaded}");
|
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALthreaded}");
|
||||||
|
|
||||||
if (ConfigurationState.Instance.System.AudioBackend.Value == AudioBackend.SDL2)
|
// Initialize Configuration.
|
||||||
{
|
|
||||||
if (SDL2HardwareDeviceDriver.IsSupported)
|
|
||||||
{
|
|
||||||
deviceDriver = new SDL2HardwareDeviceDriver();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "SDL2 is not supported, trying to fall back to OpenAL.");
|
|
||||||
|
|
||||||
if (OpenALHardwareDeviceDriver.IsSupported)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "Found OpenAL, changing configuration.");
|
|
||||||
|
|
||||||
ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.OpenAl;
|
|
||||||
MainWindowViewModel.SaveConfig();
|
|
||||||
|
|
||||||
deviceDriver = new OpenALHardwareDeviceDriver();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "OpenAL is not supported, trying to fall back to SoundIO.");
|
|
||||||
|
|
||||||
if (SoundIoHardwareDeviceDriver.IsSupported)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "Found SoundIO, changing configuration.");
|
|
||||||
|
|
||||||
ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SoundIo;
|
|
||||||
MainWindowViewModel.SaveConfig();
|
|
||||||
|
|
||||||
deviceDriver = new SoundIoHardwareDeviceDriver();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "SoundIO is not supported, falling back to dummy audio out.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ConfigurationState.Instance.System.AudioBackend.Value == AudioBackend.SoundIo)
|
|
||||||
{
|
|
||||||
if (SoundIoHardwareDeviceDriver.IsSupported)
|
|
||||||
{
|
|
||||||
deviceDriver = new SoundIoHardwareDeviceDriver();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "SoundIO is not supported, trying to fall back to SDL2.");
|
|
||||||
|
|
||||||
if (SDL2HardwareDeviceDriver.IsSupported)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "Found SDL2, changing configuration.");
|
|
||||||
|
|
||||||
ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SDL2;
|
|
||||||
MainWindowViewModel.SaveConfig();
|
|
||||||
|
|
||||||
deviceDriver = new SDL2HardwareDeviceDriver();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "SDL2 is not supported, trying to fall back to OpenAL.");
|
|
||||||
|
|
||||||
if (OpenALHardwareDeviceDriver.IsSupported)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "Found OpenAL, changing configuration.");
|
|
||||||
|
|
||||||
ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.OpenAl;
|
|
||||||
MainWindowViewModel.SaveConfig();
|
|
||||||
|
|
||||||
deviceDriver = new OpenALHardwareDeviceDriver();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "OpenAL is not supported, falling back to dummy audio out.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ConfigurationState.Instance.System.AudioBackend.Value == AudioBackend.OpenAl)
|
|
||||||
{
|
|
||||||
if (OpenALHardwareDeviceDriver.IsSupported)
|
|
||||||
{
|
|
||||||
deviceDriver = new OpenALHardwareDeviceDriver();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "OpenAL is not supported, trying to fall back to SDL2.");
|
|
||||||
|
|
||||||
if (SDL2HardwareDeviceDriver.IsSupported)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "Found SDL2, changing configuration.");
|
|
||||||
|
|
||||||
ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SDL2;
|
|
||||||
MainWindowViewModel.SaveConfig();
|
|
||||||
|
|
||||||
deviceDriver = new SDL2HardwareDeviceDriver();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "SDL2 is not supported, trying to fall back to SoundIO.");
|
|
||||||
|
|
||||||
if (SoundIoHardwareDeviceDriver.IsSupported)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "Found SoundIO, changing configuration.");
|
|
||||||
|
|
||||||
ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SoundIo;
|
|
||||||
MainWindowViewModel.SaveConfig();
|
|
||||||
|
|
||||||
deviceDriver = new SoundIoHardwareDeviceDriver();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Audio, "SoundIO is not supported, falling back to dummy audio out.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var memoryConfiguration = ConfigurationState.Instance.System.ExpandRam.Value ? HLE.MemoryConfiguration.MemoryConfiguration6GiB : HLE.MemoryConfiguration.MemoryConfiguration4GiB;
|
var memoryConfiguration = ConfigurationState.Instance.System.ExpandRam.Value ? HLE.MemoryConfiguration.MemoryConfiguration6GiB : HLE.MemoryConfiguration.MemoryConfiguration4GiB;
|
||||||
|
|
||||||
IntegrityCheckLevel fsIntegrityCheckLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None;
|
HLE.HLEConfiguration configuration = new(VirtualFileSystem,
|
||||||
|
_viewModel.LibHacHorizonManager,
|
||||||
HLE.HLEConfiguration configuration = new HLE.HLEConfiguration(VirtualFileSystem,
|
ContentManager,
|
||||||
_viewModel.LibHacHorizonManager,
|
_accountManager,
|
||||||
ContentManager,
|
_userChannelPersistence,
|
||||||
_accountManager,
|
renderer,
|
||||||
_userChannelPersistence,
|
InitializeAudio(),
|
||||||
renderer,
|
memoryConfiguration,
|
||||||
deviceDriver,
|
_viewModel.UiHandler,
|
||||||
memoryConfiguration,
|
(SystemLanguage)ConfigurationState.Instance.System.Language.Value,
|
||||||
_viewModel.UiHandler,
|
(RegionCode)ConfigurationState.Instance.System.Region.Value,
|
||||||
(SystemLanguage)ConfigurationState.Instance.System.Language.Value,
|
ConfigurationState.Instance.Graphics.EnableVsync,
|
||||||
(RegionCode)ConfigurationState.Instance.System.Region.Value,
|
ConfigurationState.Instance.System.EnableDockedMode,
|
||||||
ConfigurationState.Instance.Graphics.EnableVsync,
|
ConfigurationState.Instance.System.EnablePtc,
|
||||||
ConfigurationState.Instance.System.EnableDockedMode,
|
ConfigurationState.Instance.System.EnableInternetAccess,
|
||||||
ConfigurationState.Instance.System.EnablePtc,
|
ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||||
ConfigurationState.Instance.System.EnableInternetAccess,
|
ConfigurationState.Instance.System.FsGlobalAccessLogMode,
|
||||||
fsIntegrityCheckLevel,
|
ConfigurationState.Instance.System.SystemTimeOffset,
|
||||||
ConfigurationState.Instance.System.FsGlobalAccessLogMode,
|
ConfigurationState.Instance.System.TimeZone,
|
||||||
ConfigurationState.Instance.System.SystemTimeOffset,
|
ConfigurationState.Instance.System.MemoryManagerMode,
|
||||||
ConfigurationState.Instance.System.TimeZone,
|
ConfigurationState.Instance.System.IgnoreMissingServices,
|
||||||
ConfigurationState.Instance.System.MemoryManagerMode,
|
ConfigurationState.Instance.Graphics.AspectRatio,
|
||||||
ConfigurationState.Instance.System.IgnoreMissingServices,
|
ConfigurationState.Instance.System.AudioVolume);
|
||||||
ConfigurationState.Instance.Graphics.AspectRatio,
|
|
||||||
ConfigurationState.Instance.System.AudioVolume);
|
|
||||||
|
|
||||||
Device = new Switch(configuration);
|
Device = new Switch(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IHardwareDeviceDriver InitializeAudio()
|
||||||
|
{
|
||||||
|
var availableBackends = new List<AudioBackend>()
|
||||||
|
{
|
||||||
|
AudioBackend.SDL2,
|
||||||
|
AudioBackend.SoundIo,
|
||||||
|
AudioBackend.OpenAl,
|
||||||
|
AudioBackend.Dummy
|
||||||
|
};
|
||||||
|
|
||||||
|
AudioBackend preferredBackend = ConfigurationState.Instance.System.AudioBackend.Value;
|
||||||
|
|
||||||
|
for (int i = 0; i < availableBackends.Count; i++)
|
||||||
|
{
|
||||||
|
if (availableBackends[i] == preferredBackend)
|
||||||
|
{
|
||||||
|
availableBackends.RemoveAt(i);
|
||||||
|
availableBackends.Insert(0, preferredBackend);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IHardwareDeviceDriver InitializeAudioBackend<T>(AudioBackend backend, AudioBackend nextBackend) where T : IHardwareDeviceDriver, new()
|
||||||
|
{
|
||||||
|
if (T.IsSupported)
|
||||||
|
{
|
||||||
|
return new T();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Audio, $"{backend} is not supported, falling back to {nextBackend}.");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IHardwareDeviceDriver deviceDriver = null;
|
||||||
|
|
||||||
|
for (int i = 0; i < availableBackends.Count; i++)
|
||||||
|
{
|
||||||
|
AudioBackend currentBackend = availableBackends[i];
|
||||||
|
AudioBackend nextBackend = i + 1 < availableBackends.Count ? availableBackends[i + 1] : AudioBackend.Dummy;
|
||||||
|
|
||||||
|
deviceDriver = currentBackend switch
|
||||||
|
{
|
||||||
|
AudioBackend.SDL2 => InitializeAudioBackend<SDL2HardwareDeviceDriver>(AudioBackend.SDL2, nextBackend),
|
||||||
|
AudioBackend.SoundIo => InitializeAudioBackend<SoundIoHardwareDeviceDriver>(AudioBackend.SoundIo, nextBackend),
|
||||||
|
AudioBackend.OpenAl => InitializeAudioBackend<OpenALHardwareDeviceDriver>(AudioBackend.OpenAl, nextBackend),
|
||||||
|
_ => new DummyHardwareDeviceDriver()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (deviceDriver != null)
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.System.AudioBackend.Value = currentBackend;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindowViewModel.SaveConfig();
|
||||||
|
|
||||||
|
return deviceDriver;
|
||||||
|
}
|
||||||
|
|
||||||
private void Window_SizeChanged(object sender, Size e)
|
private void Window_SizeChanged(object sender, Size e)
|
||||||
{
|
{
|
||||||
Width = (int)e.Width;
|
Width = (int)e.Width;
|
||||||
Height = (int)e.Height;
|
Height = (int)e.Height;
|
||||||
|
|
||||||
SetRendererWindowSize(e);
|
SetRendererWindowSize(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -798,7 +739,7 @@ namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
UpdateFrame();
|
UpdateFrame();
|
||||||
|
|
||||||
// Polling becomes expensive if it's not slept
|
// Polling becomes expensive if it's not slept.
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -818,14 +759,7 @@ namespace Ryujinx.Ava
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
IRenderer renderer = Device.Gpu.Renderer;
|
_renderer = Device.Gpu.Renderer is ThreadedRenderer tr ? tr.BaseRenderer : Device.Gpu.Renderer;
|
||||||
|
|
||||||
if (renderer is ThreadedRenderer tr)
|
|
||||||
{
|
|
||||||
renderer = tr.BaseRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderer = renderer;
|
|
||||||
|
|
||||||
_renderer.ScreenCaptured += Renderer_ScreenCaptured;
|
_renderer.ScreenCaptured += Renderer_ScreenCaptured;
|
||||||
|
|
||||||
|
@ -884,13 +818,12 @@ namespace Ryujinx.Ava
|
||||||
|
|
||||||
public void UpdateStatus()
|
public void UpdateStatus()
|
||||||
{
|
{
|
||||||
// Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued
|
// Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued.
|
||||||
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance[LocaleKeys.Docked] : LocaleManager.Instance[LocaleKeys.Handheld];
|
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance[LocaleKeys.Docked] : LocaleManager.Instance[LocaleKeys.Handheld];
|
||||||
float scale = GraphicsConfig.ResScale;
|
|
||||||
|
if (GraphicsConfig.ResScale != 1)
|
||||||
if (scale != 1)
|
|
||||||
{
|
{
|
||||||
dockedMode += $" ({scale}x)";
|
dockedMode += $" ({GraphicsConfig.ResScale}x)";
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
|
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
|
||||||
|
@ -907,7 +840,6 @@ namespace Ryujinx.Ava
|
||||||
public async Task ShowExitPrompt()
|
public async Task ShowExitPrompt()
|
||||||
{
|
{
|
||||||
bool shouldExit = !ConfigurationState.Instance.ShowConfirmExit;
|
bool shouldExit = !ConfigurationState.Instance.ShowConfirmExit;
|
||||||
|
|
||||||
if (!shouldExit)
|
if (!shouldExit)
|
||||||
{
|
{
|
||||||
if (_dialogShown)
|
if (_dialogShown)
|
||||||
|
@ -916,6 +848,7 @@ namespace Ryujinx.Ava
|
||||||
}
|
}
|
||||||
|
|
||||||
_dialogShown = true;
|
_dialogShown = true;
|
||||||
|
|
||||||
shouldExit = await ContentDialogHelper.CreateStopEmulationDialog();
|
shouldExit = await ContentDialogHelper.CreateStopEmulationDialog();
|
||||||
|
|
||||||
_dialogShown = false;
|
_dialogShown = false;
|
||||||
|
@ -933,7 +866,7 @@ namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
_viewModel.Cursor = _isMouseInRenderer ? InvisibleCursor : Cursor.Default;
|
_viewModel.Cursor = _isCursorInRenderer ? InvisibleCursor : Cursor.Default;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1046,7 +979,7 @@ namespace Ryujinx.Ava
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Touchscreen
|
// Touchscreen.
|
||||||
bool hasTouch = false;
|
bool hasTouch = false;
|
||||||
|
|
||||||
if (_viewModel.IsActive && !ConfigurationState.Instance.Hid.EnableMouse)
|
if (_viewModel.IsActive && !ConfigurationState.Instance.Hid.EnableMouse)
|
||||||
|
|
Loading…
Reference in a new issue