static void Main(string[] args) { // Parse Arguments. string launchPathArg = null; string baseDirPathArg = null; bool startFullscreenArg = false; for (int i = 0; i < args.Length; ++i) { string arg = args[i]; if (arg == "-r" || arg == "--root-data-dir") { if (i + 1 >= args.Length) { Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'"); continue; } baseDirPathArg = args[++i]; } else if (arg == "-f" || arg == "--fullscreen") { startFullscreenArg = true; } else if (launchPathArg == null) { launchPathArg = arg; } } // Make process DPI aware for proper window sizing on high-res screens. ForceDpiAware.Windows(); WindowScaleFactor = ForceDpiAware.GetWindowScaleFactor(); // Delete backup files after updating. Task.Run(Updater.CleanupUpdate); Toolkit.Init(new ToolkitOptions { Backend = PlatformBackend.PreferNative }); Version = Assembly.GetEntryAssembly().GetCustomAttribute <AssemblyInformationalVersionAttribute>().InformationalVersion; Console.Title = $"Ryujinx Console {Version}"; string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine); Environment.SetEnvironmentVariable("Path", $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")};{systemPath}"); // Hook unhandled exception and process exit events. GLib.ExceptionManager.UnhandledException += (GLib.UnhandledExceptionArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating); AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating); AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit(); // Setup base data directory. AppDataManager.Initialize(baseDirPathArg); // Initialize the configuration. ConfigurationState.Initialize(); // Initialize the logger system. LoggerModule.Initialize(); // Initialize Discord integration. DiscordIntegrationModule.Initialize(); string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"); string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, "Config.json"); // Now load the configuration as the other subsystems are now registered ConfigurationPath = File.Exists(localConfigurationPath) ? localConfigurationPath : File.Exists(appDataConfigurationPath) ? appDataConfigurationPath : null; if (ConfigurationPath == null) { // No configuration, we load the default values and save it to disk ConfigurationPath = appDataConfigurationPath; ConfigurationState.Instance.LoadDefault(); ConfigurationState.Instance.ToFileFormat().SaveConfig(ConfigurationPath); } else { if (ConfigurationFileFormat.TryLoad(ConfigurationPath, out ConfigurationFileFormat configurationFileFormat)) { ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath); } else { ConfigurationState.Instance.LoadDefault(); Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location {ConfigurationPath}"); } } if (startFullscreenArg) { ConfigurationState.Instance.Ui.StartFullscreen.Value = true; } // Logging system information. PrintSystemInfo(); // Initialize Gtk. Application.Init(); // Check if keys exists. bool hasGlobalProdKeys = File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")); bool hasAltProdKeys = !AppDataManager.IsCustomBasePath && File.Exists(Path.Combine(AppDataManager.KeysDirPathAlt, "prod.keys")); if (!hasGlobalProdKeys && !hasAltProdKeys) { UserErrorDialog.CreateUserErrorDialog(UserError.NoKeys); } // Force dedicated GPU if we can. ForceDedicatedGpu.Nvidia(); // Show the main window UI. MainWindow mainWindow = new MainWindow(); mainWindow.Show(); if (launchPathArg != null) { mainWindow.LoadApplication(launchPathArg); } if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false)) { _ = Updater.BeginParse(mainWindow, false); } Application.Run(); }