Compare commits

..

7 Commits

Author SHA1 Message Date
Evan Husted
3f12727ef8 input: LED rainbow now updates the LED with the normal gamepad update loop instead of subscribing to an updated event for the rainbow color in SetConfiguration. 2025-01-25 23:13:51 -06:00
Evan Husted
8bfcebebf1 Merge remote-tracking branch 'origin/master' 2025-01-25 22:44:26 -06:00
Evan Husted
e3f20abd23 UI: RPC: Maintain game started timestamp for the duration of the AppHost 2025-01-25 22:44:16 -06:00
Daenorth
0c36bcd7d4 Added more titles to RPC (#569)
Added some more titles to the RPC environment

-Brawlhalla
-Minecraft
-Risk
-Stardew Vallet
-Valkyria Chronicles 4
-Super bomberman R
-Arcade archives Super mario bros
-Divinity Original sin 2 DE
-Monopoly
-titan Quest
2025-01-25 22:02:24 -06:00
shinyoyo
050b9a0da4 Updated Zh_CN Simplified Chinese (#578) 2025-01-25 21:59:20 -06:00
Dehunc
a1291f1061 Improved Simplified Chinese translation (#568)
Co-authored-by: Cwood <Cwood@DoVirt.org>
2025-01-25 21:59:06 -06:00
Otozinclus
f15aa8fba0 Fix LED turning on in input settings, despite TurnOffLed being set to true (#583)
The ColorPicker auotmatically sets the LED to the selected Color
whenever the Input Settings are opened. Therefore it now checks if the
setting is turned off before changing the color.
2025-01-25 17:15:17 -06:00
9 changed files with 104 additions and 87 deletions

View File

@@ -105,6 +105,7 @@ namespace Ryujinx.Common
"0100b04011742000", // Monster Hunter Rise "0100b04011742000", // Monster Hunter Rise
//Mario Franchise //Mario Franchise
"010021d00812a000", // Arcade Archives VS. SUPER MARIO BROS.
"01006d0017f7a000", // Mario & Luigi: Brothership "01006d0017f7a000", // Mario & Luigi: Brothership
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020 "010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
"010067300059a000", // Mario + Rabbids: Kingdom Battle "010067300059a000", // Mario + Rabbids: Kingdom Battle
@@ -212,32 +213,41 @@ namespace Ryujinx.Common
//Misc Games //Misc Games
"010056e00853a000", // A Hat in Time "010056e00853a000", // A Hat in Time
"0100fd1014726000", // Baldurs Gate: Dark Alliance "0100fd1014726000", // Baldurs Gate: Dark Alliance
"0100c6800b934000", // Brawlhalla
"0100dbf01000a000", // Burnout Paradise Remastered "0100dbf01000a000", // Burnout Paradise Remastered
"0100744001588000", // Cars 3: Driven to Win "0100744001588000", // Cars 3: Driven to Win
"0100b41013c82000", // Cruis'n Blast "0100b41013c82000", // Cruis'n Blast
"010085900337e000", // Death Squared "010085900337e000", // Death Squared
"01001b300b9be000", // Diablo III: Eternal Collection "01001b300b9be000", // Diablo III: Eternal Collection
"010027400cdc6000", // Divinity Original 2 - Definitive Edition
"01008c8012920000", // Dying Light Platinum Edition "01008c8012920000", // Dying Light Platinum Edition
"01001cc01b2d4000", // Goat Simulator 3 "01001cc01b2d4000", // Goat Simulator 3
"01003620068ea000", // Hand of Fate 2 "01003620068ea000", // Hand of Fate 2
"010085500130a000", // Lego City: Undercover "010085500130a000", // Lego City: Undercover
"010073c01af34000", // LEGO Horizon Adventures "010073c01af34000", // LEGO Horizon Adventures
"0100d71004694000", // Minecraft
"01007430037f6000", // Monopoly
"0100853015e86000", // No Man's Sky "0100853015e86000", // No Man's Sky
"01007bb017812000", // Portal "01007bb017812000", // Portal
"0100abd01785c000", // Portal 2 "0100abd01785c000", // Portal 2
"01008e200c5c2000", // Muse Dash "01008e200c5c2000", // Muse Dash
"01007820196a6000", // Red Dead Redemption "01007820196a6000", // Red Dead Redemption
"0100e8300a67a000", // Risk
"01002f7013224000", // Rune Factory 5 "01002f7013224000", // Rune Factory 5
"01008d100d43e000", // Saints Row IV "01008d100d43e000", // Saints Row IV
"0100de600beee000", // Saints Row: The Third - The Full Package "0100de600beee000", // Saints Row: The Third - The Full Package
"01001180021fa000", // Shovel Knight: Specter of Torment "01001180021fa000", // Shovel Knight: Specter of Torment
"0100e65002bb8000", // Stardew Valley
"0100d7a01b7a2000", // Star Wars: Bounty Hunter "0100d7a01b7a2000", // Star Wars: Bounty Hunter
"0100800015926000", // Suika Game "0100800015926000", // Suika Game
"01007ad00013e000", // Super Bomberman R
"0100e46006708000", // Terraria "0100e46006708000", // Terraria
"0100605008268000", // Titan Quest
"01000a10041ea000", // The Elder Scrolls V: Skyrim "01000a10041ea000", // The Elder Scrolls V: Skyrim
"010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon- "010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon-
"010080b00ad66000", // Undertale "010080b00ad66000", // Undertale
"010069401adb8000", // Unicorn Overlord "010069401adb8000", // Unicorn Overlord
"01005c600ac68000", // Valkyria Chronicles 4
"0100534009ff2000", // Yonder - The cloud catcher chronicles "0100534009ff2000", // Yonder - The cloud catcher chronicles
]; ];
} }

