diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index e152846e..acb6b1d1 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -98,6 +98,10 @@ namespace Ryujinx.HLE.HOS public string CurrentTitle { get; private set; } + public string TitleName { get; private set; } + + public string TitleID { get; private set; } + public IntegrityCheckLevel FsIntegrityCheckLevel { get; set; } internal long HidBaseAddress { get; private set; } @@ -233,7 +237,7 @@ namespace Ryujinx.HLE.HOS } } - CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); + TitleID = CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); LoadNso("rtld"); LoadNso("main"); @@ -431,7 +435,7 @@ namespace Ryujinx.HLE.HOS } } - CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); + TitleID = CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); LoadNso("rtld"); LoadNso("main"); @@ -522,11 +526,12 @@ namespace Ryujinx.HLE.HOS Nacp controlData = new Nacp(controlFile.AsStream()); - CurrentTitle = controlData.Descriptions[(int)State.DesiredTitleLanguage].Title; + TitleName = CurrentTitle = controlData.Descriptions[(int)State.DesiredTitleLanguage].Title; + TitleID = metaData.Aci0.TitleId.ToString("x16"); if (string.IsNullOrWhiteSpace(CurrentTitle)) { - CurrentTitle = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; + TitleName = CurrentTitle = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } return controlData; @@ -538,7 +543,7 @@ namespace Ryujinx.HLE.HOS } else { - CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); + TitleID = CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); } LoadNso("rtld"); @@ -608,6 +613,9 @@ namespace Ryujinx.HLE.HOS ContentManager.LoadEntries(); + TitleID = CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); + TitleName = metaData.TitleName; + ProgramLoader.LoadStaticObjects(this, metaData, new IExecutable[] { staticObject }); } diff --git a/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs b/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs index d1d54d0e..436897ed 100644 --- a/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs +++ b/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs @@ -42,6 +42,8 @@ namespace Ryujinx.HLE.HOS.SystemState internal string ActiveAudioOutput { get; private set; } + public bool DiscordIntergrationEnabled { get; set; } + public bool DockedMode { get; set; } public ColorSet ThemeColor { get; set; } diff --git a/Ryujinx/Config.jsonc b/Ryujinx/Config.jsonc index 9dc46912..e362a0d4 100644 --- a/Ryujinx/Config.jsonc +++ b/Ryujinx/Config.jsonc @@ -32,6 +32,9 @@ // Enable or disable Docked Mode "docked_mode": false, + // Enable or disable Discord Rich Presense + "enable_discord_intergration": true, + // Enable or disable Game Vsync "enable_vsync": true, diff --git a/Ryujinx/Configuration.cs b/Ryujinx/Configuration.cs index 1c49de08..a5108544 100644 --- a/Ryujinx/Configuration.cs +++ b/Ryujinx/Configuration.cs @@ -72,6 +72,11 @@ namespace Ryujinx /// public bool DockedMode { get; private set; } + /// + /// Enables or disables Discord Rich Presense + /// + public bool EnableDiscordIntergration { get; private set; } + /// /// Enables or disables Vertical Sync /// @@ -198,6 +203,8 @@ namespace Ryujinx } } + device.System.State.DiscordIntergrationEnabled = Instance.EnableDiscordIntergration; + device.EnableDeviceVsync = Instance.EnableVsync; device.System.State.DockedMode = Instance.DockedMode; diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs index a72cd39e..6d8bbf39 100644 --- a/Ryujinx/Program.cs +++ b/Ryujinx/Program.cs @@ -1,4 +1,5 @@ -using Ryujinx.Audio; +using DiscordRPC; +using Ryujinx.Audio; using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gal.OpenGL; @@ -6,11 +7,16 @@ using Ryujinx.HLE; using Ryujinx.Profiler; using System; using System.IO; +using System.Linq; namespace Ryujinx { class Program { + public static DiscordRpcClient DiscordClient; + + public static RichPresence DiscordPresence; + public static string ApplicationDirectory => AppDomain.CurrentDomain.BaseDirectory; static void Main(string[] args) @@ -31,6 +37,22 @@ namespace Ryujinx AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; + if (device.System.State.DiscordIntergrationEnabled == true) + { + DiscordClient = new DiscordRpcClient("568815339807309834"); + DiscordPresence = new RichPresence + { + Assets = new Assets + { + LargeImageKey = "ryujinx", + LargeImageText = "Ryujinx is an emulator for the Nintendo Switch" + } + }; + + DiscordClient.Initialize(); + DiscordClient.SetPresence(DiscordPresence); + } + if (args.Length == 1) { if (Directory.Exists(args[0])) @@ -45,13 +67,11 @@ namespace Ryujinx if (romFsFiles.Length > 0) { Logger.PrintInfo(LogClass.Application, "Loading as cart with RomFS."); - device.LoadCart(args[0], romFsFiles[0]); } else { Logger.PrintInfo(LogClass.Application, "Loading as cart WITHOUT RomFS."); - device.LoadCart(args[0]); } } @@ -88,6 +108,23 @@ namespace Ryujinx Logger.PrintWarning(LogClass.Application, "Please specify the folder with the NSOs/IStorage or a NSO/NRO."); } + if (device.System.State.DiscordIntergrationEnabled == true) + { + if (File.ReadAllLines(Path.Combine(ApplicationDirectory, "RPsupported.dat")).Contains(device.System.TitleID)) + { + DiscordPresence.Assets.LargeImageKey = device.System.TitleID; + } + + DiscordPresence.Details = $"Playing {device.System.TitleName}"; + DiscordPresence.State = device.System.TitleID.ToUpper(); + DiscordPresence.Assets.LargeImageText = device.System.TitleName; + DiscordPresence.Assets.SmallImageKey = "ryujinx"; + DiscordPresence.Assets.SmallImageText = "Ryujinx is an emulator for the Nintendo Switch"; + DiscordPresence.Timestamps = new Timestamps(DateTime.UtcNow); + + DiscordClient.SetPresence(DiscordPresence); + } + using (GlScreen screen = new GlScreen(device, renderer)) { screen.MainLoop(); @@ -100,11 +137,15 @@ namespace Ryujinx audioOut.Dispose(); Logger.Shutdown(); + + DiscordClient.Dispose(); } private static void CurrentDomain_ProcessExit(object sender, EventArgs e) { Logger.Shutdown(); + + DiscordClient.Dispose(); } private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) @@ -116,6 +157,8 @@ namespace Ryujinx if (e.IsTerminating) { Logger.Shutdown(); + + DiscordClient.Dispose(); } } diff --git a/Ryujinx/RPsupported.dat b/Ryujinx/RPsupported.dat new file mode 100644 index 00000000..ad2d715d --- /dev/null +++ b/Ryujinx/RPsupported.dat @@ -0,0 +1,38 @@ +01000d200ac0c000 +01000d700be88000 +01000dc007e90000 +01000e2003fa0000 +01002fc00c6d0000 +0100225000fee000 +010028d0045ce000 +01002b30028f6000 +010034e005c9c000 +01004f8006a78000 +010051f00ac5e000 +0100574009f9e000 +0100628004bce000 +0100633007d48000 +010065500b218000 +010068f00aa78000 +01006a800016e000 +01007330027ee000 +0100749009844000 +01007a4008486000 +010080b00ad66000 +010094e00b52e000 +01009aa000faa000 +0100a4200a284000 +0100a5c00d162000 +0100ae000aebc000 +0100b3f000be2000 +0100bc2004ff4000 +0100cf3007578000 +0100d5d00c6be000 +0100d6b00cd88000 +0100d870045b6000 +0100e0c00adac000 +0100e7200b272000 +0100e9f00b882000 +0100eab00605c000 +0100efd00a4fa000 +0100f6a00a684000 \ No newline at end of file diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj index ab0ee599..4ff06fa0 100644 --- a/Ryujinx/Ryujinx.csproj +++ b/Ryujinx/Ryujinx.csproj @@ -19,6 +19,7 @@ + @@ -35,6 +36,9 @@ PreserveNewest + + PreserveNewest + diff --git a/Ryujinx/_schema.json b/Ryujinx/_schema.json index f07f930b..1eb046b3 100644 --- a/Ryujinx/_schema.json +++ b/Ryujinx/_schema.json @@ -368,6 +368,17 @@ false ] }, + "enable_discord_intergration": { + "$id": "#/properties/enable_discord_intergration", + "type": "boolean", + "title": "Enable Discord Rich Presense", + "description": "Enable or disable Discord Rich Presense", + "default": true, + "examples": [ + true, + false + ] + }, "enable_vsync": { "$id": "#/properties/enable_vsync", "type": "boolean",