using Ryujinx.Audio; using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gal.OpenGL; using Ryujinx.HLE; using System; using System.IO; namespace Ryujinx { class Program { public static string ApplicationDirectory => AppDomain.CurrentDomain.BaseDirectory; static void Main(string[] args) { Console.Title = "Ryujinx Console"; IGalRenderer renderer = new OGLRenderer(); IAalOutput audioOut = InitializeAudioEngine(); Switch device = new Switch(renderer, audioOut); Configuration.Load(Path.Combine(ApplicationDirectory, "Config.jsonc")); Configuration.Configure(device); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; if (args.Length == 1) { 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"); } } else { Logger.PrintWarning(LogClass.Application, "Please specify the folder with the NSOs/IStorage or a NSO/NRO."); } using (GlScreen screen = new GlScreen(device, renderer)) { screen.MainLoop(); device.Dispose(); } audioOut.Dispose(); Logger.Shutdown(); } private static void CurrentDomain_ProcessExit(object sender, EventArgs e) { Logger.Shutdown(); } private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { var exception = e.ExceptionObject as Exception; Logger.PrintError(LogClass.Emulation, $"Unhandled exception caught: {exception}"); if (e.IsTerminating) { Logger.Shutdown(); } } /// /// 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(); } } } }