View File

@@ -1,6 +1,7 @@
using Gommon; using Gommon;
using System; using System;
using System.Drawing; using System.Drawing;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Common.Utilities namespace Ryujinx.Common.Utilities
@@ -18,7 +19,7 @@ namespace Ryujinx.Common.Utilities
{ {
while (CyclingEnabled) while (CyclingEnabled)
{ {
await Task.Delay(15); await Task.Delay(20);
Tick(); Tick();
} }
}); });
@@ -33,28 +34,46 @@ namespace Ryujinx.Common.Utilities
public static float Speed { get; set; } = 1; public static float Speed { get; set; } = 1;
public static Color Color { get; private set; } = Color.Blue; private static readonly Lock _lock = new();
private static Color _color = Color.Blue;
public static ref Color Color
{
get
{
lock (_lock)
{
return ref _color;
}
}
}
public static void Tick() public static void Tick()
{ {
Color = HsbToRgb((Color.GetHue() + Speed) / 360); lock (_lock)
{
_color = HsbToRgb((_color.GetHue() + Speed) / 360);
UpdatedHandler.Call(Color.ToArgb()); _updatedHandler.Call(_color.ToArgb());
}
} }
public static void Reset() public static void Reset()
{ {
Color = Color.Blue; _updatedHandler.Clear();
UpdatedHandler.Clear();
lock (_lock)
_color = Color.Blue;
} }
public static event Action<int> Updated public static event Action<int> Updated
{ {
add => UpdatedHandler.Add(value); add => _updatedHandler.Add(value);
remove => UpdatedHandler.Remove(value); remove => _updatedHandler.Remove(value);
} }
internal static Event<int> UpdatedHandler = new(); private static readonly Event<int> _updatedHandler = new();
private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1) private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1)
{ {

View File

@@ -148,8 +148,6 @@ namespace Ryujinx.Input.SDL2
{ {
if (disposing && _gamepadHandle != nint.Zero) if (disposing && _gamepadHandle != nint.Zero)
{ {
Rainbow.Updated -= RainbowColorChanged;
SDL_GameControllerClose(_gamepadHandle); SDL_GameControllerClose(_gamepadHandle);
_gamepadHandle = nint.Zero; _gamepadHandle = nint.Zero;
@@ -228,15 +226,6 @@ namespace Ryujinx.Input.SDL2
private static Vector3 GsToMs2(Vector3 gs) => gs / SDL_STANDARD_GRAVITY; private static Vector3 GsToMs2(Vector3 gs) => gs / SDL_STANDARD_GRAVITY;
private void RainbowColorChanged(int packedRgb)
{
if (!_configuration.Led.UseRainbow) return;
SetLed((uint)packedRgb);
}
private bool _rainbowColorEnabled;
public void SetConfiguration(InputConfig configuration) public void SetConfiguration(InputConfig configuration)
{ {
lock (_userMappingLock) lock (_userMappingLock)
@@ -247,19 +236,10 @@ namespace Ryujinx.Input.SDL2
{ {
if (_configuration.Led.TurnOffLed) if (_configuration.Led.TurnOffLed)
(this as IGamepad).ClearLed(); (this as IGamepad).ClearLed();
else switch (_configuration.Led.UseRainbow) else if (_configuration.Led.UseRainbow)
{ SetLed((uint)Rainbow.Color.ToArgb());
case true when !_rainbowColorEnabled:
Rainbow.Updated += RainbowColorChanged;
_rainbowColorEnabled = true;
break;
case false when _rainbowColorEnabled:
Rainbow.Updated -= RainbowColorChanged;
_rainbowColorEnabled = false;
break;
}
if (!_configuration.Led.TurnOffLed && !_rainbowColorEnabled) if (!_configuration.Led.TurnOffLed && !_configuration.Led.UseRainbow)
SetLed(_configuration.Led.LedColor); SetLed(_configuration.Led.LedColor);
} }

View File

@@ -3,6 +3,7 @@ using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Threading; using Avalonia.Threading;
using DiscordRPC;
using LibHac.Common; using LibHac.Common;
using LibHac.Ns; using LibHac.Ns;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
@@ -595,6 +596,8 @@ namespace Ryujinx.Ava
gamepad?.Dispose(); gamepad?.Dispose();
} }
DiscordIntegrationModule.GuestAppStartedAt = null;
Rainbow.Disable(); Rainbow.Disable();
Rainbow.Reset(); Rainbow.Reset();
@@ -685,6 +688,8 @@ namespace Ryujinx.Ava
public async Task<bool> LoadGuestApplication(BlitStruct<ApplicationControlProperty>? customNacpData = null) public async Task<bool> LoadGuestApplication(BlitStruct<ApplicationControlProperty>? customNacpData = null)
{ {
DiscordIntegrationModule.GuestAppStartedAt = Timestamps.Now;
InitEmulatedSwitch(); InitEmulatedSwitch();
MainWindow.UpdateGraphicsConfig(); MainWindow.UpdateGraphicsConfig();

View File

@@ -593,7 +593,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
"zh_CN": "", "zh_CN": "启动游戏时隐藏 UI",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -768,7 +768,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Сканувати Amiibo (з теки Bin)", "uk_UA": "Сканувати Amiibo (з теки Bin)",
"zh_CN": "从bin文件扫描 Amiibo", "zh_CN": "扫描 Amiibo (从 bin 文件)",
"zh_TW": "掃瞄 Amiibo (從 Bin 檔案)" "zh_TW": "掃瞄 Amiibo (從 Bin 檔案)"
} }
}, },
@@ -818,7 +818,7 @@
"th_TH": "ติดตั้งเฟิร์มแวร์จาก ไฟล์ XCI หรือ ไฟล์ ZIP", "th_TH": "ติดตั้งเฟิร์มแวร์จาก ไฟล์ XCI หรือ ไฟล์ ZIP",
"tr_TR": "XCI veya ZIP'ten Yazılım Yükle", "tr_TR": "XCI veya ZIP'ten Yazılım Yükle",
"uk_UA": "Встановити прошивку з XCI або ZIP", "uk_UA": "Встановити прошивку з XCI або ZIP",
"zh_CN": "从 XCI 或 ZIP 文件安装系统固件", "zh_CN": "从 XCI 或 ZIP 文件安装系统固件",
"zh_TW": "從 XCI 或 ZIP 安裝韌體" "zh_TW": "從 XCI 或 ZIP 安裝韌體"
} }
}, },
@@ -843,7 +843,7 @@
"th_TH": "ติดตั้งเฟิร์มแวร์จากไดเร็กทอรี", "th_TH": "ติดตั้งเฟิร์มแวร์จากไดเร็กทอรี",
"tr_TR": "Bir Dizin Üzerinden Yazılım Yükle", "tr_TR": "Bir Dizin Üzerinden Yazılım Yükle",
"uk_UA": "Встановити прошивку з теки", "uk_UA": "Встановити прошивку з теки",
"zh_CN": "从文件夹安装系统固件", "zh_CN": "从文件夹安装系统固件",
"zh_TW": "從資料夾安裝韌體" "zh_TW": "從資料夾安裝韌體"
} }
}, },
@@ -893,7 +893,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Встановити ключі з файлу .KEYS або .ZIP", "uk_UA": "Встановити ключі з файлу .KEYS або .ZIP",
"zh_CN": "从.KEYS文件或ZIP压缩包安装密匙", "zh_CN": "从 .KEYS 文件或 .ZIP 压缩包安装密匙",
"zh_TW": "從 .KEYS 或 .ZIP 安裝金鑰" "zh_TW": "從 .KEYS 或 .ZIP 安裝金鑰"
} }
}, },
@@ -1018,7 +1018,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Обрізати XCI файли", "uk_UA": "Обрізати XCI файли",
"zh_CN": "XCI文件瘦身", "zh_CN": "瘦身 XCI 文件",
"zh_TW": "修剪 XCI 檔案" "zh_TW": "修剪 XCI 檔案"
} }
}, },
@@ -1293,7 +1293,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Відкриває сторінку з Посібником по усуненню помилок та несправностей на офіційній вікі-сторінці Ryujinx (англійською)", "uk_UA": "Відкриває сторінку з Посібником по усуненню помилок та несправностей на офіційній вікі-сторінці Ryujinx (англійською)",
"zh_CN": "打开Ryujinx官方wiki的常见问题和问题排除页面", "zh_CN": "打开 Ryujinx 官方 Wiki 的常见问题和问题排除页面",
"zh_TW": "開啟官方 Ryujinx Wiki 常見問題 (FAQ) 和疑難排解頁面" "zh_TW": "開啟官方 Ryujinx Wiki 常見問題 (FAQ) 和疑難排解頁面"
} }
}, },
@@ -1343,7 +1343,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Відкриває посібник з Налаштування та конфігурації на офіційній вікі-сторінці Ryujinx (англійською)", "uk_UA": "Відкриває посібник з Налаштування та конфігурації на офіційній вікі-сторінці Ryujinx (англійською)",
"zh_CN": "打开Ryujinx官方wiki的安装与配置指南", "zh_CN": "打开 Ryujinx 官方 Wiki 的安装与配置指南",
"zh_TW": "開啟官方 Ryujinx Wiki 設定和配置指南" "zh_TW": "開啟官方 Ryujinx Wiki 設定和配置指南"
} }
}, },
@@ -1393,7 +1393,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Відкриває посібник з налаштування Мультиплеєру на офіційній вікі-сторінці Ryujinx (англійською)", "uk_UA": "Відкриває посібник з налаштування Мультиплеєру на офіційній вікі-сторінці Ryujinx (англійською)",
"zh_CN": "打开Ryujinx官方wiki的多人游戏指南", "zh_CN": "打开 Ryujinx 官方 Wiki 的多人游戏指南",
"zh_TW": "開啟官方 Ryujinx Wiki 多人遊戲 (LDN/LAN) 指南" "zh_TW": "開啟官方 Ryujinx Wiki 多人遊戲 (LDN/LAN) 指南"
} }
}, },
@@ -1443,7 +1443,7 @@
"th_TH": "กำลังค้นหา...", "th_TH": "กำลังค้นหา...",
"tr_TR": "Ara...", "tr_TR": "Ara...",
"uk_UA": "Пошук...", "uk_UA": "Пошук...",
"zh_CN": "搜索", "zh_CN": "搜索...",
"zh_TW": "搜尋..." "zh_TW": "搜尋..."
} }
}, },
@@ -2343,7 +2343,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
"zh_CN": "", "zh_CN": "从选定的 DLC 文件中解压 RomFS",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -2693,7 +2693,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Обрізається XCI Файлів '{0}'", "uk_UA": "Обрізається XCI Файлів '{0}'",
"zh_CN": "XCI文件瘦身中'{0}'", "zh_CN": "正在瘦身 XCI 文件 '{0}'",
"zh_TW": "正在修剪 XCI 檔案 '{0}'" "zh_TW": "正在修剪 XCI 檔案 '{0}'"
} }
}, },
@@ -3218,7 +3218,7 @@
"th_TH": "โหลดไดเรกทอรี DLC/ไฟล์อัปเดต อัตโนมัติ", "th_TH": "โหลดไดเรกทอรี DLC/ไฟล์อัปเดต อัตโนมัติ",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Автозавантаження теки DLC/Оновлень", "uk_UA": "Автозавантаження теки DLC/Оновлень",
"zh_CN": "自动加载DLC/游戏更新目录", "zh_CN": "自动加载 DLC游戏更新目录",
"zh_TW": "自動載入 DLC/遊戲更新資料夾" "zh_TW": "自動載入 DLC/遊戲更新資料夾"
} }
}, },
@@ -3243,7 +3243,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "DLC та Оновлення, які посилаються на відсутні файли, будуть автоматично вимкнуті.", "uk_UA": "DLC та Оновлення, які посилаються на відсутні файли, будуть автоматично вимкнуті.",
"zh_CN": "DLC/游戏更新可自动加载和卸载", "zh_CN": "DLC游戏更新 可自动加载和卸载",
"zh_TW": "遺失的 DLC 及遊戲更新檔案將會在自動載入中移除" "zh_TW": "遺失的 DLC 及遊戲更新檔案將會在自動載入中移除"
} }
}, },
@@ -7668,7 +7668,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
"zh_CN": "", "zh_CN": "关闭",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -7693,7 +7693,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
"zh_CN": "", "zh_CN": "彩虹",
"zh_TW": "" "zh_TW": ""
} }
}, },
@@ -23043,7 +23043,7 @@
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
"zh_CN": "", "zh_CN": "选择一个要解压的 DLC",
"zh_TW": "" "zh_TW": ""
} }
} }

