Skip to content

Commit

Permalink
hia: prevent infinite loading
Browse files Browse the repository at this point in the history
  • Loading branch information
GreemDev committed Dec 26, 2024
1 parent b13e9c8 commit 09a7fc0
Show file tree
Hide file tree
Showing 3 changed files with 382 additions and 299 deletions.
361 changes: 361 additions & 0 deletions src/Ryujinx/Headless/HeadlessRyujinx.Init.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,361 @@
using DiscordRPC;
using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Ava;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.GAL.Multithreading;
using Ryujinx.Graphics.OpenGL;
using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE;
using Ryujinx.Input;
using Ryujinx.UI.Common;
using Ryujinx.UI.Common.Configuration;
using Silk.NET.Vulkan;
using System;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
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
{
public partial class HeadlessRyujinx
{
public static void Initialize()
{
// Ensure Discord presence timestamp begins at the absolute start of when Ryujinx is launched
DiscordIntegrationModule.StartedAt = Timestamps.Now;

// Delete backup files after updating.
Task.Run(Updater.CleanupUpdate);

// Hook unhandled exception and process exit events.
AppDomain.CurrentDomain.UnhandledException += (sender, e)
=> Program.ProcessUnhandledException(sender, e.ExceptionObject as Exception, e.IsTerminating);
AppDomain.CurrentDomain.ProcessExit += (_, _) => Program.Exit();

// Initialize the configuration.
ConfigurationState.Initialize();

// Initialize Discord integration.
DiscordIntegrationModule.Initialize();

// Logging system information.
Program.PrintSystemInfo();
}

private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
{
if (inputId == null)
{
if (index == PlayerIndex.Player1)
{
Logger.Info?.Print(LogClass.Application, $"{index} not configured, defaulting to default keyboard.");

// Default to keyboard
inputId = "0";
}
else
{
Logger.Info?.Print(LogClass.Application, $"{index} not configured");

return null;
}
}

IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(inputId);

bool isKeyboard = true;

if (gamepad == null)
{
gamepad = _inputManager.GamepadDriver.GetGamepad(inputId);
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
{
bool isNintendoStyle = gamepadName.Contains("Nintendo");

config = new StandardControllerInputConfig
{
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;
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)
{
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");
}
}

return config;
}

private static IRenderer CreateRenderer(Options options, WindowBase window)

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / macOS Universal (Debug)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / macOS Universal (Debug)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / macOS Universal (Release)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / macOS Universal (Release)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-x64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-x64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-arm64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-arm64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / osx-x64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / osx-x64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-x64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-x64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-arm64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-arm64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / osx-x64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types

Check failure on line 284 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / osx-x64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'CreateRenderer' with the same parameter types
{
if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
{
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)

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / macOS Universal (Debug)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / macOS Universal (Debug)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / macOS Universal (Release)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / macOS Universal (Release)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-x64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-x64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-arm64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-arm64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / osx-x64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / osx-x64 (Debug)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-x64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-x64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-arm64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / linux-arm64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / osx-x64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types

Check failure on line 316 in src/Ryujinx/Headless/HeadlessRyujinx.Init.cs

View workflow job for this annotation

GitHub Actions / pr_build / osx-x64 (Release)

Type 'HeadlessRyujinx' already defines a member called 'InitializeEmulationContext' with the same parameter types
{
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);
}
}
}
Loading

0 comments on commit 09a7fc0

Please sign in to comment.