Merge branch 'master' into 20-empty-nca-lockup

This commit is contained in:
Shyanne
2026-01-28 00:34:04 -05:00
50 changed files with 2115 additions and 60 deletions

View File

@@ -190,7 +190,7 @@ namespace Ryujinx.Ava.Common.Locale
}
foreach (LocalesJson file in _localeData.Value.LocalesFiles.Values)
foreach ((string fileName, LocalesJson file) in _localeData.Value.LocalesFiles)
{
foreach (LocalesEntry locale in file.Locales)
{
@@ -206,7 +206,7 @@ namespace Ryujinx.Ava.Common.Locale
$"Locale key {{{locale.ID}}} has too many languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!");
}
if (!Enum.TryParse<LocaleKeys>(locale.ID, out LocaleKeys localeKey))
if (!Enum.TryParse<LocaleKeys>(fileName == "Root.json" ? locale.ID : $"{fileName[..^".json".Length]}_{locale.ID}" , out LocaleKeys localeKey))
continue;
string str = locale.Translations.TryGetValue(languageCode, out string val) && !string.IsNullOrEmpty(val)

View File

@@ -18,6 +18,7 @@ using Ryujinx.Common.GraphicsDriver;
using Ryujinx.Common.Logging;
using Ryujinx.Common.SystemInterop;
using Ryujinx.Common.Utilities;
using Ryujinx.Graphics.RenderDocApi;
using Ryujinx.Graphics.Vulkan.MoltenVK;
using Ryujinx.Headless;
using Ryujinx.SDL3.Common;

View File

@@ -77,16 +77,18 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ryujinx.Audio.Backends.SDL3\Ryujinx.Audio.Backends.SDL3.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.RenderDocApi\Ryujinx.Graphics.RenderDocApi.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan/Ryujinx.Graphics.Vulkan.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.OpenGL/Ryujinx.Graphics.OpenGL.csproj" />
<ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" />
<ProjectReference Include="..\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj" />
<ProjectReference Include="..\Ryujinx.Audio.Backends.Apple\Ryujinx.Audio.Backends.Apple.csproj" />
<ProjectReference Include="..\Ryujinx.Audio.Backends.SDL3\Ryujinx.Audio.Backends.SDL3.csproj" />
<ProjectReference Include="..\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj" />
<ProjectReference Include="..\Ryujinx.Audio.Backends.SoundIo\Ryujinx.Audio.Backends.SoundIo.csproj" />
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
<ProjectReference Include="..\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

View File

@@ -6,6 +6,7 @@ using Avalonia.Threading;
using DiscordRPC;
using LibHac.Common;
using LibHac.Ns;
using Ryujinx.Audio.Backends.Apple;
using Ryujinx.Audio.Backends.Dummy;
using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL3;
@@ -979,6 +980,9 @@ namespace Ryujinx.Ava.Systems
AudioBackend.Dummy
];
if (OperatingSystem.IsMacOS())
availableBackends.Insert(0, AudioBackend.AudioToolbox);
AudioBackend preferredBackend = ConfigurationState.Instance.System.AudioBackend.Value;
if (preferredBackend is AudioBackend.SDL2)
@@ -1015,6 +1019,9 @@ namespace Ryujinx.Ava.Systems
deviceDriver = currentBackend switch
{
#pragma warning disable CA1416 // Platform compatibility is enforced in AppleHardwareDeviceDriver.IsSupported, before any potentially platform-sensitive code can run.
AudioBackend.AudioToolbox => InitializeAudioBackend<AppleHardwareDeviceDriver>(AudioBackend.AudioToolbox, nextBackend),
#pragma warning restore CA1416
AudioBackend.SDL3 => InitializeAudioBackend<SDL3HardwareDeviceDriver>(AudioBackend.SDL3, nextBackend),
AudioBackend.SoundIo => InitializeAudioBackend<SoundIoHardwareDeviceDriver>(AudioBackend.SoundIo, nextBackend),
AudioBackend.OpenAl => InitializeAudioBackend<OpenALHardwareDeviceDriver>(AudioBackend.OpenAl, nextBackend),

View File

@@ -9,6 +9,7 @@ namespace Ryujinx.Ava.Systems.Configuration
OpenAl,
SoundIo,
SDL3,
AudioToolbox,
SDL2 = SDL3
}
}

