diff --git a/Ryujinx/Configuration.cs b/Ryujinx/Configuration.cs
index 4f7fbc9e0e..9f2a08d0bf 100644
--- a/Ryujinx/Configuration.cs
+++ b/Ryujinx/Configuration.cs
@@ -221,7 +221,7 @@ namespace Ryujinx
if (Instance.EnableFileLog)
{
Logger.AddTarget(new AsyncLogTargetWrapper(
- new FileLogTarget(Path.Combine(Program.ApplicationDirectory, "Ryujinx.log")),
+ new FileLogTarget(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.log")),
1000,
AsyncLogTargetOverflowAction.Block
));
@@ -253,7 +253,7 @@ namespace Ryujinx
}
}
- Program.DiscordIntegrationEnabled = SwitchConfig.EnableDiscordIntegration;
+ MainMenu.DiscordIntegrationEnabled = SwitchConfig.EnableDiscordIntergration;
device.EnableDeviceVsync = SwitchConfig.EnableVsync;
diff --git a/Ryujinx/GUI/GeneralSettings.cs b/Ryujinx/GUI/GeneralSettings.cs
index 7c41016bbb..bd137ded9d 100644
--- a/Ryujinx/GUI/GeneralSettings.cs
+++ b/Ryujinx/GUI/GeneralSettings.cs
@@ -9,7 +9,7 @@ namespace Ryujinx
{
public class GeneralSettings : Window
{
- internal HLE.Switch device { get; private set; }
+ private HLE.Switch device { get; set; }
internal static Configuration SwitchConfig { get; private set; }
diff --git a/Ryujinx/GUI/MainMenu.cs b/Ryujinx/GUI/MainMenu.cs
index 39aa3ebcff..2348d7e8fa 100644
--- a/Ryujinx/GUI/MainMenu.cs
+++ b/Ryujinx/GUI/MainMenu.cs
@@ -1,19 +1,35 @@
-using Gtk;
+using DiscordRPC;
+using Gtk;
using GUI = Gtk.Builder.ObjectAttribute;
+using Ryujinx.Audio;
using Ryujinx.Common.Logging;
+using Ryujinx.Graphics.Gal;
+using Ryujinx.Graphics.Gal.OpenGL;
+using Ryujinx.Profiler;
using System;
using System.IO;
+using System.Linq;
using System.Reflection;
namespace Ryujinx
{
public class MainMenu : Window
{
- internal HLE.Switch device { get; private set; }
+ public static bool DiscordIntegrationEnabled { get; set; }
- internal Application gtkapp { get; private set; }
+ public static DiscordRpcClient DiscordClient;
- internal ListStore TableStore { get; private set; }
+ public static RichPresence DiscordPresence;
+
+ private static IGalRenderer renderer;
+
+ private static IAalOutput audioOut;
+
+ private static HLE.Switch device { get; set; }
+
+ private static Application gtkapp { get; set; }
+
+ private static ListStore TableStore { get; set; }
//UI Controls
[GUI] Window MainWin;
@@ -23,52 +39,88 @@ namespace Ryujinx
[GUI] ScrolledWindow GameTableWindow;
[GUI] GLArea GLScreen;
- public MainMenu(HLE.Switch _device, Application _gtkapp) : this(new Builder("Ryujinx.GUI.MainMenu.glade"), _device, _gtkapp) { }
+ public MainMenu(string[] args, Application _gtkapp) : this(new Builder("Ryujinx.GUI.MainMenu.glade"), args, _gtkapp) { }
- private MainMenu(Builder builder, HLE.Switch _device, Application _gtkapp) : base(builder.GetObject("MainWin").Handle)
+ private MainMenu(Builder builder, string[] args, Application _gtkapp) : base(builder.GetObject("MainWin").Handle)
{
- device = _device;
+ renderer = new OglRenderer();
+
+ audioOut = InitializeAudioEngine();
+
+ device = new HLE.Switch(renderer, audioOut);
+
+ Configuration.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.jsonc"));
+ Configuration.InitialConfigure(device);
+
gtkapp = _gtkapp;
- if (Program.DiscordIntergrationEnabled)
- {
- Program.DiscordPresence.Details = "Main Menu";
- Program.DiscordPresence.State = "Idling";
- Program.DiscordPresence.Timestamps = new DiscordRPC.Timestamps(DateTime.UtcNow);
-
- Program.DiscordClient.SetPresence(Program.DiscordPresence);
- }
-
- builder.Autoconnect(this);
- MainWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.GUI.assets.ryujinxIcon.png");
- GameTableWindow.Show();
- GLScreen.Hide();
-
ApplyTheme();
DeleteEvent += Window_Close;
- //disable some buttons
- NFC.Sensitive = false;
- ControlSettingsMenu.Sensitive = false;
-
- //Games grid thing
- GameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 0);
- GameTable.AppendColumn("Game", new CellRendererText(), "text", 1);
- GameTable.AppendColumn("Version", new CellRendererText(), "text", 2);
- GameTable.AppendColumn("DLC", new CellRendererText(), "text", 3);
- GameTable.AppendColumn("Time Played", new CellRendererText(), "text", 4);
- GameTable.AppendColumn("Last Played", new CellRendererText(), "text", 5);
- GameTable.AppendColumn("Path", new CellRendererText(), "text", 6);
-
- TableStore = new ListStore(typeof(Gdk.Pixbuf), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string));
-
- foreach (ApplicationLibrary.ApplicationData AppData in ApplicationLibrary.ApplicationLibraryData)
+ if (DiscordIntegrationEnabled)
{
- TableStore.AppendValues(AppData.Icon, AppData.Game, AppData.Version, AppData.DLC, AppData.TP, AppData.LP, AppData.Path);
+ DiscordClient = new DiscordRpcClient("568815339807309834");
+ DiscordPresence = new RichPresence
+ {
+ Assets = new Assets
+ {
+ LargeImageKey = "ryujinx",
+ LargeImageText = "Ryujinx is an emulator for the Nintendo Switch"
+ },
+ Details = "Main Menu",
+ State = "Idling",
+ Timestamps = new Timestamps(DateTime.UtcNow)
+ };
+
+ DiscordClient.Initialize();
+ DiscordClient.SetPresence(DiscordPresence);
}
- GameTable.Model = TableStore;
+ builder.Autoconnect(this);
+ MainWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.GUI.assets.ryujinxIcon.png");
+
+ if (args.Length == 1)
+ {
+ GameTableWindow.Hide();
+ GLScreen.Show();
+
+ LoadApplication(args[0]);
+
+ using (GlScreen screen = new GlScreen(device, renderer))
+ {
+ screen.MainLoop();
+
+ Profile.FinishProfiling();
+
+ device.Dispose();
+ }
+ }
+ else
+ {
+ GameTableWindow.Show();
+ GLScreen.Hide();
+
+ NFC.Sensitive = false;
+ ControlSettingsMenu.Sensitive = false;
+
+ GameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 0);
+ GameTable.AppendColumn("Game", new CellRendererText(), "text", 1);
+ GameTable.AppendColumn("Version", new CellRendererText(), "text", 2);
+ GameTable.AppendColumn("DLC", new CellRendererText(), "text", 3);
+ GameTable.AppendColumn("Time Played", new CellRendererText(), "text", 4);
+ GameTable.AppendColumn("Last Played", new CellRendererText(), "text", 5);
+ GameTable.AppendColumn("Path", new CellRendererText(), "text", 6);
+
+ TableStore = new ListStore(typeof(Gdk.Pixbuf), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string));
+
+ foreach (ApplicationLibrary.ApplicationData AppData in ApplicationLibrary.ApplicationLibraryData)
+ {
+ TableStore.AppendValues(AppData.Icon, AppData.Game, AppData.Version, AppData.DLC, AppData.TP, AppData.LP, AppData.Path);
+ }
+
+ GameTable.Model = TableStore;
+ }
}
public static void ApplyTheme()
@@ -93,38 +145,98 @@ namespace Ryujinx
StyleContext.AddProviderForScreen(Gdk.Screen.Default, css_provider, 800);
}
+ private static void LoadApplication(string path)
+ {
+ if (Directory.Exists(path))
+ {
+ string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
+
+ if (romFsFiles.Length == 0)
+ {
+ romFsFiles = Directory.GetFiles(path, "*.romfs");
+ }
+
+ if (romFsFiles.Length > 0)
+ {
+ Logger.PrintInfo(LogClass.Application, "Loading as cart with RomFS.");
+ device.LoadCart(path, romFsFiles[0]);
+ }
+ else
+ {
+ Logger.PrintInfo(LogClass.Application, "Loading as cart WITHOUT RomFS.");
+ device.LoadCart(path);
+ }
+ }
+ else if (File.Exists(path))
+ {
+ switch (System.IO.Path.GetExtension(path).ToLowerInvariant())
+ {
+ case ".xci":
+ Logger.PrintInfo(LogClass.Application, "Loading as XCI.");
+ device.LoadXci(path);
+ break;
+ case ".nca":
+ Logger.PrintInfo(LogClass.Application, "Loading as NCA.");
+ device.LoadNca(path);
+ break;
+ case ".nsp":
+ case ".pfs0":
+ Logger.PrintInfo(LogClass.Application, "Loading as NSP.");
+ device.LoadNsp(path);
+ break;
+ default:
+ Logger.PrintInfo(LogClass.Application, "Loading as homebrew.");
+ device.LoadProgram(path);
+ break;
+ }
+ }
+ else
+ {
+ Logger.PrintWarning(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file");
+ }
+
+ if (DiscordIntegrationEnabled)
+ {
+ if (File.ReadAllLines(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "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);
+ }
+ }
+
//Events
private void Row_Activated(object obj, RowActivatedArgs args)
{
TableStore.GetIter(out TreeIter treeiter, new TreePath(args.Path.ToString()));
string path = (string)TableStore.GetValue(treeiter, 6);
- switch (System.IO.Path.GetExtension(path).ToLowerInvariant())
- {
- case ".xci":
- Logger.PrintInfo(LogClass.Application, "Loading as XCI.");
- device.LoadXci(path);
- break;
- case ".nca":
- Logger.PrintInfo(LogClass.Application, "Loading as NCA.");
- device.LoadNca(path);
- break;
- case ".nsp":
- case ".pfs0":
- Logger.PrintInfo(LogClass.Application, "Loading as NSP.");
- device.LoadNsp(path);
- break;
- default:
- Logger.PrintInfo(LogClass.Application, "Loading as homebrew.");
- device.LoadProgram(path);
- break;
- }
+ LoadApplication(path);
GameTableWindow.Hide();
GLScreen.Show();
Destroy();
- Application.Quit();
+
+ using (GlScreen screen = new GlScreen(device, renderer))
+ {
+ screen.MainLoop();
+
+ Profile.FinishProfiling();
+
+ device.Dispose();
+ }
+
+ audioOut.Dispose();
+ Logger.Shutdown();
}
private void Load_Application_File(object o, EventArgs args)
@@ -139,32 +251,24 @@ namespace Ryujinx
if (fc.Run() == (int)ResponseType.Accept)
{
- switch (System.IO.Path.GetExtension(fc.Filename).ToLowerInvariant())
- {
- case ".xci":
- Logger.PrintInfo(LogClass.Application, "Loading as XCI.");
- device.LoadXci(fc.Filename);
- break;
- case ".nca":
- Logger.PrintInfo(LogClass.Application, "Loading as NCA.");
- device.LoadNca(fc.Filename);
- break;
- case ".nsp":
- case ".pfs0":
- Logger.PrintInfo(LogClass.Application, "Loading as NSP.");
- device.LoadNsp(fc.Filename);
- break;
- default:
- Logger.PrintInfo(LogClass.Application, "Loading as homebrew.");
- device.LoadProgram(fc.Filename);
- break;
- }
+ LoadApplication(fc.Filename);
GameTableWindow.Hide();
GLScreen.Show();
Destroy();
- Application.Quit();
+
+ using (GlScreen screen = new GlScreen(device, renderer))
+ {
+ screen.MainLoop();
+
+ Profile.FinishProfiling();
+
+ device.Dispose();
+ }
+
+ audioOut.Dispose();
+ Logger.Shutdown();
}
fc.Destroy();
@@ -176,29 +280,24 @@ namespace Ryujinx
if (fc.Run() == (int)ResponseType.Accept)
{
- string[] romFsFiles = Directory.GetFiles(fc.Filename, "*.istorage");
-
- if (romFsFiles.Length == 0)
- {
- romFsFiles = Directory.GetFiles(fc.Filename, "*.romfs");
- }
-
- if (romFsFiles.Length > 0)
- {
- Logger.PrintInfo(LogClass.Application, "Loading as cart with RomFS.");
- device.LoadCart(fc.Filename, romFsFiles[0]);
- }
- else
- {
- Logger.PrintInfo(LogClass.Application, "Loading as cart WITHOUT RomFS.");
- device.LoadCart(fc.Filename);
- }
+ LoadApplication(fc.Filename);
GameTableWindow.Hide();
GLScreen.Show();
Destroy();
- Application.Quit();
+
+ using (GlScreen screen = new GlScreen(device, renderer))
+ {
+ screen.MainLoop();
+
+ Profile.FinishProfiling();
+
+ device.Dispose();
+ }
+
+ audioOut.Dispose();
+ Logger.Shutdown();
}
fc.Destroy();
@@ -206,11 +305,17 @@ namespace Ryujinx
private void Exit_Pressed(object o, EventArgs args)
{
+ audioOut.Dispose();
+ DiscordClient.Dispose();
+ Logger.Shutdown();
Environment.Exit(0);
}
private void Window_Close(object obj, DeleteEventArgs args)
{
+ audioOut.Dispose();
+ DiscordClient.Dispose();
+ Logger.Shutdown();
Environment.Exit(0);
}
@@ -252,5 +357,25 @@ namespace Ryujinx
about.Run();
about.Destroy();
}
+
+ ///
+ /// Picks an audio output renderer supported on this machine
+ ///
+ /// An supported by this machine
+ private static IAalOutput InitializeAudioEngine()
+ {
+ if (SoundIoAudioOut.IsSupported)
+ {
+ return new SoundIoAudioOut();
+ }
+ else if (OpenALAudioOut.IsSupported)
+ {
+ return new OpenALAudioOut();
+ }
+ else
+ {
+ return new DummyAudioOut();
+ }
+ }
}
}
diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs
index 3e9d1b5319..3cb594baf3 100644
--- a/Ryujinx/Program.cs
+++ b/Ryujinx/Program.cs
@@ -1,26 +1,12 @@
-using DiscordRPC;
-using Ryujinx.Audio;
-using Ryujinx.Common.Logging;
-using Ryujinx.Graphics.Gal;
-using Ryujinx.Graphics.Gal.OpenGL;
-using Ryujinx.HLE;
+using Ryujinx.Common.Logging;
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 bool DiscordIntegrationEnabled { get; set; }
-
- public static string ApplicationDirectory => AppDomain.CurrentDomain.BaseDirectory;
-
static void Main(string[] args)
{
Console.Title = "Ryujinx Console";
@@ -29,141 +15,26 @@ namespace Ryujinx
string systemPATH = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
Environment.SetEnvironmentVariable("Path", $"{Path.Combine(parentDir, "bin")};{systemPATH}");
- IGalRenderer renderer = new OglRenderer();
-
- IAalOutput audioOut = InitializeAudioEngine();
-
- Switch device = new Switch(renderer, audioOut);
-
- Configuration.Load(Path.Combine(ApplicationDirectory, "Config.jsonc"));
- Configuration.InitialConfigure(device);
+ AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
+ AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
Profile.Initialize();
ApplicationLibrary.Init();
- AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
- AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
+ var gtkapp = new Gtk.Application("Ryujinx.Ryujinx", GLib.ApplicationFlags.None);
+ var win = new MainMenu(args, gtkapp);
- if (DiscordIntegrationEnabled)
- {
- DiscordClient = new DiscordRpcClient("568815339807309834");
- DiscordPresence = new RichPresence
- {
- Assets = new Assets
- {
- LargeImageKey = "ryujinx",
- LargeImageText = "Ryujinx is an emulator for the Nintendo Switch"
- }
- };
+ gtkapp.Register(GLib.Cancellable.Current);
+ gtkapp.AddWindow(win);
+ win.Show();
- DiscordClient.Initialize();
- DiscordClient.SetPresence(DiscordPresence);
- }
-
- if (args.Length == 0)
- {
- Gtk.Application.Init();
-
- var gtkapp = new Gtk.Application("Ryujinx.Ryujinx", GLib.ApplicationFlags.None);
- var win = new MainMenu(device, gtkapp);
-
- gtkapp.Register(GLib.Cancellable.Current);
- gtkapp.AddWindow(win);
- win.Show();
-
- Gtk.Application.Run();
- }
-
- else
- {
- if (Directory.Exists(args[0]))
- {
- string[] romFsFiles = Directory.GetFiles(args[0], "*.istorage");
-
- if (romFsFiles.Length == 0)
- {
- romFsFiles = Directory.GetFiles(args[0], "*.romfs");
- }
-
- 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]);
- }
- }
- else if (File.Exists(args[0]))
- {
- switch (Path.GetExtension(args[0]).ToLowerInvariant())
- {
- case ".xci":
- Logger.PrintInfo(LogClass.Application, "Loading as XCI.");
- device.LoadXci(args[0]);
- break;
- case ".nca":
- Logger.PrintInfo(LogClass.Application, "Loading as NCA.");
- device.LoadNca(args[0]);
- break;
- case ".nsp":
- case ".pfs0":
- Logger.PrintInfo(LogClass.Application, "Loading as NSP.");
- device.LoadNsp(args[0]);
- break;
- default:
- Logger.PrintInfo(LogClass.Application, "Loading as homebrew.");
- device.LoadProgram(args[0]);
- break;
- }
- }
- else
- {
- Logger.PrintWarning(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file");
- }
- }
-
- if (DiscordIntegrationEnabled)
- {
- 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();
-
- Profile.FinishProfiling();
-
- device.Dispose();
- }
-
- audioOut.Dispose();
-
- Logger.Shutdown();
-
- DiscordClient.Dispose();
+ Gtk.Application.Run();
}
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
Logger.Shutdown();
-
- DiscordClient.Dispose();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
@@ -175,28 +46,6 @@ namespace Ryujinx
if (e.IsTerminating)
{
Logger.Shutdown();
-
- DiscordClient.Dispose();
- }
- }
-
- ///
- /// Picks an audio output renderer supported on this machine
- ///
- /// An supported by this machine
- private static IAalOutput InitializeAudioEngine()
- {
- if (SoundIoAudioOut.IsSupported)
- {
- return new SoundIoAudioOut();
- }
- else if (OpenALAudioOut.IsSupported)
- {
- return new OpenALAudioOut();
- }
- else
- {
- return new DummyAudioOut();
}
}
}