View File

@@ -14,7 +14,8 @@ namespace Ryujinx.Ava
{ {
public static class DiscordIntegrationModule public static class DiscordIntegrationModule
{ {
public static Timestamps StartedAt { get; set; } public static Timestamps EmulatorStartedAt { get; set; }
public static Timestamps GuestAppStartedAt { get; set; }
private static string VersionString private static string VersionString
=> (ReleaseInformation.IsCanaryBuild ? "Canary " : string.Empty) + $"v{ReleaseInformation.Version}"; => (ReleaseInformation.IsCanaryBuild ? "Canary " : string.Empty) + $"v{ReleaseInformation.Version}";
@@ -43,7 +44,7 @@ namespace Ryujinx.Ava
}, },
Details = "Main Menu", Details = "Main Menu",
State = "Idling", State = "Idling",
Timestamps = StartedAt Timestamps = EmulatorStartedAt
}; };
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update; ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
@@ -100,7 +101,7 @@ namespace Ryujinx.Ava
State = appMeta.LastPlayed.HasValue && appMeta.TimePlayed.TotalSeconds > 5 State = appMeta.LastPlayed.HasValue && appMeta.TimePlayed.TotalSeconds > 5
? $"Total play time: {ValueFormatUtils.FormatTimeSpan(appMeta.TimePlayed)}" ? $"Total play time: {ValueFormatUtils.FormatTimeSpan(appMeta.TimePlayed)}"
: "Never played", : "Never played",
Timestamps = Timestamps.Now Timestamps = GuestAppStartedAt ??= Timestamps.Now
}); });
} }