View File

@@ -7,6 +7,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.Systems.Update.Client;
using Ryujinx.Systems.Update.Common;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
@@ -46,6 +47,12 @@ namespace Ryujinx.Ava.Systems
return Return<VersionResponse>.Failure(
new MessageError("DNS resolution error occurred. Is your internet down?"));
}
catch (HttpRequestException hre)
when (hre.StatusCode is HttpStatusCode.BadGateway)
{
return Return<VersionResponse>.Failure(
new MessageError("Could not connect to the update server, but it appears like you have internet. It seems like the update server is offline, try again later."));
}
}
public static async Task<Optional<(Version Current, Version Incoming)>> CheckVersionAsync(bool showVersionUpToDate = false)

View File

@@ -2,8 +2,12 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Platform;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.RenderDocApi;
using Ryujinx.HLE;
using SPB.Graphics;
using SPB.Platform;
using SPB.Platform.GLX;
@@ -30,6 +34,7 @@ namespace Ryujinx.Ava.UI.Renderer
protected nint MetalLayer { get; set; }
public delegate void UpdateBoundsCallbackDelegate(Rect rect);
private UpdateBoundsCallbackDelegate _updateBoundsCallback;
public event EventHandler<nint> WindowCreated;
@@ -46,6 +51,55 @@ namespace Ryujinx.Ava.UI.Renderer
protected virtual void OnWindowDestroyed() { }
public bool ToggleRenderDocCapture(Switch device)
{
if (!RenderDoc.IsAvailable) return false;
if (RenderDoc.IsFrameCapturing)
{
if (EndRenderDocCapture())
{
Logger.Info?.Print(LogClass.Application, "Ended RenderDoc capture.");
return true;
}
}
else if (StartRenderDocCapture(device))
{
Logger.Info?.Print(LogClass.Application, "Starting RenderDoc capture.");
return true;
}
return false;
}
public bool StartRenderDocCapture(Switch device)
{
if (!RenderDoc.IsAvailable) return false;
if (RenderDoc.IsFrameCapturing) return false;
RenderDoc.StartFrameCapture(nint.Zero, WindowHandle);
RenderDoc.SetCaptureTitle(TitleHelper.FormatRenderDocCaptureTitle(device.Processes.ActiveApplication, Program.Version));
return true;
}
public bool EndRenderDocCapture()
{
if (!RenderDoc.IsAvailable) return false;
if (!RenderDoc.IsFrameCapturing) return false;
return RenderDoc.IsFrameCapturing && RenderDoc.EndFrameCapture(nint.Zero, WindowHandle);
}
public bool DiscardRenderDocCapture()
{
if (!RenderDoc.IsAvailable) return false;
if (!RenderDoc.IsFrameCapturing) return false;
return RenderDoc.IsFrameCapturing && RenderDoc.DiscardFrameCapture(nint.Zero, WindowHandle);
}
protected virtual void OnWindowDestroying()
{
WindowHandle = nint.Zero;
@@ -124,7 +178,9 @@ namespace Ryujinx.Ava.UI.Renderer
}
else
{
X11Window = PlatformHelper.CreateOpenGLWindow(new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false), 0, 0, 100, 100) as GLXWindow;
X11Window = PlatformHelper.CreateOpenGLWindow(
new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false), 0, 0, 100,
100) as GLXWindow;
}
WindowHandle = X11Window.WindowHandle.RawHandle;
@@ -138,7 +194,7 @@ namespace Ryujinx.Ava.UI.Renderer
{
_className = "NativeWindow-" + Guid.NewGuid();
_wndProcDelegate = delegate (nint hWnd, WindowsMessages msg, nint wParam, nint lParam)
_wndProcDelegate = delegate(nint hWnd, WindowsMessages msg, nint wParam, nint lParam)
{
switch (msg)
{
@@ -161,7 +217,8 @@ namespace Ryujinx.Ava.UI.Renderer
RegisterClassEx(ref wndClassEx);
WindowHandle = CreateWindowEx(0, _className, "NativeWindow", WindowStyles.WsChild, 0, 0, 640, 480, control.Handle, nint.Zero, nint.Zero, nint.Zero);
WindowHandle = CreateWindowEx(0, _className, "NativeWindow", WindowStyles.WsChild, 0, 0, 640, 480,
control.Handle, nint.Zero, nint.Zero, nint.Zero);
SetWindowLongPtrW(control.Handle, GWLP_WNDPROC, wndClassEx.lpfnWndProc);

View File

@@ -15,6 +15,7 @@ using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.RenderDocApi;
using System;
using System.Diagnostics;

View File

@@ -38,6 +38,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.Common.UI;
using Ryujinx.Common.Utilities;
using Ryujinx.Cpu;
using Ryujinx.Graphics.RenderDocApi;
using Ryujinx.HLE;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS;
@@ -104,7 +105,7 @@ namespace Ryujinx.Ava.UI.ViewModels
[ObservableProperty] public partial Brush ProgressBarForegroundColor { get; set; }
[ObservableProperty] public partial Brush ProgressBarBackgroundColor { get; set; }
#pragma warning disable MVVMTK0042 // Must stay a normal observable field declaration since this is used as an out parameter target
[ObservableProperty] private ReadOnlyObservableCollection<ApplicationData> _appsObservableList;
#pragma warning restore MVVMTK0042
@@ -129,8 +130,7 @@ namespace Ryujinx.Ava.UI.ViewModels
[ObservableProperty] public partial string LastScannedAmiiboId { get; set; }
[ObservableProperty]
public partial long LastFullscreenToggle { get; set; } = Environment.TickCount64;
[ObservableProperty] public partial long LastFullscreenToggle { get; set; } = Environment.TickCount64;
[ObservableProperty] public partial bool ShowContent { get; set; } = true;
[ObservableProperty] public partial float VolumeBeforeMute { get; set; }
@@ -1876,6 +1876,29 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public void ReloadRenderDocApi()
{
RenderDoc.ReloadApi(ignoreAlreadyLoaded: true);
OnPropertiesChanged(nameof(ShowStartCaptureButton), nameof(ShowEndCaptureButton), nameof(RenderDocIsAvailable));
if (RenderDoc.IsAvailable)
RenderDocIsCapturing = RenderDoc.IsFrameCapturing;
NotificationHelper.ShowInformation(
"RenderDoc API reloaded",
RenderDoc.IsAvailable ? "RenderDoc is now available." : "RenderDoc is no longer available."
);
}
public void ToggleCapture()
{
if (ShowLoadProgress) return;
AppHost.RendererHost.EmbeddedWindow.ToggleRenderDocCapture(AppHost.Device);
RenderDocIsCapturing = RenderDoc.IsFrameCapturing;
}
public void ToggleFullscreen()
{
if (Environment.TickCount64 - LastFullscreenToggle < HotKeyPressDelayMs)
@@ -1966,7 +1989,8 @@ namespace Ryujinx.Ava.UI.ViewModels
if (ConfigurationState.Instance.Debug.EnableGdbStub)
{
NotificationHelper.ShowInformation(
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.NotificationLaunchCheckGdbStubTitle, ConfigurationState.Instance.Debug.GdbStubPort.Value),
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.NotificationLaunchCheckGdbStubTitle,
ConfigurationState.Instance.Debug.GdbStubPort.Value),
LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckGdbStubMessage]);
}
@@ -1975,10 +1999,12 @@ namespace Ryujinx.Ava.UI.ViewModels
var memoryConfigurationLocaleKey = ConfigurationState.Instance.System.DramSize.Value switch
{
MemoryConfiguration.MemoryConfiguration4GiB or
MemoryConfiguration.MemoryConfiguration4GiBAppletDev or
MemoryConfiguration.MemoryConfiguration4GiBSystemDev => LocaleKeys.SettingsTabSystemDramSize4GiB,
MemoryConfiguration.MemoryConfiguration4GiBAppletDev or
MemoryConfiguration.MemoryConfiguration4GiBSystemDev =>
LocaleKeys.SettingsTabSystemDramSize4GiB,
MemoryConfiguration.MemoryConfiguration6GiB or
MemoryConfiguration.MemoryConfiguration6GiBAppletDev => LocaleKeys.SettingsTabSystemDramSize6GiB,
MemoryConfiguration.MemoryConfiguration6GiBAppletDev =>
LocaleKeys.SettingsTabSystemDramSize6GiB,
MemoryConfiguration.MemoryConfiguration8GiB => LocaleKeys.SettingsTabSystemDramSize8GiB,
MemoryConfiguration.MemoryConfiguration12GiB => LocaleKeys.SettingsTabSystemDramSize12GiB,
_ => LocaleKeys.SettingsTabSystemDramSize4GiB,
@@ -1986,9 +2012,9 @@ namespace Ryujinx.Ava.UI.ViewModels
NotificationHelper.ShowWarning(
LocaleManager.Instance.UpdateAndGetDynamicValue(
LocaleKeys.NotificationLaunchCheckDramSizeTitle,
LocaleKeys.NotificationLaunchCheckDramSizeTitle,
LocaleManager.Instance[memoryConfigurationLocaleKey]
),
),
LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckDramSizeMessage]);
}
}
@@ -2473,6 +2499,67 @@ namespace Ryujinx.Ava.UI.ViewModels
png.SaveTo(fileStream);
});
public bool ShowStartCaptureButton => !RenderDocIsCapturing && RenderDoc.IsAvailable;
public bool ShowEndCaptureButton => RenderDocIsCapturing && RenderDoc.IsAvailable;
public static bool RenderDocIsAvailable => RenderDoc.IsAvailable;
public bool RenderDocIsCapturing
{
get;
set
{
field = value;
OnPropertyChanged();
OnPropertiesChanged(nameof(ShowStartCaptureButton), nameof(ShowEndCaptureButton));
}
}
public static RelayCommand<MainWindowViewModel> StartRenderDocCapture { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => RenderDoc.IsAvailable && !vm.ShowLoadProgress,
viewModel =>
{
if (!RenderDoc.IsFrameCapturing)
{
if (viewModel.AppHost.RendererHost
.EmbeddedWindow.StartRenderDocCapture(viewModel.AppHost.Device))
{
Logger.Info?.Print(LogClass.Application, "Starting RenderDoc capture.");
}
}
viewModel.RenderDocIsCapturing = RenderDoc.IsFrameCapturing;
});
public static RelayCommand<MainWindowViewModel> EndRenderDocCapture { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => RenderDoc.IsAvailable && !vm.ShowLoadProgress,
viewModel =>
{
if (RenderDoc.IsFrameCapturing)
{
if (viewModel.AppHost.RendererHost.EmbeddedWindow.EndRenderDocCapture())
{
Logger.Info?.Print(LogClass.Application, "Ended RenderDoc capture.");
}
}
viewModel.RenderDocIsCapturing = RenderDoc.IsFrameCapturing;
});
public static RelayCommand<MainWindowViewModel> DiscardRenderDocCapture { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => RenderDoc.IsAvailable && !vm.ShowLoadProgress,
viewModel =>
{
if (RenderDoc.IsFrameCapturing)
{
if (viewModel.AppHost.RendererHost.EmbeddedWindow.DiscardRenderDocCapture())
{
Logger.Info?.Print(LogClass.Application, "Discarded RenderDoc capture.");
}
}
viewModel.RenderDocIsCapturing = RenderDoc.IsFrameCapturing;
});
#endregion
}
}

