private static bool IsUpdateApplied(string titleId, out string version) { string jsonPath = Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "updates.json"); if (File.Exists(jsonPath)) { string updatePath = JsonHelper.DeserializeFromFile <TitleUpdateMetadata>(jsonPath).Selected; if (!File.Exists(updatePath)) { version = ""; return(false); } using (FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read)) { PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage()); _virtualFileSystem.ImportTickets(nsp); foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca")) { nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); try { Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage()); if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != titleId)
private TitleUpdateWindow(Builder builder, string titleId, string titleName, VirtualFileSystem virtualFileSystem) : base(builder.GetObject("_titleUpdateWindow").Handle) { builder.Autoconnect(this); _titleId = titleId; _virtualFileSystem = virtualFileSystem; _updateJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "updates.json"); _radioButtonToPathDictionary = new Dictionary <RadioButton, string>(); try { _titleUpdateWindowData = JsonHelper.DeserializeFromFile <TitleUpdateMetadata>(_updateJsonPath); } catch { _titleUpdateWindowData = new TitleUpdateMetadata { Selected = "", Paths = new List <string>() }; } _baseTitleInfoLabel.Text = $"Updates Available for {titleName} [{titleId.ToUpper()}]"; _noUpdateRadioButton.Active = true; foreach (string path in _titleUpdateWindowData.Paths) { AddUpdate(path, false); } foreach ((RadioButton update, var _) in _radioButtonToPathDictionary.Where(keyValuePair => keyValuePair.Value == _titleUpdateWindowData.Selected)) { update.Active = true; } }
private TitleUpdateWindow(Builder builder, MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetObject("_titleUpdateWindow").Handle) { _parent = parent; builder.Autoconnect(this); _titleId = titleId; _virtualFileSystem = virtualFileSystem; _updateJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "updates.json"); _radioButtonToPathDictionary = new Dictionary <RadioButton, string>(); try { _titleUpdateWindowData = JsonHelper.DeserializeFromFile <TitleUpdateMetadata>(_updateJsonPath); } catch { _titleUpdateWindowData = new TitleUpdateMetadata { Selected = "", Paths = new List <string>() }; } _baseTitleInfoLabel.Text = $"Updates Available for {titleName} [{titleId.ToUpper()}]"; int invalidUpdateCount = 0; foreach (string path in _titleUpdateWindowData.Paths) { if (!File.Exists(path)) { invalidUpdateCount++; continue; } AddUpdate(path); } if (invalidUpdateCount > 0) { Logger.Error?.PrintMsg(LogClass.Application, "Updates have been moved or deleted; skipping " + invalidUpdateCount + " updates"); GtkDialog.CreateErrorDialog(invalidUpdateCount + " updates have been moved or deleted; please re-add your updates."); } if (_titleUpdateWindowData.Selected == "") { _noUpdateRadioButton.Active = true; } else { foreach ((RadioButton update, var _) in _radioButtonToPathDictionary.Where(keyValuePair => keyValuePair.Value == _titleUpdateWindowData.Selected)) { update.Active = true; } } }
internal static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action <ApplicationMetadata> modifyFunction = null) { string metadataFolder = Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "gui"); string metadataFile = Path.Combine(metadataFolder, "metadata.json"); ApplicationMetadata appMetadata; if (!File.Exists(metadataFile)) { Directory.CreateDirectory(metadataFolder); appMetadata = new ApplicationMetadata { Favorite = false, TimePlayed = 0, LastPlayed = "Never" }; using (FileStream stream = File.Create(metadataFile, 4096, FileOptions.WriteThrough)) { JsonHelper.Serialize(stream, appMetadata, true); } } try { appMetadata = JsonHelper.DeserializeFromFile <ApplicationMetadata>(metadataFile); } catch (JsonException) { Logger.PrintWarning(LogClass.Application, $"Failed to parse metadata json for {titleId}. Loading defaults."); appMetadata = new ApplicationMetadata { Favorite = false, TimePlayed = 0, LastPlayed = "Never" }; } if (modifyFunction != null) { modifyFunction(appMetadata); using (FileStream stream = File.Create(metadataFile, 4096, FileOptions.WriteThrough)) { JsonHelper.Serialize(stream, appMetadata, true); } } return(appMetadata); }
internal ApplicationMetadata LoadAndSaveMetaData(string titleId, Action <ApplicationMetadata> modifyFunction = null) { string metadataFolder = Path.Combine(AppDataManager.GamesDirPath, titleId, "gui"); string metadataFile = Path.Combine(metadataFolder, "metadata.json"); ApplicationMetadata appMetadata; if (!File.Exists(metadataFile)) { Directory.CreateDirectory(metadataFolder); appMetadata = new ApplicationMetadata(); using (FileStream stream = File.Create(metadataFile, 4096, FileOptions.WriteThrough)) { JsonHelper.Serialize(stream, appMetadata, true); } } try { appMetadata = JsonHelper.DeserializeFromFile <ApplicationMetadata>(metadataFile); } catch (JsonException) { Logger.Warning?.Print(LogClass.Application, $"Failed to parse metadata json for {titleId}. Loading defaults."); appMetadata = new ApplicationMetadata(); } if (modifyFunction != null) { modifyFunction(appMetadata); using (FileStream stream = File.Create(metadataFile, 4096, FileOptions.WriteThrough)) { JsonHelper.Serialize(stream, appMetadata, true); } } return(appMetadata); }
public void LoadNca(Nca mainNca, Nca patchNca, Nca controlNca) { if (mainNca.Header.ContentType != NcaContentType.Program) { Logger.PrintError(LogClass.Loader, "Selected NCA is not a \"Program\" NCA"); return; } IStorage dataStorage = null; IFileSystem codeFs = null; string titleUpdateMetadataPath = System.IO.Path.Combine(Device.FileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "updates.json"); if (File.Exists(titleUpdateMetadataPath)) { string updatePath = JsonHelper.DeserializeFromFile <TitleUpdateMetadata>(titleUpdateMetadataPath).Selected; if (File.Exists(updatePath)) { FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read); PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage()); foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik")) { Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read); if (result.IsSuccess()) { Ticket ticket = new Ticket(ticketFile.AsStream()); KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(KeySet))); } } foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca")) { nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); Nca nca = new Nca(KeySet, ncaFile.AsStorage()); if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != mainNca.Header.TitleId.ToString("x16"))
private TitleUpdateWindow(Builder builder, string titleId, string titleName, VirtualFileSystem virtualFileSystem) : base(builder.GetObject("_titleUpdateWindow").Handle) { builder.Autoconnect(this); _titleId = titleId; _virtualFileSystem = virtualFileSystem; try { string path = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", _titleId, "updates.json"); _titleUpdateWindowData = JsonHelper.DeserializeFromFile <TitleUpdateMetadata>(path); } catch { _titleUpdateWindowData = new TitleUpdateMetadata { Selected = "", Paths = new List <string>() }; } _baseTitleInfoLabel.Text = $"Updates Available for {titleName} [{titleId}]"; foreach (string path in _titleUpdateWindowData.Paths) { AddUpdate(path, false); } _noUpdateRadioButton.Active = true; foreach (KeyValuePair <RadioButton, string> keyValuePair in _radioButtonToPathDictionary) { if (keyValuePair.Value == _titleUpdateWindowData.Selected) { keyValuePair.Key.Active = true; } } }
private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetObject("_dlcWindow").Handle) { builder.Autoconnect(this); _titleId = titleId; _virtualFileSystem = virtualFileSystem; _dlcJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "dlc.json"); _baseTitleInfoLabel.Text = $"DLC Available for {titleName} [{titleId.ToUpper()}]"; try { _dlcContainerList = JsonHelper.DeserializeFromFile <List <DlcContainer> >(_dlcJsonPath); } catch { _dlcContainerList = new List <DlcContainer>(); } _dlcTreeView.Model = new TreeStore(typeof(bool), typeof(string), typeof(string)); CellRendererToggle enableToggle = new CellRendererToggle(); enableToggle.Toggled += (sender, args) => { _dlcTreeView.Model.GetIter(out TreeIter treeIter, new TreePath(args.Path)); bool newValue = !(bool)_dlcTreeView.Model.GetValue(treeIter, 0); _dlcTreeView.Model.SetValue(treeIter, 0, newValue); if (_dlcTreeView.Model.IterChildren(out TreeIter childIter, treeIter)) { do { _dlcTreeView.Model.SetValue(childIter, 0, newValue); }while (_dlcTreeView.Model.IterNext(ref childIter)); } }; _dlcTreeView.AppendColumn("Enabled", enableToggle, "active", 0); _dlcTreeView.AppendColumn("TitleId", new CellRendererText(), "text", 1); _dlcTreeView.AppendColumn("Path", new CellRendererText(), "text", 2); foreach (DlcContainer dlcContainer in _dlcContainerList) { TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(false, "", dlcContainer.Path); using FileStream containerFile = File.OpenRead(dlcContainer.Path); PartitionFileSystem pfs = new PartitionFileSystem(containerFile.AsStorage()); _virtualFileSystem.ImportTickets(pfs); foreach (DlcNca dlcNca in dlcContainer.DlcNcaList) { pfs.OpenFile(out IFile ncaFile, dlcNca.Path.ToU8Span(), OpenMode.Read).ThrowIfFailure(); Nca nca = TryCreateNca(ncaFile.AsStorage(), dlcContainer.Path); if (nca != null) { ((TreeStore)_dlcTreeView.Model).AppendValues(parentIter, dlcNca.Enabled, nca.Header.TitleId.ToString("X16"), dlcNca.Path); } } } }
private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetObject("_dlcWindow").Handle) { builder.Autoconnect(this); _titleId = titleId; _virtualFileSystem = virtualFileSystem; _dlcJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "dlc.json"); _baseTitleInfoLabel.Text = $"DLC Available for {titleName} [{titleId.ToUpper()}]"; try { _dlcContainerList = JsonHelper.DeserializeFromFile <List <DlcContainer> >(_dlcJsonPath); } catch { _dlcContainerList = new List <DlcContainer>(); } _dlcTreeView.Model = new TreeStore(typeof(bool), typeof(string), typeof(string)); CellRendererToggle enableToggle = new CellRendererToggle(); enableToggle.Toggled += (sender, args) => { _dlcTreeView.Model.GetIter(out TreeIter treeIter, new TreePath(args.Path)); bool newValue = !(bool)_dlcTreeView.Model.GetValue(treeIter, 0); _dlcTreeView.Model.SetValue(treeIter, 0, newValue); if (_dlcTreeView.Model.IterChildren(out TreeIter childIter, treeIter)) { do { _dlcTreeView.Model.SetValue(childIter, 0, newValue); }while (_dlcTreeView.Model.IterNext(ref childIter)); } }; _dlcTreeView.AppendColumn("Enabled", enableToggle, "active", 0); _dlcTreeView.AppendColumn("TitleId", new CellRendererText(), "text", 1); _dlcTreeView.AppendColumn("Path", new CellRendererText(), "text", 2); foreach (DlcContainer dlcContainer in _dlcContainerList) { if (File.Exists(dlcContainer.Path)) { // The parent tree item has its own "enabled" check box, but it's the actual // nca entries that store the enabled / disabled state. A bit of a UI inconsistency. // Maybe a tri-state check box would be better, but for now we check the parent // "enabled" box if all child NCAs are enabled. Usually fine since each nsp has only one nca. bool areAllContentPacksEnabled = dlcContainer.DlcNcaList.TrueForAll((nca) => nca.Enabled); TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(areAllContentPacksEnabled, "", dlcContainer.Path); using FileStream containerFile = File.OpenRead(dlcContainer.Path); PartitionFileSystem pfs = new PartitionFileSystem(containerFile.AsStorage()); _virtualFileSystem.ImportTickets(pfs); foreach (DlcNca dlcNca in dlcContainer.DlcNcaList) { using var ncaFile = new UniqueRef <IFile>(); pfs.OpenFile(ref ncaFile.Ref(), dlcNca.Path.ToU8Span(), OpenMode.Read).ThrowIfFailure(); Nca nca = TryCreateNca(ncaFile.Get.AsStorage(), dlcContainer.Path); if (nca != null) { ((TreeStore)_dlcTreeView.Model).AppendValues(parentIter, dlcNca.Enabled, nca.Header.TitleId.ToString("X16"), dlcNca.Path); } } } else { // DLC file moved or renamed. Allow the user to remove it without crashing the whole dialog. TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(false, "", $"(MISSING) {dlcContainer.Path}"); } } }