diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs
index e152846e42..acb6b1d18f 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 d1d54d0eaf..436897edba 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 9dc46912b4..e362a0d459 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 1c49de0803..a51085448c 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 a72cd39e0f..6d8bbf39c5 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 0000000000..ad2d715df0
--- /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 ab0ee599e1..4ff06fa073 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 f07f930b6f..1eb046b3cb 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",