View File

@@ -5,6 +5,7 @@ using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.Apple;
using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL3;
using Ryujinx.Audio.Backends.SoundIo;
@@ -277,6 +278,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool IsOpenAlEnabled { get; set; }
public bool IsSoundIoEnabled { get; set; }
public bool IsSDL3Enabled { get; set; }
public bool IsAudioToolboxEnabled { get; set; }
public bool IsCustomResolutionScaleActive => _resolutionScale == 4;
public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr;
@@ -524,12 +526,14 @@ namespace Ryujinx.Ava.UI.ViewModels
IsOpenAlEnabled = OpenALHardwareDeviceDriver.IsSupported;
IsSoundIoEnabled = SoundIoHardwareDeviceDriver.IsSupported;
IsSDL3Enabled = SDL3HardwareDeviceDriver.IsSupported;
IsAudioToolboxEnabled = OperatingSystem.IsMacOS() && AppleHardwareDeviceDriver.IsSupported;
await Dispatcher.UIThread.InvokeAsync(() =>
{
OnPropertyChanged(nameof(IsOpenAlEnabled));
OnPropertyChanged(nameof(IsSoundIoEnabled));
OnPropertyChanged(nameof(IsSDL3Enabled));
OnPropertyChanged(nameof(IsAudioToolboxEnabled));
});
}

