public static void Process(Context ctx, IStorage romfsStorage) { var romfs = new RomFsFileSystem(romfsStorage); if (ctx.Options.ListRomFs) { foreach (DirectoryEntry entry in romfs.EnumerateEntries()) { ctx.Logger.LogMessage(entry.FullPath); } } if (ctx.Options.RomfsOut != null) { using (var outFile = new FileStream(ctx.Options.RomfsOut, FileMode.Create, FileAccess.ReadWrite)) { romfsStorage.CopyToStream(outFile, romfsStorage.GetSize(), ctx.Logger); } } if (ctx.Options.RomfsOutDir != null) { romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger); } }
public static void Process(Context ctx) { SwitchFs switchFs; var baseFs = new LocalFileSystem(ctx.Options.InFile); if (Directory.Exists(Path.Combine(ctx.Options.InFile, "Nintendo", "Contents", "registered"))) { ctx.Logger.LogMessage("Treating path as SD card storage"); switchFs = SwitchFs.OpenSdCard(ctx.Keyset, baseFs); } else if (Directory.Exists(Path.Combine(ctx.Options.InFile, "Contents", "registered"))) { ctx.Logger.LogMessage("Treating path as NAND storage"); switchFs = SwitchFs.OpenNandPartition(ctx.Keyset, baseFs); } else { ctx.Logger.LogMessage("Treating path as a directory of loose NCAs"); switchFs = SwitchFs.OpenNcaDirectory(ctx.Keyset, baseFs); } if (ctx.Options.ListNcas) { ctx.Logger.LogMessage(ListNcas(switchFs)); } if (ctx.Options.ListTitles) { ctx.Logger.LogMessage(ListTitles(switchFs)); } if (ctx.Options.ListApps) { ctx.Logger.LogMessage(ListApplications(switchFs)); } if (ctx.Options.ExefsOutDir != null || ctx.Options.ExefsOut != null) { ulong id = ctx.Options.TitleId; if (id == 0) { ctx.Logger.LogMessage("Title ID must be specified to dump ExeFS"); return; } if (!switchFs.Titles.TryGetValue(id, out Title title)) { ctx.Logger.LogMessage($"Could not find title {id:X16}"); return; } if (title.MainNca == null) { ctx.Logger.LogMessage($"Could not find main data for title {id:X16}"); return; } NcaSection section = title.MainNca.Sections[(int)ProgramPartitionType.Code]; if (section == null) { ctx.Logger.LogMessage($"Main NCA for title {id:X16} has no ExeFS section"); return; } if (ctx.Options.ExefsOutDir != null) { title.MainNca.ExtractSection(section.SectionNum, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger); } if (ctx.Options.ExefsOut != null) { title.MainNca.ExportSection(section.SectionNum, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger); } } if (ctx.Options.RomfsOutDir != null || ctx.Options.RomfsOut != null) { ulong id = ctx.Options.TitleId; if (id == 0) { ctx.Logger.LogMessage("Title ID must be specified to dump RomFS"); return; } if (!switchFs.Titles.TryGetValue(id, out Title title)) { ctx.Logger.LogMessage($"Could not find title {id:X16}"); return; } if (title.MainNca == null) { ctx.Logger.LogMessage($"Could not find main data for title {id:X16}"); return; } NcaSection section = title.MainNca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs || x?.Type == SectionType.Bktr); if (section == null) { ctx.Logger.LogMessage($"Main NCA for title {id:X16} has no RomFS section"); return; } if (ctx.Options.RomfsOutDir != null) { var romfs = new RomFsFileSystem(title.MainNca.OpenSection(section.SectionNum, false, ctx.Options.IntegrityLevel, true)); romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger); } if (ctx.Options.RomfsOut != null) { title.MainNca.ExportSection(section.SectionNum, ctx.Options.RomfsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger); } } if (ctx.Options.OutDir != null) { SaveTitle(ctx, switchFs); } if (ctx.Options.NspOut != null) { ProcessNsp.CreateNsp(ctx, switchFs); } if (ctx.Options.SaveOutDir != null) { ExportSdSaves(ctx, switchFs); } if (ctx.Options.Validate) { ValidateSwitchFs(ctx, switchFs); } }
public static void Process(Context ctx) { using (var file = new LocalStorage(ctx.Options.InFile, FileAccess.Read)) { var xci = new Xci(ctx.Keyset, file); ctx.Logger.LogMessage(xci.Print()); if (ctx.Options.RootDir != null) { xci.OpenPartition(XciPartitionType.Root).Extract(ctx.Options.RootDir, ctx.Logger); } if (ctx.Options.UpdateDir != null && xci.HasPartition(XciPartitionType.Update)) { xci.OpenPartition(XciPartitionType.Update).Extract(ctx.Options.UpdateDir, ctx.Logger); } if (ctx.Options.NormalDir != null && xci.HasPartition(XciPartitionType.Normal)) { xci.OpenPartition(XciPartitionType.Normal).Extract(ctx.Options.NormalDir, ctx.Logger); } if (ctx.Options.SecureDir != null && xci.HasPartition(XciPartitionType.Secure)) { xci.OpenPartition(XciPartitionType.Secure).Extract(ctx.Options.SecureDir, ctx.Logger); } if (ctx.Options.LogoDir != null && xci.HasPartition(XciPartitionType.Logo)) { xci.OpenPartition(XciPartitionType.Logo).Extract(ctx.Options.LogoDir, ctx.Logger); } if (ctx.Options.OutDir != null) { XciPartition root = xci.OpenPartition(XciPartitionType.Root); if (root == null) { ctx.Logger.LogMessage("Could not find root partition"); return; } foreach (PartitionFileEntry sub in root.Files) { var subPfs = new PartitionFileSystem(root.OpenFile(sub, OpenMode.Read).AsStorage()); string subDir = Path.Combine(ctx.Options.OutDir, sub.Name); subPfs.Extract(subDir, ctx.Logger); } } if (ctx.Options.ExefsOutDir != null || ctx.Options.ExefsOut != null) { Nca mainNca = GetXciMainNca(xci, ctx); if (mainNca == null) { ctx.Logger.LogMessage("Could not find Program NCA"); return; } NcaSection exefsSection = mainNca.Sections[(int)ProgramPartitionType.Code]; if (exefsSection == null) { ctx.Logger.LogMessage("NCA has no ExeFS section"); return; } if (ctx.Options.ExefsOutDir != null) { mainNca.ExtractSection(exefsSection.SectionNum, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger); } if (ctx.Options.ExefsOut != null) { mainNca.ExportSection(exefsSection.SectionNum, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger); } } if (ctx.Options.RomfsOutDir != null || ctx.Options.RomfsOut != null) { Nca mainNca = GetXciMainNca(xci, ctx); if (mainNca == null) { ctx.Logger.LogMessage("Could not find Program NCA"); return; } NcaSection romfsSection = mainNca.Sections.FirstOrDefault(x => x.Type == SectionType.Romfs); if (romfsSection == null) { ctx.Logger.LogMessage("NCA has no RomFS section"); return; } if (ctx.Options.RomfsOutDir != null) { var romfs = new RomFsFileSystem(mainNca.OpenSection(romfsSection.SectionNum, false, ctx.Options.IntegrityLevel, true)); romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger); } if (ctx.Options.RomfsOut != null) { mainNca.ExportSection(romfsSection.SectionNum, ctx.Options.RomfsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger); } } } }