View File

@@ -33,7 +33,7 @@ namespace Ryujinx.Headless
public static void Initialize() public static void Initialize()
{ {
// Ensure Discord presence timestamp begins at the absolute start of when Ryujinx is launched // Ensure Discord presence timestamp begins at the absolute start of when Ryujinx is launched
DiscordIntegrationModule.StartedAt = Timestamps.Now; DiscordIntegrationModule.EmulatorStartedAt = Timestamps.Now;
// Delete backup files after updating. // Delete backup files after updating.
Task.Run(Updater.CleanupUpdate); Task.Run(Updater.CleanupUpdate);

View File

@@ -94,7 +94,7 @@ namespace Ryujinx.Ava
private static void Initialize(string[] args) private static void Initialize(string[] args)
{ {
// Ensure Discord presence timestamp begins at the absolute start of when Ryujinx is launched // Ensure Discord presence timestamp begins at the absolute start of when Ryujinx is launched
DiscordIntegrationModule.StartedAt = Timestamps.Now; DiscordIntegrationModule.EmulatorStartedAt = Timestamps.Now;
// Parse arguments // Parse arguments
CommandLineState.ParseArguments(args); CommandLineState.ParseArguments(args);

View File

@@ -252,6 +252,7 @@ namespace Ryujinx.Ava.UI.Views.Input
if (!args.NewColor.HasValue) return; if (!args.NewColor.HasValue) return;
if (DataContext is not ControllerInputViewModel cVm) return; if (DataContext is not ControllerInputViewModel cVm) return;
if (!cVm.Config.EnableLedChanging) return; if (!cVm.Config.EnableLedChanging) return;
if (cVm.Config.TurnOffLed) return;
cVm.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32()); cVm.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32());
} }
@@ -260,6 +261,7 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
if (DataContext is not ControllerInputViewModel cVm) return; if (DataContext is not ControllerInputViewModel cVm) return;
if (!cVm.Config.EnableLedChanging) return; if (!cVm.Config.EnableLedChanging) return;
if (cVm.Config.TurnOffLed) return;
cVm.ParentModel.SelectedGamepad.SetLed(cVm.Config.LedColor.ToUInt32()); cVm.ParentModel.SelectedGamepad.SetLed(cVm.Config.LedColor.ToUInt32());
} }