View File

@@ -8,6 +8,7 @@
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
xmlns:common="clr-namespace:Ryujinx.Common;assembly=Ryujinx.Common"
xmlns:renderDocApi="clr-namespace:Ryujinx.Graphics.RenderDocApi;assembly=Ryujinx.Graphics.RenderDocApi"
x:DataType="viewModels:MainWindowViewModel"
x:Class="Ryujinx.Ava.UI.Views.Main.MainMenuBarView">
<Design.DataContext>
@@ -200,6 +201,29 @@
Header="{ext:Locale GameListContextMenuManageCheat}"
Icon="{ext:Icon fa-solid fa-code}"
IsEnabled="{Binding IsGameRunning}" />
<Separator IsVisible="{Binding RenderDocIsAvailable}" />
<MenuItem
IsVisible="{Binding ShowStartCaptureButton}"
Command="{Binding StartRenderDocCapture}"
CommandParameter="{Binding}"
Header="{ext:Locale RenderDoc_MenuBarActions_StartCapture}"
Icon="{ext:Icon fa-solid fa-video}"
IsEnabled="{Binding IsGameRunning}" />
<MenuItem
IsVisible="{Binding ShowEndCaptureButton}"
Command="{Binding EndRenderDocCapture}"
CommandParameter="{Binding}"
Header="{ext:Locale RenderDoc_MenuBarActions_EndCapture}"
Icon="{ext:Icon fa-solid fa-video-slash}"
IsEnabled="{Binding IsGameRunning}" />
<MenuItem
IsVisible="{Binding ShowEndCaptureButton}"
Command="{Binding DiscardRenderDocCapture}"
CommandParameter="{Binding}"
Header="{ext:Locale RenderDoc_MenuBarActions_DiscardCapture}"
ToolTip.Tip="{ext:Locale RenderDoc_MenuBarActions_DiscardCapture_ToolTip}"
Icon="{ext:Icon fa-solid fa-video-slash}"
IsEnabled="{Binding IsGameRunning}" />
</MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarActions}" IsVisible="{Binding EnableNonGameRunningControls}">
<MenuItem Header="{ext:Locale MenuBarActionsInstallKeys}" Icon="{ext:Icon fa-solid fa-key}">

