// todo: Implement NcaReader and other Nca classes public Result Create(out ReferenceCountedDisposable <IStorage> storage, out NcaFsHeader fsHeader, Nca nca, int fsIndex, bool isCodeFs) { UnsafeHelpers.SkipParamInit(out storage, out fsHeader); Result rc = OpenStorage(out IStorage storageTemp, nca, fsIndex); if (rc.IsFailure()) { return(rc); } if (isCodeFs) { using (var codeFs = new PartitionFileSystemCore <StandardEntry>()) { rc = codeFs.Initialize(storageTemp); if (rc.IsFailure()) { return(rc); } rc = VerifyAcidSignature(codeFs, nca); if (rc.IsFailure()) { return(rc); } } } storage = new ReferenceCountedDisposable <IStorage>(storageTemp); fsHeader = nca.GetFsHeader(fsIndex); return(Result.Success); }
public ExtractPartition(List <SwitchFsNca> selected) : base(selected) { InitializeComponent(); Indexed = new Dictionary <NcaFormatType, List <Tuple <SwitchFsNca, int> > >(); foreach (SwitchFsNca nca in selected) { if (nca.Nca.Header.ContentType != ContentType.Meta) { for (int i = 0; i < 4; i++) { if (!nca.Nca.Header.IsSectionEnabled(i)) { continue; } NcaFsHeader section = nca.Nca.Header.GetFsHeader(i); if (!Indexed.ContainsKey(section.FormatType)) { Indexed[section.FormatType] = new List <Tuple <SwitchFsNca, int> >(); } Indexed[section.FormatType].Add(new Tuple <SwitchFsNca, int>(nca, i)); } } } if (Indexed.ContainsKey(NcaFormatType.Romfs)) { ComboBox.Items.Add(MountType.Romfs); } if (Indexed.ContainsKey(NcaFormatType.Pfs0)) { ComboBox.Items.Add(MountType.Exefs); } }
public TitleMountDialog(Dictionary <NcaFormatType, List <Tuple <SwitchFsNca, int> > > indexed, SwitchFsNca mainNca) { InitializeComponent(); Indexed = indexed; MainNca = mainNca; bool hasPatch = false; foreach (Tuple <SwitchFsNca, int> t in Indexed.Values.SelectMany(i => i)) { NcaFsHeader section = t.Item1.Nca.Header.GetFsHeader(t.Item2); if (section.IsPatchSection()) { hasPatch = true; break; } } if (Indexed.ContainsKey(NcaFormatType.Romfs) || hasPatch) { ComboBox.Items.Add(MountType.Romfs); } if (Indexed.ContainsKey(NcaFormatType.Pfs0)) { ComboBox.Items.Add(MountType.Exefs); } }
// todo: Implement NcaReader and other Nca classes public Result Create(out IStorage storage, out NcaFsHeader fsHeader, Nca nca, int fsIndex, bool isCodeFs) { storage = default; fsHeader = default; Result rc = OpenStorage(out IStorage storageTemp, nca, fsIndex); if (rc.IsFailure()) { return(rc); } if (isCodeFs) { using (var codeFs = new PartitionFileSystemCore <StandardEntry>()) { rc = codeFs.Initialize(storageTemp); if (rc.IsFailure()) { return(rc); } rc = VerifyAcidSignature(codeFs, nca); if (rc.IsFailure()) { return(rc); } } } storage = storageTemp; fsHeader = nca.GetFsHeader(fsIndex); return(Result.Success); }
private void MountClicked(object sender, RoutedEventArgs e) { if (ComboBox.SelectedItem == null) { return; } MountType mountType = (MountType)ComboBox.SelectedItem; NcaFormatType sectionType = NcaFormatType.Romfs; switch (mountType) { case MountType.Exefs: sectionType = NcaFormatType.Pfs0; break; case MountType.Romfs: sectionType = NcaFormatType.Romfs; break; } List <IFileSystem> filesystems = new List <IFileSystem>(); IEnumerable <Tuple <SwitchFsNca, int> > list = Indexed[sectionType]; TaskManagerPage.Current.Queue.Submit(new RunTask("Opening filesystems to mount...", new Task(() => { foreach (Tuple <SwitchFsNca, int> t in list) { SwitchFsNca nca = t.Item1; NcaFsHeader section = t.Item1.Nca.Header.GetFsHeader(t.Item2); int index = t.Item2; /*IStorage inStorage = nca.OpenStorage(index, IntegrityCheckLevel.ErrorOnInvalid); * IFile outFile = new LocalFile("./tmp.bin", OpenMode.Write | OpenMode.AllowAppend); * IStorage outStorage = outFile.AsStorage(); * inStorage.GetSize(out long size); * long buffLen = 0x10000; * for (int i = 0; i < (int)Math.Min(Math.Ceiling((double)size / buffLen), 5); i++) * { * long off = i * buffLen; * long left = size - off; * long toRead = Math.Min(buffLen, left); * * byte[] buff = new byte[toRead]; * * inStorage.Read(off, buff); * outStorage.Write(off, buff); * } * //inStorage.Dispose(); * outFile.Dispose();*/ filesystems.Add(nca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid)); } filesystems.Reverse(); LayeredFileSystem fs = new LayeredFileSystem(filesystems); string typeString = sectionType.ToString(); MountService.Mount(new MountableFileSystem(fs, $"Mounted {mountType.ToString().ToLower()}", typeString, OpenMode.Read)); }))); }
private void MountClicked(object sender, RoutedEventArgs e) { List <Title> selected = new List <Title>(); foreach (TitleElement info in ListView.Items) { if (info.Selected) { selected.Add(info.Title); } } List <Title> orderedTitles = Element.OrderTitlesByBest(); Title baseTitle = orderedTitles.FirstOrDefault(t => t.Metadata.Type == TitleType.Application); if (baseTitle == null && orderedTitles.Count == 1) { baseTitle = orderedTitles.First(); } if (!IsMountable(baseTitle, selected)) { MessageBox.Show("The base game isn't available, so the patch cannot be mounted."); return; } Dictionary <NcaFormatType, List <Tuple <SwitchFsNca, int> > > indexed = new Dictionary <NcaFormatType, List <Tuple <SwitchFsNca, int> > >(); foreach (Title title in selected) { SwitchFsNca nca = title.MainNca; if (nca.Nca.Header.ContentType != ContentType.Meta) { for (int i = 0; i < 4; i++) { if (!nca.Nca.Header.IsSectionEnabled(i)) { continue; } NcaFsHeader section = nca.Nca.Header.GetFsHeader(i); if (!indexed.ContainsKey(section.FormatType)) { indexed[section.FormatType] = new List <Tuple <SwitchFsNca, int> >(); } indexed[section.FormatType].Add(new Tuple <SwitchFsNca, int>(nca, i)); } } } Window window = new TitleMountDialog(indexed, baseTitle.MainNca) { Owner = Window.GetWindow(this) }; window.ShowDialog(); }
private void ExtractClicked(object sender, RoutedEventArgs e) { MountType mountType = (MountType)ComboBox.SelectedItem; NcaFormatType sectionType = NcaFormatType.Romfs; switch (mountType) { case MountType.Exefs: sectionType = NcaFormatType.Pfs0; break; case MountType.Romfs: sectionType = NcaFormatType.Romfs; break; } IEnumerable <Tuple <SwitchFsNca, int> > list = Indexed[sectionType]; string path = Path.Text; TaskManagerPage.Current.Queue.Submit(new RunTask("Opening filesystems to extract...", new Task(() => { List <IFileSystem> filesystems = new List <IFileSystem>(); foreach (Tuple <SwitchFsNca, int> t in list) { SwitchFsNca nca = t.Item1; NcaFsHeader section = t.Item1.Nca.Header.GetFsHeader(t.Item2); int index = t.Item2; filesystems.Add(nca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid)); } filesystems.Reverse(); LayeredFileSystem lfs = new LayeredFileSystem(filesystems); ExtractFileSystemTask task = new ExtractFileSystemTask($"Extracting {sectionType}...", lfs, path); Dispatcher.InvokeAsync(() => { ProgressView view = new ProgressView(new List <ProgressTask>() { task }); NavigationWindow window = new NavigationWindow { ShowsNavigationUI = false // get rid of the t r a s h }; window.Navigate(view); TaskManagerPage.Current.Queue.Submit(task); window.Owner = Window.GetWindow(this); window.ShowDialog(); }); }))); }
public static NcaFsHeader GetFsHeader(this NcaHeader obj, NcaFormatType type) { for (int i = 0; i < 4; i++) { NcaFsHeader header = obj.GetFsHeader(i); if (header.FormatType == type) { return(header); } } throw new InvalidOperationException($"NCA is missing section type {type}"); }
void PrintSha256Hash(NcaFsHeader sect, int index) { NcaFsIntegrityInfoSha256 hashInfo = sect.GetIntegrityInfoSha256(); PrintItem(sb, colLen, $" Master Hash{nca.ValidateSectionMasterHash(index).GetValidityString()}:", hashInfo.MasterHash.ToArray()); sb.AppendLine(" Hash Table:"); PrintItem(sb, colLen, " Offset:", $"0x{hashInfo.GetLevelOffset(0):x12}"); PrintItem(sb, colLen, " Size:", $"0x{hashInfo.GetLevelSize(0):x12}"); PrintItem(sb, colLen, " Block Size:", $"0x{hashInfo.BlockSize:x}"); PrintItem(sb, colLen, " PFS0 Offset:", $"0x{hashInfo.GetLevelOffset(1):x12}"); PrintItem(sb, colLen, " PFS0 Size:", $"0x{hashInfo.GetLevelSize(1):x12}"); }
static string GetPartitionType(NcaFsHeader fsHeader, bool isExefs, bool isNca0) { if (isExefs) { return("ExeFS"); } if (isNca0 && fsHeader.FormatType == NcaFormatType.Romfs) { return("NCA0 RomFS"); } return(fsHeader.FormatType.Print() + (fsHeader.IsPatchSection() ? " patch" : "")); }
public static void MatchupBaseNca(this IEnumerable <SwitchFsNca> ncas) { PseudoFileSystem ps = ncas.MakeFs(); SwitchFs fs = SwitchFs.OpenNcaDirectory(HACGUIKeyset.Keyset, ps); foreach (KeyValuePair <ulong, LibHac.Application> kv in fs.Applications) { ulong tid = kv.Key; LibHac.Application app = kv.Value; if (app.Patch != null && app.Main != null) { foreach (SwitchFsNca nca in app.Patch.Ncas) { ContentType type = nca.Nca.Header.ContentType; SwitchFsNca baseNca = app.Main.Ncas.Where(n => n.Nca.Header.ContentType == type).FirstOrDefault(); if (baseNca != null) { bool hasPatch = false; for (int i = 0; i < 4; i++) { Nca n = nca.Nca; if (n.CanOpenSection(i)) { NcaFsHeader section = n.Header.GetFsHeader(i); if (section.IsPatchSection()) { hasPatch = true; break; } } } if (hasPatch) { ncas.Where(n => n.Filename == nca.Filename.Replace("/", "")).First().BaseNca = baseNca.Nca; // set original NCA, not new parsed one } } } } } }
private void MountClicked(object sender, RoutedEventArgs e) { List <SwitchFsNca> selected = new List <SwitchFsNca>(); foreach (NcaElement info in ListView.Items) { if (info.Selected) { selected.Add(info.Nca); } } Dictionary <NcaFormatType, List <Tuple <SwitchFsNca, int> > > indexed = new Dictionary <NcaFormatType, List <Tuple <SwitchFsNca, int> > >(); foreach (SwitchFsNca nca in selected) { for (int i = 0; i < 4; i++) { if (!nca.Nca.Header.IsSectionEnabled(i)) { continue; } NcaFsHeader section = nca.Nca.Header.GetFsHeader(i); if (!indexed.ContainsKey(section.FormatType)) { indexed[section.FormatType] = new List <Tuple <SwitchFsNca, int> >(); } indexed[section.FormatType].Add(new Tuple <SwitchFsNca, int>(nca, i)); } } Window window = new TitleMountDialog(indexed) { Owner = Window.GetWindow(this) }; window.ShowDialog(); }
private void MountClicked(object sender, RoutedEventArgs e) { MountType mountType = (MountType)ComboBox.SelectedItem; NcaFormatType sectionType = NcaFormatType.Romfs; switch (mountType) { case MountType.Exefs: sectionType = NcaFormatType.Pfs0; break; case MountType.Romfs: sectionType = NcaFormatType.Romfs; break; } List <IFileSystem> filesystems = new List <IFileSystem>(); IEnumerable <Tuple <SwitchFsNca, int> > list = Indexed[sectionType]; TaskManagerPage.Current.Queue.Submit(new RunTask("Opening filesystems to mount...", new Task(() => { foreach (Tuple <SwitchFsNca, int> t in list) { SwitchFsNca nca = t.Item1; NcaFsHeader section = t.Item1.Nca.Header.GetFsHeader(t.Item2); int index = t.Item2; if (section.IsPatchSection()) { MainNca.BaseNca = nca.Nca; } filesystems.Add(nca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid)); } filesystems.Reverse(); LayeredFileSystem fs = new LayeredFileSystem(filesystems); string typeString = sectionType.ToString(); MountService.Mount(new MountableFileSystem(fs, $"Mounted {mountType.ToString().ToLower()}", typeString, OpenMode.Read)); }))); }
public Result CreateWithPatch(out IStorage storage, out NcaFsHeader fsHeader, Nca baseNca, Nca patchNca, int fsIndex, bool isCodeFs) { throw new NotImplementedException(); }
public Result CreateWithPatch(out ReferenceCountedDisposable <IStorage> storage, out NcaFsHeader fsHeader, Nca baseNca, Nca patchNca, int fsIndex, bool isCodeFs) { throw new NotImplementedException(); }
private static string Print(this NcaHolder ncaHolder) { Nca nca = ncaHolder.Nca; int masterKey = Keyset.GetMasterKeyRevisionFromKeyGeneration(nca.Header.KeyGeneration); int colLen = 36; var sb = new StringBuilder(); sb.AppendLine(); sb.AppendLine("NCA:"); PrintItem(sb, colLen, "Magic:", MagicToString(nca.Header.Magic)); PrintItem(sb, colLen, $"Fixed-Key Signature{nca.VerifyHeaderSignature().GetValidityString()}:", nca.Header.Signature1.ToArray()); PrintItem(sb, colLen, $"NPDM Signature{nca.VerifySignature2().GetValidityString()}:", nca.Header.Signature2.ToArray()); PrintItem(sb, colLen, "Content Size:", $"0x{nca.Header.NcaSize:x12}"); PrintItem(sb, colLen, "TitleID:", $"{nca.Header.TitleId:X16}"); if (nca.CanOpenSection(NcaSectionType.Code)) { IFileSystem fs = nca.OpenFileSystem(NcaSectionType.Code, IntegrityCheckLevel.None); Result r = fs.OpenFile(out IFile file, "/main.npdm".ToU8String(), OpenMode.Read); if (r.IsSuccess()) { var npdm = new NpdmBinary(file.AsStream(), null); PrintItem(sb, colLen, "Title Name:", npdm.TitleName); } } PrintItem(sb, colLen, "SDK Version:", nca.Header.SdkVersion); PrintItem(sb, colLen, "Distribution type:", nca.Header.DistributionType); PrintItem(sb, colLen, "Content Type:", nca.Header.ContentType); PrintItem(sb, colLen, "Master Key Revision:", $"{masterKey} ({Utilities.GetKeyRevisionSummary(masterKey)})"); PrintItem(sb, colLen, "Encryption Type:", $"{(nca.Header.HasRightsId ? "Titlekey crypto" : "Standard crypto")}"); if (nca.Header.HasRightsId) { PrintItem(sb, colLen, "Rights ID:", nca.Header.RightsId.ToArray()); } else { PrintItem(sb, colLen, "Key Area Encryption Key:", nca.Header.KeyAreaKeyIndex); sb.AppendLine("Key Area (Encrypted):"); for (int i = 0; i < 4; i++) { PrintItem(sb, colLen, $" Key {i} (Encrypted):", nca.Header.GetEncryptedKey(i).ToArray()); } sb.AppendLine("Key Area (Decrypted):"); for (int i = 0; i < 4; i++) { PrintItem(sb, colLen, $" Key {i} (Decrypted):", nca.GetDecryptedKey(i)); } } PrintSections(); return(sb.ToString()); void PrintSections() { sb.AppendLine("Sections:"); for (int i = 0; i < 4; i++) { if (!nca.Header.IsSectionEnabled(i)) { continue; } NcaFsHeader sectHeader = nca.Header.GetFsHeader(i); bool isExefs = nca.Header.ContentType == NcaContentType.Program && i == 0; sb.AppendLine($" Section {i}:"); PrintItem(sb, colLen, " Offset:", $"0x{nca.Header.GetSectionStartOffset(i):x12}"); PrintItem(sb, colLen, " Size:", $"0x{nca.Header.GetSectionSize(i):x12}"); PrintItem(sb, colLen, " Partition Type:", (isExefs ? "ExeFS" : sectHeader.FormatType.ToString()) + (sectHeader.IsPatchSection() ? " patch" : "")); PrintItem(sb, colLen, " Section CTR:", $"{sectHeader.Counter:x16}"); PrintItem(sb, colLen, " Section Validity:", $"{ncaHolder.Validities[i]}"); switch (sectHeader.HashType) { case NcaHashType.Sha256: PrintSha256Hash(sectHeader, i); break; case NcaHashType.Ivfc: Validity masterHashValidity = nca.ValidateSectionMasterHash(i); PrintIvfcHashNew(sb, colLen, 8, sectHeader.GetIntegrityInfoIvfc(), IntegrityStorageType.RomFs, masterHashValidity); break; default: sb.AppendLine(" Unknown/invalid superblock!"); break; } } } void PrintSha256Hash(NcaFsHeader sect, int index) { NcaFsIntegrityInfoSha256 hashInfo = sect.GetIntegrityInfoSha256(); PrintItem(sb, colLen, $" Master Hash{nca.ValidateSectionMasterHash(index).GetValidityString()}:", hashInfo.MasterHash.ToArray()); sb.AppendLine($" Hash Table:"); PrintItem(sb, colLen, " Offset:", $"0x{hashInfo.GetLevelOffset(0):x12}"); PrintItem(sb, colLen, " Size:", $"0x{hashInfo.GetLevelSize(0):x12}"); PrintItem(sb, colLen, " Block Size:", $"0x{hashInfo.BlockSize:x}"); PrintItem(sb, colLen, " PFS0 Offset:", $"0x{hashInfo.GetLevelOffset(1):x12}"); PrintItem(sb, colLen, " PFS0 Size:", $"0x{hashInfo.GetLevelSize(1):x12}"); } }
public SectionItem(int sectionIndex, NcaFsHeader ncaFsHeader, NcaItem parentItem) { FsHeader = ncaFsHeader; SectionIndex = sectionIndex; ParentItem = parentItem ?? throw new ArgumentNullException(nameof(parentItem)); }