public void LoadApplication(string path) { if (_gameLoaded) { GtkDialog.CreateInfoDialog("A game has already been loaded", "Please close it first and try again."); } else { PerformanceCheck(); Logger.RestartTime(); InitializeSwitchInstance(); UpdateGraphicsConfig(); SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion(); bool isDirectory = Directory.Exists(path); if (!SetupValidator.CanStartApplication(_contentManager, path, out UserError userError)) { if (SetupValidator.CanFixStartApplication(_contentManager, path, userError, out firmwareVersion)) { if (userError == UserError.NoFirmware) { string message = $"Would you like to install the firmware embedded in this game? (Firmware {firmwareVersion.VersionString})"; ResponseType responseDialog = (ResponseType)GtkDialog.CreateConfirmationDialog("No Firmware Installed", message).Run(); if (responseDialog != ResponseType.Yes) { UserErrorDialog.CreateUserErrorDialog(userError); _emulationContext.Dispose(); return; } } if (!SetupValidator.TryFixStartApplication(_contentManager, path, userError, out _)) { UserErrorDialog.CreateUserErrorDialog(userError); _emulationContext.Dispose(); return; } // Tell the user that we installed a firmware for them. if (userError == UserError.NoFirmware) { firmwareVersion = _contentManager.GetCurrentFirmwareVersion(); RefreshFirmwareLabel(); string message = $"No installed firmware was found but Ryujinx was able to install firmware {firmwareVersion.VersionString} from the provided game.\nThe emulator will now start."; GtkDialog.CreateInfoDialog($"Firmware {firmwareVersion.VersionString} was installed", message); } } else { UserErrorDialog.CreateUserErrorDialog(userError); _emulationContext.Dispose(); return; } } Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {firmwareVersion?.VersionString}"); if (Directory.Exists(path)) { string[] romFsFiles = Directory.GetFiles(path, "*.istorage"); if (romFsFiles.Length == 0) { romFsFiles = Directory.GetFiles(path, "*.romfs"); } if (romFsFiles.Length > 0) { Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS."); _emulationContext.LoadCart(path, romFsFiles[0]); } else { Logger.Info?.Print(LogClass.Application, "Loading as cart WITHOUT RomFS."); _emulationContext.LoadCart(path); } } else if (File.Exists(path)) { switch (System.IO.Path.GetExtension(path).ToLowerInvariant()) { case ".xci": Logger.Info?.Print(LogClass.Application, "Loading as XCI."); _emulationContext.LoadXci(path); break; case ".nca": Logger.Info?.Print(LogClass.Application, "Loading as NCA."); _emulationContext.LoadNca(path); break; case ".nsp": case ".pfs0": Logger.Info?.Print(LogClass.Application, "Loading as NSP."); _emulationContext.LoadNsp(path); break; default: Logger.Info?.Print(LogClass.Application, "Loading as homebrew."); try { _emulationContext.LoadProgram(path); } catch (ArgumentOutOfRangeException) { Logger.Error?.Print(LogClass.Application, "The file which you have specified is unsupported by Ryujinx."); } break; } } else { Logger.Warning?.Print(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file."); _emulationContext.Dispose(); return; } _currentEmulatedGamePath = path; _deviceExitStatus.Reset(); Translator.IsReadyForTranslation.Reset(); #if MACOS_BUILD CreateGameWindow(); #else Thread windowThread = new Thread(() => { CreateGameWindow(); }) { Name = "GUI.WindowThread" }; windowThread.Start(); #endif _gameLoaded = true; _stopEmulation.Sensitive = true; _simulateWakeUpMessage.Sensitive = true; _firmwareInstallFile.Sensitive = false; _firmwareInstallDirectory.Sensitive = false; DiscordIntegrationModule.SwitchToPlayingState(_emulationContext.Application.TitleIdText, _emulationContext.Application.TitleName); _applicationLibrary.LoadAndSaveMetaData(_emulationContext.Application.TitleIdText, appMetadata => { appMetadata.LastPlayed = DateTime.UtcNow.ToString(); }); } }
internal void LoadApplication(string path) { if (_gameLoaded) { GtkDialog.CreateErrorDialog("A game has already been loaded. Please close the emulator and try again"); } else { Logger.RestartTime(); // TODO: Move this somewhere else + reloadable? GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath; 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."); try { _device.LoadProgram(path); } catch (ArgumentOutOfRangeException) { Logger.PrintError(LogClass.Application, "The file which you have specified is unsupported by Ryujinx."); } break; } } else { Logger.PrintWarning(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file."); End(); } #if MACOS_BUILD CreateGameWindow(); #else new Thread(CreateGameWindow).Start(); #endif _gameLoaded = true; _stopEmulation.Sensitive = true; DiscordIntegrationModule.SwitchToPlayingState(_device.System.TitleId, _device.System.TitleName); string metadataFolder = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "games", _device.System.TitleId, "gui"); string metadataFile = System.IO.Path.Combine(metadataFolder, "metadata.json"); IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase }); ApplicationMetadata appMetadata; if (!File.Exists(metadataFile)) { Directory.CreateDirectory(metadataFolder); appMetadata = new ApplicationMetadata { Favorite = false, TimePlayed = 0, LastPlayed = "Never" }; byte[] data = JsonSerializer.Serialize(appMetadata, resolver); File.WriteAllText(metadataFile, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson()); } using (Stream stream = File.OpenRead(metadataFile)) { appMetadata = JsonSerializer.Deserialize <ApplicationMetadata>(stream, resolver); } appMetadata.LastPlayed = DateTime.UtcNow.ToString(); byte[] saveData = JsonSerializer.Serialize(appMetadata, resolver); File.WriteAllText(metadataFile, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson()); } }
internal void LoadApplication(string path) { if (_gameLoaded) { GtkDialog.CreateDialog("Ryujinx", "A game has already been loaded", "Please close it first and try again."); } else { Logger.RestartTime(); HLE.Switch device = InitializeSwitchInstance(); // TODO: Move this somewhere else + reloadable? Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath; 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."); try { device.LoadProgram(path); } catch (ArgumentOutOfRangeException) { Logger.PrintError(LogClass.Application, "The file which you have specified is unsupported by Ryujinx."); } break; } } else { Logger.PrintWarning(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file."); End(device); } _emulationContext = device; _deviceExitStatus.Reset(); #if MACOS_BUILD CreateGameWindow(device); #else var windowThread = new Thread(() => { CreateGameWindow(device); }) { Name = "GUI.WindowThread" }; windowThread.Start(); #endif _gameLoaded = true; _stopEmulation.Sensitive = true; _firmwareInstallFile.Sensitive = false; _firmwareInstallDirectory.Sensitive = false; DiscordIntegrationModule.SwitchToPlayingState(device.System.TitleIdText, device.System.TitleName); ApplicationLibrary.LoadAndSaveMetaData(device.System.TitleIdText, appMetadata => { appMetadata.LastPlayed = DateTime.UtcNow.ToString(); }); } }
internal void LoadApplication(string path) { if (_gameLoaded) { CreateErrorDialog("A game has already been loaded. Please close the emulator and try again"); } else { Logger.RestartTime(); 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."); try { _device.LoadProgram(path); } catch (ArgumentOutOfRangeException) { Logger.PrintError(LogClass.Application, "The file which you have specified is unsupported by Ryujinx."); } break; } } else { Logger.PrintWarning(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file."); End(); } new Thread(new ThreadStart(CreateGameWindow)).Start(); _gameLoaded = true; _stopEmulation.Sensitive = true; if (DiscordIntegrationEnabled) { if (File.ReadAllLines(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RPsupported.dat")).Contains(_device.System.TitleID)) { DiscordPresence.Assets.LargeImageKey = _device.System.TitleID; } string state = _device.System.TitleID; if (state == null) { state = "Ryujinx"; } else { state = state.ToUpper(); } string details = "Idling"; if (_device.System.TitleName != null) { details = $"Playing {_device.System.TitleName}"; } DiscordPresence.Details = details; DiscordPresence.State = state; 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); } try { string savePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "nand", "user", "save", "0000000000000000", _userId, _device.System.TitleID); if (File.Exists(System.IO.Path.Combine(savePath, "TimePlayed.dat")) == false) { Directory.CreateDirectory(savePath); using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "TimePlayed.dat"))) { stream.Write(Encoding.ASCII.GetBytes("0")); } } if (File.Exists(System.IO.Path.Combine(savePath, "LastPlayed.dat")) == false) { Directory.CreateDirectory(savePath); using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "LastPlayed.dat"))) { stream.Write(Encoding.ASCII.GetBytes("Never")); } } using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "LastPlayed.dat"))) { using (StreamWriter writer = new StreamWriter(stream)) { writer.WriteLine(DateTime.UtcNow); } } } catch (ArgumentNullException) { Logger.PrintWarning(LogClass.Application, $"Could not access save path to retrieve time/last played data using: UserID: {_userId}, TitleID: {_device.System.TitleID}"); } } }
internal void LoadApplication(string path) { if (_gameLoaded) { GtkDialog.CreateErrorDialog("A game has already been loaded. Please close the emulator and try again"); } else { Logger.RestartTime(); 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."); try { _device.LoadProgram(path); } catch (ArgumentOutOfRangeException) { Logger.PrintError(LogClass.Application, "The file which you have specified is unsupported by Ryujinx."); } break; } } else { Logger.PrintWarning(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file."); End(); } #if MACOS_BUILD CreateGameWindow(); #else new Thread(CreateGameWindow).Start(); #endif _gameLoaded = true; _stopEmulation.Sensitive = true; if (DiscordIntegrationEnabled) { if (File.ReadAllLines(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RPsupported.dat")).Contains(_device.System.TitleId)) { DiscordPresence.Assets.LargeImageKey = _device.System.TitleId; } string state = _device.System.TitleId; if (state == null) { state = "Ryujinx"; } else { state = state.ToUpper(); } string details = "Idling"; if (_device.System.TitleName != null) { details = $"Playing {_device.System.TitleName}"; } DiscordPresence.Details = details; DiscordPresence.State = state; 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); } string metadataFolder = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "games", _device.System.TitleId, "gui"); string metadataFile = System.IO.Path.Combine(metadataFolder, "metadata.json"); IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase }); ApplicationMetadata appMetadata; if (!File.Exists(metadataFile)) { Directory.CreateDirectory(metadataFolder); appMetadata = new ApplicationMetadata { Favorite = false, TimePlayed = 0, LastPlayed = "Never" }; byte[] data = JsonSerializer.Serialize(appMetadata, resolver); File.WriteAllText(metadataFile, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson()); } using (Stream stream = File.OpenRead(metadataFile)) { appMetadata = JsonSerializer.Deserialize <ApplicationMetadata>(stream, resolver); } appMetadata.LastPlayed = DateTime.UtcNow.ToString(); byte[] saveData = JsonSerializer.Serialize(appMetadata, resolver); File.WriteAllText(metadataFile, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson()); } }
internal void LoadApplication(string path) { if (_gameLoaded) { GtkDialog.CreateInfoDialog("Ryujinx", "A game has already been loaded", "Please close it first and try again."); } else { if (ConfigurationState.Instance.Logger.EnableDebug.Value) { MessageDialog debugWarningDialog = new MessageDialog(this, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null) { Title = "Ryujinx - Warning", Text = "You have debug logging enabled, which is designed to be used by developers only.", SecondaryText = "For optimal performance, it's recommended to disable debug logging. Would you like to disable debug logging now?" }; if (debugWarningDialog.Run() == (int)ResponseType.Yes) { ConfigurationState.Instance.Logger.EnableDebug.Value = false; SaveConfig(); } debugWarningDialog.Dispose(); } if (!string.IsNullOrWhiteSpace(ConfigurationState.Instance.Graphics.ShadersDumpPath.Value)) { MessageDialog shadersDumpWarningDialog = new MessageDialog(this, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null) { Title = "Ryujinx - Warning", Text = "You have shader dumping enabled, which is designed to be used by developers only.", SecondaryText = "For optimal performance, it's recommended to disable shader dumping. Would you like to disable shader dumping now?" }; if (shadersDumpWarningDialog.Run() == (int)ResponseType.Yes) { ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = ""; SaveConfig(); } shadersDumpWarningDialog.Dispose(); } Logger.RestartTime(); HLE.Switch device = InitializeSwitchInstance(); UpdateGraphicsConfig(); Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {_contentManager.GetCurrentFirmwareVersion()?.VersionString}"); if (Directory.Exists(path)) { string[] romFsFiles = Directory.GetFiles(path, "*.istorage"); if (romFsFiles.Length == 0) { romFsFiles = Directory.GetFiles(path, "*.romfs"); } if (romFsFiles.Length > 0) { Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS."); device.LoadCart(path, romFsFiles[0]); } else { Logger.Info?.Print(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.Info?.Print(LogClass.Application, "Loading as XCI."); device.LoadXci(path); break; case ".nca": Logger.Info?.Print(LogClass.Application, "Loading as NCA."); device.LoadNca(path); break; case ".nsp": case ".pfs0": Logger.Info?.Print(LogClass.Application, "Loading as NSP."); device.LoadNsp(path); break; default: Logger.Info?.Print(LogClass.Application, "Loading as homebrew."); try { device.LoadProgram(path); } catch (ArgumentOutOfRangeException) { Logger.Error?.Print(LogClass.Application, "The file which you have specified is unsupported by Ryujinx."); } break; } } else { Logger.Warning?.Print(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file."); device.Dispose(); return; } _emulationContext = device; _deviceExitStatus.Reset(); #if MACOS_BUILD CreateGameWindow(device); #else Thread windowThread = new Thread(() => { CreateGameWindow(device); }) { Name = "GUI.WindowThread" }; windowThread.Start(); #endif _gameLoaded = true; _stopEmulation.Sensitive = true; _firmwareInstallFile.Sensitive = false; _firmwareInstallDirectory.Sensitive = false; DiscordIntegrationModule.SwitchToPlayingState(device.Application.TitleIdText, device.Application.TitleName); ApplicationLibrary.LoadAndSaveMetaData(device.Application.TitleIdText, appMetadata => { appMetadata.LastPlayed = DateTime.UtcNow.ToString(); }); } }