View File

@@ -101,8 +101,8 @@ namespace Ryujinx.Ava.UI.Views.Main
Padding = new Thickness(15, 0, 0, 0),
Margin = new Thickness(3, 0, 3, 0),
HorizontalAlignment = HorizontalAlignment.Stretch,
Header = language == currentLanguageCode ? $"{languageName} ✔" : languageName,
Command = Commands.Create(() => MainWindowViewModel.ChangeLanguage(language))
Header = code == currentLanguageCode ? $"{languageName} ✔" : languageName,
Command = Commands.Create(() => MainWindowViewModel.ChangeLanguage(code))
};
yield return menuItem;

View File

@@ -46,6 +46,9 @@
<ComboBoxItem
IsEnabled="{Binding IsSDL3Enabled}"
Content="{ext:Locale SettingsTabSystemAudioBackendSDL3}" />
<ComboBoxItem
IsEnabled="{Binding IsAudioToolboxEnabled}"
Content="{ext:Locale SettingsTabSystemAudioBackendAudioToolbox}" />
</ComboBox>
</StackPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">

View File

@@ -41,6 +41,8 @@
<KeyBinding Gesture="Escape" Command="{Binding ExitCurrentState}" />
<KeyBinding Gesture="Ctrl+A" Command="{Binding OpenAmiiboWindow}" />
<KeyBinding Gesture="Ctrl+B" Command="{Binding OpenBinFile}" />
<KeyBinding Gesture="Ctrl+Shift+R" Command="{Binding ReloadRenderDocApi}" />
<KeyBinding Gesture="Ctrl+Shift+C" Command="{Binding ToggleCapture}" />
</Window.KeyBindings>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RowDefinitions="*">
<helpers:OffscreenTextBox IsEnabled="False" Opacity="0" Name="HiddenTextBox" IsHitTestVisible="False" IsTabStop="False" />

