SDL: Update game controller database on launch (#177)

Expands upon existing custom SDL mappings functionality: b82e789d4f

Downloads an updated game controller database (gamecontrollerdb.txt) on launch, which only updates when a new file is available. This keeps the database updated between SDL releases.

Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/177
This commit is contained in:
KeatonTheBot
2026-07-30 21:18:39 +00:00
committed by LotP
parent e3940abe01
commit 3f62488b26
+38 -1
View File
@@ -4,6 +4,7 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net.Http;
using System.Threading; using System.Threading;
using SDL; using SDL;
using static SDL.SDL3; using static SDL.SDL3;
@@ -43,6 +44,9 @@ namespace Ryujinx.SDL3.Common
private SDL3Driver() { } private SDL3Driver() { }
private static readonly HttpClient _httpClient = new();
private const string GamepadDbUrl = "https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt";
public void Initialize() public void Initialize()
{ {
lock (_lock) lock (_lock)
@@ -96,7 +100,9 @@ namespace Ryujinx.SDL3.Common
SDL_SetEventEnabled((uint)SDL_EventType.SDL_EVENT_GAMEPAD_SENSOR_UPDATE, false); SDL_SetEventEnabled((uint)SDL_EventType.SDL_EVENT_GAMEPAD_SENSOR_UPDATE, false);
string gamepadDbPath = Path.Combine(AppDataManager.BaseDirPath, "SDL_GameControllerDB.txt"); string gamepadDbPath = Path.Combine(AppDataManager.BaseDirPath, "gamecontrollerdb.txt");
UpdateGamepadDb(gamepadDbPath);
if (File.Exists(gamepadDbPath)) if (File.Exists(gamepadDbPath))
{ {
@@ -110,6 +116,37 @@ namespace Ryujinx.SDL3.Common
} }
} }
private static void UpdateGamepadDb(string gamepadDbPath)
{
try
{
byte[] remoteBytes = _httpClient.GetByteArrayAsync(GamepadDbUrl).GetAwaiter().GetResult();
bool shouldWrite = true;
if (File.Exists(gamepadDbPath))
{
byte[] localBytes = File.ReadAllBytes(gamepadDbPath);
if (localBytes.AsSpan().SequenceEqual(remoteBytes))
{
shouldWrite = false;
}
}
if (shouldWrite)
{
File.WriteAllBytes(gamepadDbPath ?? "", remoteBytes);
Logger.Info?.Print(LogClass.Application, "Updated gamepad database.");
}
}
catch (Exception ex)
{
Logger.Warning?.Print(LogClass.Application, $"Failed to check/download gamepad database, using existing local copy if present: {ex.Message}");
}
}
public bool RegisterWindow(SDL_WindowID windowId, Action<SDL_Event> windowEventHandler) public bool RegisterWindow(SDL_WindowID windowId, Action<SDL_Event> windowEventHandler)
{ {
return _registeredWindowHandlers.TryAdd(windowId, windowEventHandler); return _registeredWindowHandlers.TryAdd(windowId, windowEventHandler);