Merge remote-tracking branch 'origin/master2' into SDL3
# Conflicts: # src/Ryujinx/Headless/Windows/OpenGLWindow.cs # src/Ryujinx/Headless/Windows/WindowBase.cs
This commit is contained in:
commit
8fd97963e9
@ -3348,7 +3348,7 @@
|
||||
01001C400482C000,"Wunderling DX",audio;crash,ingame,2022-09-10 13:20:12
|
||||
01003B401148E000,"Wurroom",,playable,2020-10-07 22:46:21
|
||||
010081700EDF4000,"WWE 2K Battlegrounds",nvdec;online-broken;UE4,playable,2022-10-07 12:44:40
|
||||
010009800203E000,"WWE 2K18",nvdec,playable,2023-10-21 17:22:01
|
||||
010009800203E000,"WWE 2K18",nvdec;online-broken,ingame,2025-01-17 11:36:56
|
||||
0100DF100B97C000,"X-Morph: Defense",,playable,2020-06-22 11:05:31
|
||||
0100D0B00FB74000,"XCOM® 2 Collection",gpu;crash,ingame,2022-10-04 09:38:30
|
||||
0100CC9015360000,"XEL",gpu,ingame,2022-10-03 10:19:39
|
||||
@ -3421,4 +3421,4 @@
|
||||
0100936018EB4000,"牧場物語 Welcome!ワンダフルライフ",crash,ingame,2023-04-25 19:43:52
|
||||
0100F4401940A000,"超探偵事件簿 レインコード (Master Detective Archives: Rain Code)",crash,ingame,2024-02-12 20:58:31
|
||||
010064801A01C000,"超次元ゲイム ネプテューヌ GameMaker R:Evolution",crash,nothing,2023-10-30 22:37:40
|
||||
0100F3400332C000,"ゼノブレイド2",deadlock;amd-vendor-bug,ingame,2024-03-28 14:31:41
|
||||
0100F3400332C000,"ゼノブレイド2",deadlock;amd-vendor-bug,ingame,2024-03-28 14:31:41
|
||||
|
|
File diff suppressed because it is too large
Load Diff
@ -228,8 +228,6 @@ namespace Ryujinx.Headless
|
||||
_inputConfiguration ??= [];
|
||||
_enableKeyboard = option.EnableKeyboard;
|
||||
_enableMouse = option.EnableMouse;
|
||||
|
||||
|
||||
|
||||
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||
@ -301,7 +299,10 @@ namespace Ryujinx.Headless
|
||||
_userChannelPersistence.ShouldRestart = false;
|
||||
}
|
||||
|
||||
_inputManager.Dispose();
|
||||
try
|
||||
{
|
||||
_inputManager.Dispose();
|
||||
} catch {}
|
||||
|
||||
return;
|
||||
|
||||
@ -338,12 +339,12 @@ namespace Ryujinx.Headless
|
||||
{
|
||||
string label = state switch
|
||||
{
|
||||
LoadState => $"PTC : {current}/{total}",
|
||||
ShaderCacheState => $"Shaders : {current}/{total}",
|
||||
_ => throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}"),
|
||||
LoadState => "PTC",
|
||||
ShaderCacheState => "Shaders",
|
||||
_ => 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)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 3.9 KiB |
@ -1,21 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
{
|
||||
class StatusUpdatedEventArgs(
|
||||
string vSyncMode,
|
||||
string dockedMode,
|
||||
string aspectRatio,
|
||||
string gameStatus,
|
||||
string fifoStatus,
|
||||
string gpuName)
|
||||
: EventArgs
|
||||
{
|
||||
public string VSyncMode = vSyncMode;
|
||||
public string DockedMode = dockedMode;
|
||||
public string AspectRatio = aspectRatio;
|
||||
public string GameStatus = gameStatus;
|
||||
public string FifoStatus = fifoStatus;
|
||||
public string GpuName = gpuName;
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ namespace Ryujinx.Headless
|
||||
bool ignoreControllerApplet)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet) { }
|
||||
|
||||
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_METAL;
|
||||
public override SDL_WindowFlags WindowFlags => SDL_WindowFlags.SDL_WINDOW_METAL;
|
||||
|
||||
protected override void InitializeWindowRenderer()
|
||||
{
|
@ -106,7 +106,7 @@ namespace Ryujinx.Headless
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private readonly GraphicsDebugLevel _glLogLevel;
|
||||
private SDL3OpenGLContext _openGLContext;
|
||||
|
||||
@ -119,10 +119,9 @@ namespace Ryujinx.Headless
|
||||
bool ignoreControllerApplet)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet)
|
||||
{
|
||||
_glLogLevel = glLogLevel;
|
||||
}
|
||||
|
||||
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_OPENGL;
|
||||
public override SDL_WindowFlags WindowFlags() => SDL_WindowFlags.SDL_WINDOW_OPENGL;
|
||||
|
||||
protected override void InitializeWindowRenderer()
|
||||
{
|
@ -10,8 +10,6 @@ namespace Ryujinx.Headless
|
||||
{
|
||||
class VulkanWindow : WindowBase
|
||||
{
|
||||
private readonly GraphicsDebugLevel _glLogLevel;
|
||||
|
||||
public VulkanWindow(
|
||||
InputManager inputManager,
|
||||
GraphicsDebugLevel glLogLevel,
|
||||
@ -21,10 +19,9 @@ namespace Ryujinx.Headless
|
||||
bool ignoreControllerApplet)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet)
|
||||
{
|
||||
_glLogLevel = glLogLevel;
|
||||
}
|
||||
|
||||
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_VULKAN;
|
||||
public override SDL_WindowFlags WindowFlags => SDL_WindowFlags.SDL_WINDOW_VULKAN;
|
||||
|
||||
protected override void InitializeWindowRenderer() { }
|
||||
|
@ -1,12 +1,12 @@
|
||||
using Humanizer;
|
||||
using LibHac.Util;
|
||||
using Ryujinx.Ava;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.GAL.Multithreading;
|
||||
using Ryujinx.Graphics.Gpu;
|
||||
using Ryujinx.Graphics.OpenGL;
|
||||
using Ryujinx.HLE.HOS.Applets;
|
||||
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
||||
@ -43,6 +43,10 @@ namespace Ryujinx.Headless
|
||||
|
||||
private static readonly ConcurrentQueue<Action> _mainThreadActions = new();
|
||||
|
||||
[LibraryImport("SDL2")]
|
||||
// TODO: Remove this as soon as SDL2-CS was updated to expose this method publicly
|
||||
private static partial nint SDL_LoadBMP_RW(nint src, int freesrc);
|
||||
|
||||
public static void QueueMainThreadAction(Action action)
|
||||
{
|
||||
_mainThreadActions.Enqueue(action);
|
||||
@ -72,7 +76,7 @@ namespace Ryujinx.Headless
|
||||
protected SDL3MouseDriver MouseDriver;
|
||||
private readonly InputManager _inputManager;
|
||||
private readonly IKeyboard _keyboardInterface;
|
||||
private readonly GraphicsDebugLevel _glLogLevel;
|
||||
protected readonly GraphicsDebugLevel GlLogLevel;
|
||||
private readonly Stopwatch _chrono;
|
||||
private readonly long _ticksPerFrame;
|
||||
private readonly CancellationTokenSource _gpuCancellationTokenSource;
|
||||
@ -104,7 +108,7 @@ namespace Ryujinx.Headless
|
||||
NpadManager = _inputManager.CreateNpadManager();
|
||||
TouchScreenManager = _inputManager.CreateTouchScreenManager();
|
||||
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
|
||||
_glLogLevel = glLogLevel;
|
||||
GlLogLevel = glLogLevel;
|
||||
_chrono = new Stopwatch();
|
||||
_ticksPerFrame = Stopwatch.Frequency / TargetFps;
|
||||
_gpuCancellationTokenSource = new CancellationTokenSource();
|
||||
@ -137,7 +141,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
private void SetWindowIcon()
|
||||
{
|
||||
Stream iconStream = typeof(Program).Assembly.GetManifestResourceStream("HeadlessLogo");
|
||||
Stream iconStream = EmbeddedResources.GetStream("Ryujinx/Assets/UIImages/Logo_Ryujinx.png");
|
||||
byte[] iconBytes = new byte[iconStream!.Length];
|
||||
|
||||
if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length)
|
||||
@ -169,15 +173,9 @@ namespace Ryujinx.Headless
|
||||
var nacp = activeProcess.ApplicationControlProperties;
|
||||
int desiredLanguage = (int)Device.System.State.DesiredTitleLanguage;
|
||||
|
||||
string titleNameSection = string.IsNullOrWhiteSpace(nacp.Title[desiredLanguage].NameString.ToString())
|
||||
? string.Empty
|
||||
: $" - {nacp.Title[desiredLanguage].NameString.ToString()}";
|
||||
string titleVersionSection = string.IsNullOrWhiteSpace(nacp.DisplayVersionString.ToString())
|
||||
? string.Empty
|
||||
: $" v{nacp.DisplayVersionString.ToString()}";
|
||||
string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText)
|
||||
? string.Empty
|
||||
: $" ({activeProcess.ProgramIdText.ToUpper()})";
|
||||
string titleNameSection = string.IsNullOrWhiteSpace(nacp.Title[desiredLanguage].NameString.ToString()) ? string.Empty : $" - {nacp.Title[desiredLanguage].NameString.ToString()}";
|
||||
string titleVersionSection = string.IsNullOrWhiteSpace(nacp.DisplayVersionString.ToString()) ? string.Empty : $" v{nacp.DisplayVersionString.ToString()}";
|
||||
string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText) ? string.Empty : $" ({activeProcess.ProgramIdText.ToUpper()})";
|
||||
string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
|
||||
|
||||
Width = DefaultWidth;
|
||||
@ -197,10 +195,7 @@ namespace Ryujinx.Headless
|
||||
FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
|
||||
WindowHandle =
|
||||
SDL_CreateWindow(
|
||||
$"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}",
|
||||
Width, Height, DefaultFlags | FullscreenFlag | GetWindowFlags());
|
||||
WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", Width, Height, DefaultFlags | FullscreenFlag | WindowFlags());
|
||||
|
||||
if (WindowHandle == nint.Zero)
|
||||
{
|
||||
@ -236,7 +231,6 @@ namespace Ryujinx.Headless
|
||||
Renderer?.Window.SetSize(Width, Height);
|
||||
MouseDriver.SetClientSize(Width, Height);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SDL_EventType.SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||
@ -258,7 +252,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
protected abstract void SwapBuffers();
|
||||
|
||||
public abstract SDL_WindowFlags GetWindowFlags();
|
||||
public abstract SDL_WindowFlags WindowFlags { get; }
|
||||
|
||||
private string GetGpuDriverName()
|
||||
{
|
||||
@ -280,7 +274,7 @@ namespace Ryujinx.Headless
|
||||
{
|
||||
InitializeWindowRenderer();
|
||||
|
||||
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
||||
Device.Gpu.Renderer.Initialize(GlLogLevel);
|
||||
|
||||
InitializeRenderer();
|
||||
|
||||
@ -320,21 +314,6 @@ namespace Ryujinx.Headless
|
||||
|
||||
if (_ticks >= _ticksPerFrame)
|
||||
{
|
||||
string dockedMode = Device.System.State.DockedMode ? "Docked" : "Handheld";
|
||||
float scale = GraphicsConfig.ResScale;
|
||||
if (scale != 1)
|
||||
{
|
||||
dockedMode += $" ({scale}x)";
|
||||
}
|
||||
|
||||
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
|
||||
Device.VSyncMode.ToString(),
|
||||
dockedMode,
|
||||
Device.Configuration.AspectRatio.ToText(),
|
||||
$"{Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
||||
$"FIFO: {Device.Statistics.GetFifoPercent():0.00} %",
|
||||
$"GPU: {_gpuDriverName}"));
|
||||
|
||||
_ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame);
|
||||
}
|
||||
}
|
||||
@ -434,9 +413,7 @@ namespace Ryujinx.Headless
|
||||
// Get screen touch position
|
||||
if (!_enableMouse)
|
||||
{
|
||||
hasTouch = TouchScreenManager.Update(true,
|
||||
(_inputManager.MouseDriver as SDL3MouseDriver).IsButtonPressed(MouseButton.Button1),
|
||||
_aspectRatio.ToFloat());
|
||||
hasTouch = TouchScreenManager.Update(true, (_inputManager.MouseDriver as SDL3MouseDriver).IsButtonPressed(MouseButton.Button1), _aspectRatio.ToFloat());
|
||||
}
|
||||
|
||||
if (!hasTouch)
|
||||
@ -459,13 +436,19 @@ namespace Ryujinx.Headless
|
||||
|
||||
InitializeWindow();
|
||||
|
||||
Thread renderLoopThread = new(Render) { Name = "GUI.RenderLoop", };
|
||||
Thread renderLoopThread = new(Render)
|
||||
{
|
||||
Name = "GUI.RenderLoop",
|
||||
};
|
||||
renderLoopThread.Start();
|
||||
|
||||
Thread nvidiaStutterWorkaround = null;
|
||||
if (Renderer is OpenGLRenderer)
|
||||
{
|
||||
nvidiaStutterWorkaround = new Thread(NvidiaStutterWorkaround) { Name = "GUI.NvidiaStutterWorkaround", };
|
||||
nvidiaStutterWorkaround = new Thread(NvidiaStutterWorkaround)
|
||||
{
|
||||
Name = "GUI.NvidiaStutterWorkaround",
|
||||
};
|
||||
nvidiaStutterWorkaround.Start();
|
||||
}
|
||||
|
||||
@ -505,24 +488,20 @@ namespace Ryujinx.Headless
|
||||
|
||||
public void DisplayCabinetMessageDialog()
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_INFORMATION, "Cabinet Dialog",
|
||||
"Please scan your Amiibo now.", WindowHandle);
|
||||
SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_INFORMATION, "Cabinet Dialog", "Please scan your Amiibo now.", WindowHandle);
|
||||
}
|
||||
|
||||
public bool DisplayMessageDialog(ControllerAppletUIArgs args)
|
||||
{
|
||||
if (_ignoreControllerApplet) return false;
|
||||
|
||||
string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
|
||||
|
||||
string playerCount = args.PlayerCountMin == args.PlayerCountMax
|
||||
? $"exactly {args.PlayerCountMin}"
|
||||
: $"{args.PlayerCountMin}-{args.PlayerCountMax}";
|
||||
|
||||
string message =
|
||||
$"Application requests {playerCount} {"player".ToQuantity(args.PlayerCountMin + args.PlayerCountMax, ShowQuantityAs.None)} with:\n\n"
|
||||
+ $"TYPES: {args.SupportedStyles}\n\n"
|
||||
+ $"PLAYERS: {string.Join(", ", args.SupportedPlayers)}\n\n"
|
||||
+ (args.IsDocked ? "Docked mode set. Handheld is also invalid.\n\n" : string.Empty)
|
||||
+ "Please reconfigure Input now and then press OK.";
|
||||
string message = $"Application requests {playerCount} {"player".ToQuantity(args.PlayerCountMin + args.PlayerCountMax, ShowQuantityAs.None)} with:\n\n"
|
||||
+ $"TYPES: {args.SupportedStyles}\n\n"
|
||||
+ $"PLAYERS: {string.Join(", ", args.SupportedPlayers)}\n\n"
|
||||
+ (args.IsDocked ? "Docked mode set. Handheld is also invalid.\n\n" : string.Empty)
|
||||
+ "Please reconfigure Input now and then press OK.";
|
||||
|
||||
return DisplayMessageDialog("Controller Applet", message);
|
||||
}
|
@ -170,7 +170,6 @@
|
||||
<EmbeddedResource Include="Assets\UIImages\Logo_GitHub_Light.png" />
|
||||
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx.png" />
|
||||
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx_AntiAlias.png" />
|
||||
<EmbeddedResource Include="Headless\Ryujinx.bmp" LogicalName="HeadlessLogo" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="Assets\locales.json" />
|
||||
|
@ -7,6 +7,7 @@
|
||||
Title="Ryujinx - Waiting"
|
||||
SizeToContent="WidthAndHeight"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Grid
|
||||
|
@ -22,5 +22,22 @@ namespace Ryujinx.Ava.UI.Models
|
||||
FifoStatus = fifoStatus;
|
||||
ShaderCount = shaderCount;
|
||||
}
|
||||
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is not StatusUpdatedEventArgs suea) return false;
|
||||
return
|
||||
VSyncMode == suea.VSyncMode &&
|
||||
VolumeStatus == suea.VolumeStatus &&
|
||||
DockedMode == suea.DockedMode &&
|
||||
AspectRatio == suea.AspectRatio &&
|
||||
GameStatus == suea.GameStatus &&
|
||||
FifoStatus == suea.FifoStatus &&
|
||||
ShaderCount == suea.ShaderCount;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
=> HashCode.Combine(VSyncMode, VolumeStatus, AspectRatio, DockedMode, FifoStatus, GameStatus, ShaderCount);
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +136,12 @@
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageBrazilianPortuguese}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageSwedish}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageNorwegian}" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
|
@ -32,6 +32,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -136,6 +137,8 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
NotificationHelper.SetNotificationManager(this);
|
||||
|
||||
Executor.ExecuteBackgroundAsync(ShowIntelMacWarningAsync);
|
||||
}
|
||||
|
||||
private void OnScalingChanged(object sender, EventArgs e)
|
||||
@ -731,5 +734,22 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
(int)Symbol.Checkmark);
|
||||
});
|
||||
}
|
||||
|
||||
private static bool _intelMacWarningShown;
|
||||
|
||||
public static async Task ShowIntelMacWarningAsync()
|
||||
{
|
||||
if (!_intelMacWarningShown &&
|
||||
(OperatingSystem.IsMacOS() &&
|
||||
(RuntimeInformation.OSArchitecture == Architecture.X64 ||
|
||||
RuntimeInformation.OSArchitecture == Architecture.X86)))
|
||||
{
|
||||
_intelMacWarningShown = true;
|
||||
|
||||
await Dispatcher.UIThread.InvokeAsync(async () => await ContentDialogHelper.CreateWarningDialog(
|
||||
"Intel Mac Warning",
|
||||
"Intel Macs are not supported and will not work properly.\nIf you continue, do not come to our Discord asking for support."));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user