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); CheckForNcaFolders(ctx, switchFs); } 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); CheckForNcaFolders(ctx, switchFs); } 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; } if (!title.MainNca.Nca.SectionExists(NcaSectionType.Code)) { ctx.Logger.LogMessage($"Main NCA for title {id:X16} has no ExeFS section"); return; } if (ctx.Options.ExefsOutDir != null) { IFileSystem fs = title.MainNca.OpenFileSystem(NcaSectionType.Code, ctx.Options.IntegrityLevel); fs.Extract(ctx.Options.ExefsOutDir, ctx.Logger); } if (ctx.Options.ExefsOut != null) { title.MainNca.OpenStorage(NcaSectionType.Code, ctx.Options.IntegrityLevel).WriteAllBytes(ctx.Options.ExefsOut, 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; } if (!title.MainNca.Nca.SectionExists(NcaSectionType.Data)) { ctx.Logger.LogMessage($"Main NCA for title {id:X16} has no RomFS section"); return; } ProcessRomfs.Process(ctx, title.MainNca.OpenStorage(NcaSectionType.Data, ctx.Options.IntegrityLevel)); } if (ctx.Options.OutDir != null) { SaveTitle(ctx, switchFs); } if (ctx.Options.NspOut != null) { ProcessPfs.CreateNsp(ctx, switchFs); } if (ctx.Options.SaveOutDir != null) { ExportSdSaves(ctx, switchFs); } if (ctx.Options.Validate) { ValidateSwitchFs(ctx, switchFs); } }
private static void RunTask(Context ctx) { switch (ctx.Options.InFileType) { case FileType.Nca: ProcessNca.Process(ctx); break; case FileType.Pfs0: case FileType.Nsp: ProcessPfs.Process(ctx); break; case FileType.PfsBuild: ProcessFsBuild.ProcessPartitionFs(ctx); break; case FileType.Romfs: ProcessRomfs.Process(ctx); break; case FileType.RomfsBuild: ProcessFsBuild.ProcessRomFs(ctx); break; case FileType.Nax0: ProcessNax0.Process(ctx); break; case FileType.SwitchFs: ProcessSwitchFs.Process(ctx); break; case FileType.Save: ProcessSave.Process(ctx); break; case FileType.Xci: ProcessXci.Process(ctx); break; case FileType.Keygen: ProcessKeygen(ctx); break; case FileType.Pk11: ProcessPackage.ProcessPk11(ctx); break; case FileType.Pk21: ProcessPackage.ProcessPk21(ctx); break; case FileType.Kip1: ProcessKip.ProcessKip1(ctx); break; case FileType.Ini1: ProcessKip.ProcessIni1(ctx); break; case FileType.Ndv0: ProcessDelta.Process(ctx); break; case FileType.Bench: ProcessBench.Process(ctx); break; default: throw new ArgumentOutOfRangeException(); } }