View File

@@ -19,6 +19,9 @@ namespace Ryujinx.Ava.Utilities
public static string OverrideSystemLanguage { get; private set; }
public static string OverrideHideCursor { get; private set; }
public static string BaseDirPathArg { get; private set; }
public static string RenderDocCaptureTitleFormat { get; private set; } =
"{EmuVersion}\n{GuestName} {GuestVersion} {GuestTitleId} {GuestArch}";
public static Optional<FilePath> FirmwareToInstallPathArg { get; set; }
public static string Profile { get; private set; }
public static string LaunchPathArg { get; private set; }
@@ -54,6 +57,20 @@ namespace Ryujinx.Ava.Utilities
BaseDirPathArg = args[++i];
arguments.Add(arg);
arguments.Add(args[i]);
break;
case "-rdct":
case "--rd-capture-title-format":
if (i + 1 >= args.Length)
{
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
continue;
}
RenderDocCaptureTitleFormat = args[++i];
arguments.Add(arg);
arguments.Add(args[i]);
break;

View File

@@ -1,3 +1,4 @@
using Gommon;
using Ryujinx.HLE.Loaders.Processes;
namespace Ryujinx.Ava.Utilities
@@ -22,5 +23,23 @@ namespace Ryujinx.Ava.Utilities
? appTitle + $" ({pauseString})"
: appTitle;
}
public static string FormatRenderDocCaptureTitle(ProcessResult activeProcess, string applicationVersion)
{
if (activeProcess == null)
return string.Empty;
string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : activeProcess.Name;
string titleVersionSection = string.IsNullOrWhiteSpace(activeProcess.DisplayVersion) ? string.Empty : $"v{activeProcess.DisplayVersion}";
string titleIdSection = $"({activeProcess.ProgramIdText.ToUpper()})";
string titleArchSection = activeProcess.Is64Bit ? "(64-bit)" : "(32-bit)";
return CommandLineState.RenderDocCaptureTitleFormat
.ReplaceIgnoreCase("{EmuVersion}", applicationVersion)
.ReplaceIgnoreCase("{GuestName}", titleNameSection)
.ReplaceIgnoreCase("{GuestVersion}", titleVersionSection)
.ReplaceIgnoreCase("{GuestTitleId}", titleIdSection)
.ReplaceIgnoreCase("{GuestArch}", titleArchSection);
}
}
}