public static void Process(Context ctx) { using (IStorage deltaFile = new LocalStorage(ctx.Options.InFile, FileAccess.Read)) { IStorage deltaStorage = deltaFile; Span <byte> magic = stackalloc byte[4]; deltaFile.Read(magic, 0); if (MemoryMarshal.Read <uint>(magic) != Ndv0Magic) { try { var nca = new Nca(ctx.Keyset, deltaStorage, true); IFileSystem fs = nca.OpenSectionFileSystem(0, IntegrityCheckLevel.ErrorOnInvalid); if (!fs.FileExists(FragmentFileName)) { throw new FileNotFoundException("Specified NCA does not contain a delta fragment"); } deltaStorage = fs.OpenFile(FragmentFileName, OpenMode.Read).AsStorage(); } catch (InvalidDataException) { } // Ignore non-NCA3 files } var delta = new DeltaFragment(deltaStorage); if (ctx.Options.BaseFile != null) { using (IStorage baseFile = new LocalStorage(ctx.Options.BaseFile, FileAccess.Read)) { delta.SetBaseStorage(baseFile); if (ctx.Options.OutFile != null) { using (var outFile = new FileStream(ctx.Options.OutFile, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { IStorage patchedStorage = delta.GetPatchedStorage(); patchedStorage.CopyToStream(outFile, patchedStorage.Length, ctx.Logger); } } } } ctx.Logger.LogMessage(delta.Print()); } }
public static void Process(Context ctx) { using (IStorage file = new LocalStorage(ctx.Options.InFile, FileAccess.Read)) { var nca = new Nca(ctx.Keyset, file, false); nca.ValidateMasterHashes(); nca.ParseNpdm(); if (ctx.Options.BaseNca != null) { IStorage baseFile = new LocalStorage(ctx.Options.BaseNca, FileAccess.Read); var baseNca = new Nca(ctx.Keyset, baseFile, false); nca.SetBaseNca(baseNca); } for (int i = 0; i < 3; i++) { if (ctx.Options.SectionOut[i] != null) { nca.ExportSection(i, ctx.Options.SectionOut[i], ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger); } if (ctx.Options.SectionOutDir[i] != null) { nca.ExtractSection(i, ctx.Options.SectionOutDir[i], ctx.Options.IntegrityLevel, ctx.Logger); } if (ctx.Options.Validate && nca.Sections[i] != null) { nca.VerifySection(i, ctx.Logger); } } if (ctx.Options.ListRomFs && nca.Sections[1] != null) { var romfs = new RomFsFileSystem(nca.OpenSection(1, false, ctx.Options.IntegrityLevel, true)); foreach (DirectoryEntry entry in romfs.EnumerateEntries()) { ctx.Logger.LogMessage(entry.FullPath); } } if (ctx.Options.RomfsOutDir != null || ctx.Options.RomfsOut != null || ctx.Options.ReadBench) { NcaSection section = nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs || x?.Type == SectionType.Bktr); if (section == null) { ctx.Logger.LogMessage("NCA has no RomFS section"); return; } if (section.Type == SectionType.Bktr && ctx.Options.BaseNca == null) { ctx.Logger.LogMessage("Cannot save BKTR section without base RomFS"); return; } if (ctx.Options.RomfsOut != null) { nca.ExportSection(section.SectionNum, ctx.Options.RomfsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger); } if (ctx.Options.RomfsOutDir != null) { IFileSystem romfs = nca.OpenSectionFileSystem(section.SectionNum, ctx.Options.IntegrityLevel); romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger); } if (ctx.Options.ReadBench) { long bytesToRead = 1024L * 1024 * 1024 * 5; IStorage storage = nca.OpenSection(section.SectionNum, false, ctx.Options.IntegrityLevel, true); var dest = new NullStorage(storage.Length); int iterations = (int)(bytesToRead / storage.Length) + 1; ctx.Logger.LogMessage(iterations.ToString()); ctx.Logger.StartNewStopWatch(); for (int i = 0; i < iterations; i++) { storage.CopyTo(dest, ctx.Logger); ctx.Logger.LogMessage(ctx.Logger.GetRateString()); } ctx.Logger.PauseStopWatch(); ctx.Logger.LogMessage(ctx.Logger.GetRateString()); } } if (ctx.Options.ExefsOutDir != null || ctx.Options.ExefsOut != null) { if (nca.Header.ContentType != ContentType.Program) { ctx.Logger.LogMessage("NCA's content type is not \"Program\""); return; } NcaSection section = nca.Sections[(int)ProgramPartitionType.Code]; if (section == null) { ctx.Logger.LogMessage("Could not find an ExeFS section"); return; } if (ctx.Options.ExefsOut != null) { nca.ExportSection(section.SectionNum, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger); } if (ctx.Options.ExefsOutDir != null) { IFileSystem pfs = nca.OpenSectionFileSystem(section.SectionNum, ctx.Options.IntegrityLevel); pfs.Extract(ctx.Options.ExefsOutDir, ctx.Logger); } } if (ctx.Options.PlaintextOut != null) { nca.OpenDecryptedNca().WriteAllBytes(ctx.Options.PlaintextOut, ctx.Logger); } if (!ctx.Options.ReadBench) { ctx.Logger.LogMessage(nca.Print()); } } }