Exemplo n.º 1
0
        public void Load(System.IO.Stream stream)
        {
            string homeFolder   = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
            string KeyFile      = Path.Combine(homeFolder, ".switch", "prod.keys");
            string TitleKeyFile = Path.Combine(homeFolder, ".switch", "title.keys");

            var Keys = ExternalKeys.ReadKeyFile(KeyFile, TitleKeyFile);

            Stream Input;

            var Pfs       = new Pfs(stream.AsStorage());
            var CnmtNca   = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
            var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true));
            var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream());
            var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
            var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);

            if (CtrlEntry != null)
            {
                Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
            }
            Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream();

            var Nca = new Nca(Keys, Input.AsStorage(), true);

            Romfs romfs = new Romfs(
                Nca.OpenSection(Nca.Sections.FirstOrDefault
                                    (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                                .SectionNum, false, IntegrityCheckLevel.None, true));

            for (int i = 0; i < romfs.Files.Count; i++)
            {
                files.Add(new FileEntry(romfs, romfs.Files[i]));
            }
        }
Exemplo n.º 2
0
        public void Load(System.IO.Stream stream)
        {
            var Keys = Forms.SwitchKeySelectionForm.ShowKeySelector();

            if (Keys == null)
            {
                throw new Exception("Failed to get keys. Please select valid paths!");
            }

            var Pfs     = new Pfs(stream.AsStorage());
            var CnmtNca = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
            var CnmtPfs = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true));
            var Cnmt    = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream());

            foreach (var entry in Cnmt.ContentEntries)
            {
                if (entry.Type == CnmtContentType.Program)
                {
                    var    Program     = entry;
                    string ncaFileName = $"{Program.NcaId.ToHexString().ToLower()}.nca";

                    Stream Input = Pfs.OpenFile(ncaFileName).AsStream();
                    var    Nca   = new Nca(Keys, Input.AsStorage(), true);

                    string root = Nca.Header.TitleId.ToString("X");

                    Romfs romfs = new Romfs(
                        Nca.OpenSection(Nca.Sections.FirstOrDefault
                                            (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                                        .SectionNum, false, IntegrityCheckLevel.None, true));

                    if (Nca.CanOpenSection((int)ProgramPartitionType.Code))
                    {
                        var exefs = new Pfs(Nca.OpenSection((int)ProgramPartitionType.Code,
                                                            false, IntegrityCheckLevel.None, true));

                        foreach (var file in exefs.Files)
                        {
                            files.Add(new ExefsEntry(exefs, file, root));
                        }
                    }

                    for (int i = 0; i < romfs.Files.Count; i++)
                    {
                        files.Add(new FileEntry(romfs, romfs.Files[i], root));
                    }
                }
            }
            var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);

            if (CtrlEntry != null)
            {
                Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
            }
        }
Exemplo n.º 3
0
        public CnmtItem(Cnmt cnmt, SectionItem parentSectionItem, DirectoryEntryEx directoryEntry)
            : base(parentSectionItem, directoryEntry)
        {
            Cnmt = cnmt ?? throw new ArgumentNullException(nameof(cnmt));

            ParentItem         = parentSectionItem;
            PatchLevel         = GetPatchLevel(Cnmt.TitleVersion);
            TitleId            = Cnmt.TitleId.ToStrId();
            ApplicationTitleId = Cnmt.ApplicationTitleId.ToStrId();
            PatchTitleId       = Cnmt.PatchTitleId.ToStrId();
            TitleVersion       = Cnmt.TitleVersion?.Version.ToString();
        }
Exemplo n.º 4
0
        public static CnmtExtended GetCnmtExtended(string folderPath, Keyset keyset, Output Out)
        {
            var dirDecrypted = new DirectoryInfo(folderPath);

            foreach (var inFile in dirDecrypted.GetFiles("*.cnmt.nca"))
            {
                Out.Log($"{inFile}\r\n");
                var ncaStorage = new StreamStorage(new FileStream(inFile.FullName, FileMode.Open, FileAccess.Read),
                                                   false);
                var DecryptedHeader = new byte[0xC00];
                ncaStorage.Read(DecryptedHeader, 0, 0xC00, 0);
                var Header = new NcaHeader(new BinaryReader(new MemoryStream(DecryptedHeader)), keyset);

                for (var i = 0; i < 4; ++i)
                {
                    var section = NcaParseSection.ParseSection(Header, i);
                    if (section == null || section.Header.Type != SectionType.Pfs0)
                    {
                        continue;
                    }

                    IStorage sectionStorage = ncaStorage.Slice(section.Offset, section.Size, false);
                    IStorage pfs0Storage    = sectionStorage.Slice(section.Header.Sha256Info.DataOffset,
                                                                   section.Header.Sha256Info.DataSize, false);
                    var Pfs0Header = new PartitionFileSystemHeader(new BinaryReader(pfs0Storage.AsStream()));
                    var FileDict   = Pfs0Header.Files.ToDictionary(x => x.Name, x => x);

                    foreach (var file in FileDict)
                    {
                        if (file.Key.EndsWith(".cnmt"))
                        {
                            IStorage fileStorage = pfs0Storage.Slice(Pfs0Header.HeaderSize + file.Value.Offset,
                                                                     file.Value.Size, false);
                            var metadata = new Cnmt(fileStorage.AsStream());
                            if (metadata.ExtendedData != null)
                            {
                                ncaStorage.Dispose();
                                return(metadata.ExtendedData);
                            }
                        }
                    }
                }

                ncaStorage.Dispose();
            }

            return(null);
        }
Exemplo n.º 5
0
        // fs must contain AOC nca files in its root
        public void AddAocData(IFileSystem fs, string containerPath, ulong aocBaseId)
        {
            _virtualFileSystem.ImportTickets(fs);

            foreach (var ncaPath in fs.EnumerateEntries("*.cnmt.nca", SearchOptions.Default))
            {
                fs.OpenFile(out IFile ncaFile, ncaPath.FullPath.ToU8Span(), OpenMode.Read);
                using (ncaFile)
                {
                    var nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
                    if (nca.Header.ContentType != NcaContentType.Meta)
                    {
                        Logger.Warning?.Print(LogClass.Application, $"{ncaPath} is not a valid metadata file");

                        continue;
                    }

                    using var pfs0 = nca.OpenFileSystem(0, Switch.GetIntegrityCheckLevel());

                    pfs0.OpenFile(out IFile cnmtFile, pfs0.EnumerateEntries().Single().FullPath.ToU8Span(), OpenMode.Read);

                    using (cnmtFile)
                    {
                        var cnmt = new Cnmt(cnmtFile.AsStream());

                        if (cnmt.Type != ContentMetaType.AddOnContent || (cnmt.TitleId & 0xFFFFFFFFFFFFE000) != aocBaseId)
                        {
                            continue;
                        }

                        string ncaId = BitConverter.ToString(cnmt.ContentEntries[0].NcaId).Replace("-", "").ToLower();
                        if (!_aocData.TryAdd(cnmt.TitleId, new AocItem(containerPath, $"{ncaId}.nca", true)))
                        {
                            Logger.Warning?.Print(LogClass.Application, $"Duplicate AddOnContent detected. TitleId {cnmt.TitleId:X16}");
                        }
                        else
                        {
                            Logger.Info?.Print(LogClass.Application, $"Found AddOnContent with TitleId {cnmt.TitleId:X16}");
                        }
                    }
                }
            }
        }
Exemplo n.º 6
0
        public CnmtInfo[] GetContentEntries(IStorage NcaStorage)
        {
            if (Config.Keyset is null)
            {
                throw new ArgumentNullException(nameof(Config.Keyset));
            }

            List <CnmtInfo> res = new List <CnmtInfo>();

            var nca = new Nca(Config.Keyset, NcaStorage);

            using IFileSystem fs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
            foreach (var entry in fs.EnumerateEntries("/", "*.cnmt"))
            {
                fs.OpenFile(out IFile fp, new U8Span(entry.Name), OpenMode.Read);
                Cnmt cnmt = new Cnmt(fp.AsStream());

                foreach (var meta_entry in cnmt.MetaEntries)
                {
                    var i = new CnmtInfo
                    {
                        IsMeta  = true,
                        TitleID = $"0{meta_entry.TitleId:X}",
                        Version = meta_entry.Version.Version.ToString()
                    };
                    Trace.WriteLine($"[GetContentEntries] From {cnmt.TitleId:x} => {i}");
                    res.Add(i);
                }

                foreach (var content_entry in cnmt.ContentEntries)
                {
                    var i = new CnmtInfo
                    {
                        IsMeta = false,
                        NcaID  = content_entry.NcaId.ToHexString().ToLower(),
                    };
                    Trace.WriteLine($"[GetContentEntries] From {cnmt.TitleId:x} => {i}");
                    res.Add(i);
                }
            }

            return(res.ToArray());
        }
Exemplo n.º 7
0
        public void AddNcaInfo()
        {
            if (Config.verbose)
            {
                Console.WriteLine($"Parsing File:     {path}");
            }

            infile = new LocalStorage(path, FileAccess.Read);

            try
            {
                data = new Nca(Config.keyset, infile);
            }
            catch (Exception e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Unable to create NCA class. Is your keyset file valid?");
                Console.WriteLine($"Error: {e.Message}");
                Console.ResetColor();
                Environment.Exit(0);
            }

            if (header.ContentType == NcaContentType.Meta)
            {
                using IFileSystem fs = data.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
                string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;

                fs.OpenFile(out IFile cnmtFile, new U8Span(cnmtPath), OpenMode.Read).ThrowIfFailure();
                cnmt = new Cnmt(cnmtFile.AsStream());

                cnmtFile.GetSize(out long size);
                byte[] cnmtRaw = new byte[size];
                cnmtFile.Read(out long none, 0, cnmtRaw);

                cnmt_raw = new CnmtRawParser(cnmtRaw);
            }

            titleId = header.TitleId.ToString("x16").ToUpper();
        }
Exemplo n.º 8
0
        private void Open()
        {
            treeView1.Nodes.Clear();

            string FileToOpen = null;

            if (Program.FileArg != null)
            {
                FileToOpen = Program.FileArg;
            }
            else
            {
                FileToOpen = openFileDialog1.FileName;
            }

            Program.FileArg = null;
            Stream Input = null;

            try
            {
                string ExpEnv(string In) => Environment.ExpandEnvironmentVariables(In);

                var ProdKeys  = ExpEnv(@"%USERPROFILE%\.switch\prod.keys");
                var TitleKeys = ExpEnv(@"%USERPROFILE%\.switch\title.keys");

                var Keys = ExternalKeys.ReadKeyFile(ProdKeys, TitleKeys);

                var Ext = (new FileInfo(FileToOpen).Extension);

                if (Ext == ".nsp")
                {
                    var InputPFS  = File.OpenRead(FileToOpen);
                    var Pfs       = new Pfs(InputPFS);
                    var CnmtNca   = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
                    var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None));
                    var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]));
                    var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                    var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                    if (CtrlEntry != null)
                    {
                        Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                    }
                    Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca");
                }
                else if (Ext == ".xci")
                {
                    var InputPFS  = File.OpenRead(FileToOpen);
                    var Xci       = new Xci(Keys, InputPFS);
                    var CnmtNca   = new Nca(Keys, Xci.SecurePartition.OpenFile(Xci.SecurePartition.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
                    var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None));
                    var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]));
                    var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                    var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                    if (CtrlEntry != null)
                    {
                        Control = new Nca(Keys, Xci.SecurePartition.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                    }
                    Input = Xci.SecurePartition.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca");
                }
                else if (FileToOpen.Split('.')[1] == "cnmt" && Ext == ".nca")
                {
                    var TargetFile = File.OpenRead(FileToOpen);
                    var CnmtNca    = new Nca(Keys, TargetFile, false);
                    var CnmtPfs    = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None));
                    var Cnmt       = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]));
                    var Program    = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                    var CtrlEntry  = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                    if (CtrlEntry != null)
                    {
                        Control = new Nca(Keys, File.OpenRead($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                    }
                    Input = File.OpenRead($"{Program.NcaId.ToHexString().ToLower()}.nca");
                }
                else
                {
                    Input = File.OpenRead(FileToOpen);
                }

                try
                {
                    Nca = new Nca(Keys, Input, true);

                    if (Nca.HasRightsId && !Keys.TitleKeys.Keys.Any(k => k.SequenceEqual(Nca.Header.RightsId)))
                    {
                        MessageBox.Show($"Error: the titlekey for {Nca.Header.RightsId.ToHexString().ToLower()} is not present in your key file.");
                    }
                    else
                    {
                        bool isUpdateNca = false;

                        if (Nca.Sections.Any(s => s?.Type == SectionType.Bktr))
                        {
                            isUpdateNca = true;
                        }

                        if (isUpdateNca)
                        {
                            openFileDialog1.Title = "Select base Nca";
                            openFileDialog1.ShowDialog();
                            var Input2 = File.OpenRead(openFileDialog1.FileName);
                            Patch = new Nca(Keys, Input2, true);
                            Nca.SetBaseNca(Patch);
                        }

                        new Thread
                        (
                            () =>
                        {
                            Thread.CurrentThread.IsBackground = true;
                            var Info = GetTitleMeta($"{Nca.Header.TitleId:x16}");

                            label2.Invoke(new Action(() => { label2.Text = Info[0]; label3.Text = Info[1]; }));
                        }
                        )
                        .Start();

                        Rom = new Romfs
                              (
                            Nca.OpenSection
                            (
                                Nca.Sections.FirstOrDefault
                                    (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                                .SectionNum,
                                false,
                                IntegrityCheckLevel.None
                            )
                              );

                        IO.PopulateTreeView(treeView1.Nodes, Rom.RootDir);
                    }
                }
                catch
                {
                    MessageBox.Show("There was an error reading the NCA. Are you sure the correct keys are present in your keyfiles?");
                }
            }
            catch (ArgumentNullException)
            {
                MessageBox.Show("Error: key files are missing!");
            }
        }
Exemplo n.º 9
0
        //Open update only
        private void Open_NSP_Update(object sender, EventArgs e)
        {
            var Dialog = openFileDialog1.ShowDialog();

            if (Dialog != DialogResult.Cancel)
            {
                Console.WriteLine("LOADING.");
                label8.Visible = true;
                this.Update();
                treeView1.Nodes.Clear();

                string FileToOpen = null;

                if (Program.FileArg != null)
                {
                    FileToOpen = Program.FileArg;
                }
                else
                {
                    FileToOpen = openFileDialog1.FileName;
                }

                Program.FileArg = null;
                Stream Input = null;

                try
                {
                    string ExpEnv(string In) => Environment.ExpandEnvironmentVariables(In);

                    var ProdKeys  = ExpEnv(@"%USERPROFILE%\.switch\prod.keys");
                    var TitleKeys = ExpEnv(@"%USERPROFILE%\.switch\title.keys");
                    Console.WriteLine(FileToOpen);

                    var Keys = ExternalKeys.ReadKeyFile(ProdKeys, TitleKeys);

                    var Ext = (new FileInfo(FileToOpen).Extension);
                    if (Ext == ".nsp")
                    {
                        var InputPFS  = File.OpenRead(FileToOpen);
                        var Pfs       = new Pfs(InputPFS.AsStorage());
                        var CnmtNca   = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
                        var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true));
                        var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream());
                        var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                        var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                        if (CtrlEntry != null)
                        {
                            Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                        }
                        Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream();
                    }
                    else
                    {
                        Input = File.OpenRead(FileToOpen);
                    }

                    try
                    {
                        Nca = new Nca(Keys, Input.AsStorage(), true);

                        if (Nca.HasRightsId && !Keys.TitleKeys.Keys.Any(k => k.SequenceEqual(Nca.Header.RightsId)))
                        {
                            MessageBox.Show($"Error: the titlekey for {Nca.Header.RightsId.ToHexString().ToLower()} is not present in your key file.");
                        }
                        else
                        {
                            var isUpdateNca = false;

                            if (Nca.Sections.Any(s => s?.Type == SectionType.Bktr))
                            {
                                isUpdateNca = true;
                            }

                            if (isUpdateNca)
                            {
                                var InputPFS  = File.OpenRead(FileToOpen);
                                var Pfs       = new Pfs(InputPFS.AsStorage());
                                var CnmtNca   = new Nca(Keys, Pfs.OpenFile(Pfs.Files.FirstOrDefault(s => s.Name.Contains(".cnmt.nca"))), false);
                                var CnmtPfs   = new Pfs(CnmtNca.OpenSection(0, false, IntegrityCheckLevel.None, true));
                                var Cnmt      = new Cnmt(CnmtPfs.OpenFile(CnmtPfs.Files[0]).AsStream());
                                var Program   = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Program);
                                var CtrlEntry = Cnmt.ContentEntries.FirstOrDefault(c => c.Type == CnmtContentType.Control);
                                if (CtrlEntry != null)
                                {
                                    Control = new Nca(Keys, Pfs.OpenFile($"{CtrlEntry.NcaId.ToHexString().ToLower()}.nca"), false);
                                }
                                Input = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream();

                                var Input2 = Pfs.OpenFile($"{Program.NcaId.ToHexString().ToLower()}.nca").AsStream();
                                Patch = new Nca(Keys, Input2.AsStorage(), true);
                                Nca.SetBaseNca(Patch);
                            }

                            new Thread
                                (() =>
                            {
                                Thread.CurrentThread.IsBackground = true;
                                var Info = GetTitleMeta($"{Nca.Header.TitleId:x16}");
                                label2.Invoke(new Action(() => { label2.Text = Info[0]; label3.Text = Info[1]; }));
                            }).Start();

                            Rom = new Romfs(
                                Nca.OpenSection(Nca.Sections.FirstOrDefault
                                                    (s => s?.Type == SectionType.Romfs || s?.Type == SectionType.Bktr)
                                                .SectionNum, false, IntegrityCheckLevel.None, true)
                                );

                            IO.PopulateTreeView(treeView1.Nodes, Rom.RootDir);

                            Console.WriteLine("DONE.");
                            fileToolStripMenuItem.Text = "File / Explore";
                            label8.Visible             = false;
                            this.Update();
                        }
                    }
                    catch
                    {
                        MessageBox.Show("There was an error reading the NCA. Are you sure the correct keys are present in your keyfiles?");
                    }
                }
                catch (ArgumentNullException) { MessageBox.Show("Error: key files are missing!"); }
            }
        }
Exemplo n.º 10
0
        static void Main(string[] args)
        {
            Console.WriteLine("Nintendo Switch NSP Verifier v1.00");
            Console.WriteLine("Copyright 2018 CaitSith2");
            Console.WriteLine("");

            _path = args.Length >= 1
                ? string.Join(" ", args)
                : Environment.CurrentDirectory;

            if (new[] { "--help", "-h" }.Any(x => x.Equals(_path, StringComparison.InvariantCultureIgnoreCase)))
            {
                Console.WriteLine("Usage: NSPVerify [path to NSP directory]");
                Console.WriteLine("");
                Console.WriteLine("If the tool is run without specifying a path, it will look for NSPs in the current directory and ALL sub-directories of current directory");
                return;
            }



            if (!Directory.Exists(_path))
            {
                Console.WriteLine("ERROR: Specified directory does not exist.  specify --help for usage information.");
                return;
            }

            var fs = new FileSystem(_path);

            var keys = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch", "prod.keys");

            if (File.Exists("keys.txt"))
            {
                keys = "keys.txt";
            }

            if (!File.Exists(keys))
            {
                Console.WriteLine($"Cannot verify NSPs without keys.txt. Either put it in the same directory as this tool,");
                Console.WriteLine($"or place it in \"{Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch")}\" named as prod.keys");
                PressAnyKey();
                return;
            }

            var keyset        = ExternalKeys.ReadKeyFile(keys);
            var badlist       = new List <string>();
            var exceptionlist = new List <string>();

            var files = fs.GetFileSystemEntries("", "*.nsp", SearchOption.AllDirectories).ToList();

            files.AddRange(fs.GetFileSystemEntries("", "*.nsx", SearchOption.AllDirectories));

            if (files.Count == 0)
            {
                Console.WriteLine("Error: No NSP/NSX files in specified directory");
                PressAnyKey();
                return;
            }

            foreach (var file in files)
            {
                var filename         = Path.GetFileName(file);
                var relativefilename = Util.GetRelativePath(file, Path.GetFullPath(_path));
                Console.Write($"Checking {filename}: ");
                try
                {
                    bool ok = true;
                    using (var nspfile = fs.OpenFile(file, FileMode.Open, FileAccess.Read))
                    {
                        var nspdata  = new Pfs(nspfile);
                        var cnmtfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(".cnmt.nca"));
                        if (cnmtfile == null)
                        {
                            Console.WriteLine($"\rChecking {filename}: No cnmt.nca file present");
                            badlist.Add(relativefilename);
                            continue;
                        }

                        var  cnmtdata = nspdata.OpenFile(cnmtfile);
                        Cnmt cnmt;
                        using (var sr = new BinaryReader(cnmtdata))
                        {
                            var cnmthash = SHA256.Create().ComputeHash(sr.ReadBytes((int)cnmtdata.Length));
                            if (!cnmtfile.Name.ToLowerInvariant().Contains(cnmthash.Take(16).ToArray().ToHexString()))
                            {
                                //Put failure here
                                Console.WriteLine($"\rChecking {filename}: cnmt.nca file is corrupted");
                                badlist.Add(relativefilename);
                                cnmtdata.Dispose();
                                continue;
                            }

                            cnmtdata.Position = 0;
                            var cnmtnca    = new Nca(keyset, cnmtdata, false);
                            var section    = cnmtnca.OpenSection(0, false);
                            var sectionpfs = new Pfs(section);
                            cnmt = new Cnmt(sectionpfs.OpenFile(sectionpfs.Files[0]));
                        }

                        foreach (var entry in cnmt.ContentEntries)
                        {
                            var entryfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(entry.NcaId.ToHexString() + ".nca"));
                            if (entryfile == null)
                            {
                                if (entry.Type != CnmtContentType.UpdatePatch)
                                {
                                    //Put failure here
                                    Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is missing.");
                                    badlist.Add(relativefilename);
                                    break;
                                }

                                continue;
                            }

                            using (var entrynca = nspdata.OpenFile(entryfile))
                            {
                                var hash = SHA256.Create();

                                using (var sr = new BinaryReader(entrynca))
                                {
                                    while (entrynca.Length != entrynca.Position)
                                    {
                                        var entryncadata = sr.ReadBytes(0x100000);
                                        hash.TransformBlock(entryncadata, 0, entryncadata.Length, entryncadata, 0);
                                        Console.Write($"\rChecking {filename}: {((entrynca.Position * 100.0) / entrynca.Length):0.0}%");
                                    }

                                    hash.TransformFinalBlock(new byte[0], 0, 0);
                                }

                                if (hash.Hash.ToHexString().Equals(entry.Hash.ToHexString()))
                                {
                                    Console.Write($"\rChecking {filename}: {100:0.0}%");
                                    continue;
                                }

                                //Put failure here
                                Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is corrupted");
                                badlist.Add(relativefilename);
                                ok = false;
                                break;
                            }
                        }

                        if (ok)
                        {
                            Console.WriteLine($"\rChecking {filename}: OK        ");
                        }
                        //Put Success here
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                    exceptionlist.Add($"{relativefilename}{Environment.NewLine}Exception: \"{ex.GetType()}\" {ex.Message}{Environment.NewLine}Stack Trace: {ex.StackTrace}{Environment.NewLine}");
                }
            }

            badlist.Insert(0, badlist.Count == 0
                ? "None of the files are corrupted. :)"
                : "The following NSP/NSX files are corrupted:");

            exceptionlist.Insert(0, exceptionlist.Count == 0
                ? "No exceptions to log. :)"
                : "Exceptions caused while parsing the following NSP/NSX files:");

            try
            {
                File.WriteAllText("Corrupted NSPs.txt", string.Join(Environment.NewLine, badlist));
                File.WriteAllText("Exception Log.txt", string.Join(Environment.NewLine, exceptionlist));
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Could not write the output files \"Corrupted NSPs.txt\" and \"Exception Log.txt\" due to the following exception.");
                Console.WriteLine($"Exception: \"{ex.GetType()}\" {ex.Message}");
                Console.WriteLine($"Stack Trace: {ex.StackTrace}{Environment.NewLine}");

                Console.WriteLine(string.Join(Environment.NewLine, badlist));
                Console.WriteLine();
                Console.WriteLine(string.Join(Environment.NewLine, exceptionlist));
                Console.WriteLine();
            }

            Console.WriteLine("Done.");
            PressAnyKey();
        }
Exemplo n.º 11
0
        private static (string, string) processCnmtNca(Nca nca, ref Title title, bool cnmtContent = true)
        {
            string biggestNca = null, controlNca = null;

            log?.WriteLine("Processing CNMT NCA");

            try
            {
                Pfs ncaPfs = new Pfs(nca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true));

                PfsFileEntry[] ncaFileEntries = ncaPfs.Files;
                foreach (PfsFileEntry pfsEntry in ncaFileEntries)
                {
                    Cnmt cnmt = new Cnmt(ncaPfs.OpenFile(pfsEntry).AsStream());

                    if (title.version == unchecked ((uint)-1) || cnmt.TitleVersion?.Version > title.version)
                    {
                        title.type = cnmt.Type;

                        title.titleID     = String.Format("{0:X16}", cnmt.TitleId);
                        title.baseTitleID = String.Format("{0:X16}", cnmt.ApplicationTitleId);
                        title.version     = cnmt.TitleVersion?.Version ?? title.version;

                        title.systemVersion      = cnmt.MinimumSystemVersion?.Version ?? unchecked ((uint)-1);
                        title.applicationVersion = cnmt.MinimumApplicationVersion?.Version ?? unchecked ((uint)-1);

                        if (cnmtContent)
                        {
                            CnmtContentEntry[] contentEntries = cnmt.ContentEntries;
                            foreach (CnmtContentEntry contentEntry in contentEntries)
                            {
                                if (title.type == TitleType.Application || title.type == TitleType.Patch)
                                {
                                    if (contentEntry.Type == CnmtContentType.Program)
                                    {
                                        biggestNca = BitConverter.ToString(contentEntry.NcaId).Replace("-", "").ToLower() + ".nca";

                                        log?.WriteLine("Found Biggest NCA {0}", biggestNca);
                                    }
                                    else if (contentEntry.Type == CnmtContentType.Control)
                                    {
                                        controlNca = BitConverter.ToString(contentEntry.NcaId).Replace("-", "").ToLower() + ".nca";

                                        log?.WriteLine("Found Control NCA {0}", controlNca);
                                    }
                                }
                                else if (title.type == TitleType.AddOnContent)
                                {
                                    if (contentEntry.Type == CnmtContentType.Data)
                                    {
                                        biggestNca = BitConverter.ToString(contentEntry.NcaId).Replace("-", "").ToLower() + ".nca";

                                        log?.WriteLine("Found Biggest NCA {0}", biggestNca);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (MissingKeyException ex)
            {
                title.error = String.Format("Missing {0}: {1}", ex.Type == KeyType.Title ? "Title Key" : "Key", ex.Name.Replace("key_area_key_application", "master_key"));

                log?.WriteLine(title.error);
            }
            catch (FileNotFoundException) { }

            return(biggestNca, controlNca);
        }
Exemplo n.º 12
0
        private static void Main(string[] args)
        {
            var keyFile       = Environment.ExpandEnvironmentVariables("%USERPROFILE%/.switch/prod.keys");
            var keysInUserDir = true;

            var getDeltasOnly = false;

            #region Pre-execution checks
            if (!File.Exists(keyFile))
            {
                if (!File.Exists("prod.keys"))
                {
                    Console.Error.WriteLine("Error: prod.keys is missing!");
                    return;
                }
                else
                {
                    keysInUserDir = false;
                }
            }

            if (!File.Exists("edge.token"))
            {
                Console.Error.WriteLine("Error: Please add an edge token to a file named \"edge.token\".");
                return;
            }

            if (!File.Exists("device.id"))
            {
                Console.Error.WriteLine("Error: Please add your device ID in hexadecimal text form to a file named \"device.id\".");
                return;
            }

            if (!File.Exists("nx_tls_client_cert.pfx"))
            {
                Console.Error.WriteLine("Error: Please add your Switch certificate to a file named \"nx_tls_client_cert.pfx\".");
                return;
            }
            #endregion

            var deviceID = Convert.ToInt64(File.ReadAllText("device.id"), 16);
            var keys     = ExternalKeys.ReadKeyFile(keysInUserDir ? keyFile : "prod.keys");

            var sysID = "0100000000000816";

            // To-do: Clean up
            if (args[0] == "-s" || args[0] == sysID)
            {
                var JSON    = (string)GET(deviceID, SunUrl, true);
                var Version = args.Length > 1 ? args[1] : (string)JObject.Parse(JSON)["system_update_metas"][0]["title_version"];
                HEAD(deviceID, nMetaURL('s', sysID, Version, deviceID));
                var contentID = HEAD(deviceID, nMetaURL('s', sysID, Version, deviceID));

                using (var meta = (HttpWebResponse)GET(deviceID, nContentURL('s', contentID), false))
                    using (var rd = new BinaryReader(meta.GetResponseStream()))
                        using (var strm = new MemoryStorage(rd.ReadBytes((int)meta.ContentLength)))
                        {
                            Directory.CreateDirectory(sysID);
                            strm.WriteAllBytes($"{sysID}/{contentID}.cnmt.nca");
                            using (var nca = new Nca(keys, strm, false).OpenSection(0, false, IntegrityCheckLevel.None, false))
                            {
                                var pfs  = new Pfs(nca);
                                var cnmt = new Cnmt(pfs.OpenFile(pfs.Files[0]).AsStream());
                                foreach (var entry in cnmt.MetaEntries)
                                {
                                    var tid = $"{entry.TitleId:x16}";
                                    HEAD(deviceID, nMetaURL('a', tid, $"{entry.Version.Version}", deviceID));
                                    var cID = HEAD(deviceID, nMetaURL('a', tid, $"{entry.Version.Version}", deviceID));

                                    using (var met2 = (HttpWebResponse)GET(deviceID, nContentURL('a', cID), false))
                                        using (var rdr = new BinaryReader(met2.GetResponseStream()))
                                            using (var strm2 = new MemoryStorage(rdr.ReadBytes((int)meta.ContentLength)))
                                            {
                                                Directory.CreateDirectory($"{sysID}/{tid}");
                                                strm2.WriteAllBytes($"{sysID}/{tid}/{cID}.cnmt.nca");
                                                using (var nca2 = new Nca(keys, strm2, false).OpenSection(0, false, IntegrityCheckLevel.None, false))
                                                {
                                                    var pfs2  = new Pfs(nca2);
                                                    var cnmt2 = new Cnmt(pfs2.OpenFile(pfs2.Files[0]).AsStream());
                                                    foreach (var entry2 in cnmt2.ContentEntries)
                                                    {
                                                        string NCAID = entry2.NcaId.ToHexString().ToLower();
                                                        using (var Req = (HttpWebResponse)GET(deviceID, nContentURL('c', NCAID), false))
                                                            using (var Output = File.OpenWrite($"{sysID}/{tid}/{NCAID}.nca"))
                                                                Req.GetResponseStream().CopyTo(Output);
                                                    }
                                                }
                                            }
                                }
                            }
                        }

                return;
            }

            string id          = null,
                   idFirstReq  = null,
                   idSecondReq = null;

            List <string> tidTargets   = new List <string>(),
                          verTargets   = new List <string>(),
                          entryTargets = new List <string>();

            var numOfListings = 0;

            if (args.Length == 2)
            {
                if (args[1] == "-d")
                {
                    getDeltasOnly = true;
                }
                else if (args[0] == "-t")
                {
                    var rightsID = args[1];
                    using (var tikReq = (HttpWebResponse)GET(deviceID, CETKURL(rightsID), false))
                        using (var strm = tikReq.GetResponseStream())
                            using (var rd = new BinaryReader(strm))
                            {
                                File.WriteAllBytes($"{rightsID}.tik", rd.ReadBytes(0x2C0));
                                File.WriteAllBytes($"{rightsID}.cert", rd.ReadBytes(0x700));
                            }

                    return;
                }
            }

            GET(deviceID, Aqua(deviceID), false);

            if (args.Length == 3)
            {
                numOfListings = 2;
                if (args[0].Substring(13, 3) != "000" && args[0].Substring(13, 3) != "800")
                {
                    tidTargets.Add(null);
                    tidTargets.Add(args[0]);
                }
                else
                {
                    tidTargets.Add(null);
                    tidTargets.Add($"{args[0].Substring(0, 13)}800");
                }
                verTargets.Add(null);
                verTargets.Add(args[2]);
            }
            else
            {
                var Streq = (string)GET(deviceID, Superfly(GetBaseTID(args[0])), true);
                if (args[0].Substring(13, 3) == "000")
                {
                    foreach (JToken Listing in JArray.Parse(Streq))
                    {
                        if ((string)Listing["title_type"] != "AddOnContent")
                        {
                            numOfListings++;
                            tidTargets.Add(Listing["title_id"].ToString());
                            verTargets.Add(Listing["version"].ToString());
                        }
                    }
                }
                else
                {
                    foreach (JToken Listing in JArray.Parse(Streq))
                    {
                        if ((string)Listing["title_id"] == args[0])
                        {
                            numOfListings++;
                            tidTargets.Add(Listing["title_id"].ToString());
                            verTargets.Add(Listing["version"].ToString());
                        }
                    }
                }
            }

            if (args.Length == 1)
            {
                id = HEAD(deviceID, MetaURL('a', tidTargets[0], verTargets[0], deviceID));
            }

            if (args.Length == 1 && id != null)
            {
                GET(deviceID, ContentURL('a', id), true);
            }

            if (numOfListings >= 2)
            {
                idFirstReq = HEAD(deviceID, MetaURL('a', tidTargets[1], verTargets[1], deviceID));
            }

            if (args.Length == 1 && numOfListings >= 2)
            {
                GET(deviceID, ContentURL('a', idFirstReq), true);
            }

            if (numOfListings >= 2)
            {
                idSecondReq = HEAD(deviceID, MetaURL('a', tidTargets[1], verTargets[1], deviceID));
            }

            if (numOfListings >= 2)
            {
                GET(deviceID, ContentURL('a', idSecondReq), true);
            }

            if (args.Length == 1)
            {
                using (var meta = (HttpWebResponse)GET(deviceID, ContentURL('a', id), false))
                    using (var rd = new BinaryReader(meta.GetResponseStream()))
                        using (var strm = new MemoryStorage(rd.ReadBytes((int)meta.ContentLength)))
                        {
                            Directory.CreateDirectory(tidTargets[0]);
                            strm.WriteAllBytes($"{tidTargets[0]}/{id}.cnmt.nca");
                            using (var nca = new Nca(keys, strm, false).OpenSection(0, false, IntegrityCheckLevel.None, false))
                            {
                                var pfs  = new Pfs(nca);
                                var cnmt = new Cnmt(pfs.OpenFile(pfs.Files[0]).AsStream());
                                foreach (var entry in cnmt.ContentEntries)
                                {
                                    string NCAID = entry.NcaId.ToHexString().ToLower();
                                    using (var Req = (HttpWebResponse)GET(deviceID, ContentURL('c', NCAID), false))
                                        using (var Output = File.OpenWrite($"{tidTargets[0]}/{NCAID}.nca"))
                                            Req.GetResponseStream().CopyTo(Output);
                                }
                            }
                        }
            }

            if (numOfListings >= 2)
            {
                using (var meta = (HttpWebResponse)GET(deviceID, ContentURL('a', idSecondReq), false))
                    using (var read = new BinaryReader(meta.GetResponseStream()))
                        using (var metastrm = new MemoryStorage(read.ReadBytes((int)meta.ContentLength)))
                        {
                            Directory.CreateDirectory(tidTargets[1]);
                            metastrm.WriteAllBytes($"{tidTargets[1]}/{idSecondReq}.cnmt.nca");
                            using (var nca = new Nca(keys, metastrm, false).OpenSection(0, false, IntegrityCheckLevel.None, false))
                            {
                                var pfs  = new Pfs(nca);
                                var cnmt = new Cnmt(pfs.OpenFile(pfs.Files[0]).AsStream());
                                foreach (var entry in getDeltasOnly ?
                                         cnmt.ContentEntries.Where(e => e.Type == CnmtContentType.DeltaFragment) :
                                         cnmt.ContentEntries)
                                {
                                    var ncaID = entry.NcaId.ToHexString().ToLower();
                                    using (var request = (HttpWebResponse)GET(deviceID, ContentURL('c', ncaID), false))
                                        using (var output = File.OpenWrite($"{tidTargets[1]}/{ncaID}.nca"))
                                            request.GetResponseStream().CopyTo(output);

                                    if (entry.Type == CnmtContentType.Program)
                                    {
                                        var rightsID = new Nca(keys, new StreamStorage
                                                                   (File.OpenRead($"{tidTargets[1]}/{ncaID}.nca"), false), false)
                                                       .Header.RightsId.ToHexString().ToLower();

                                        using (var tikReq = (HttpWebResponse)GET(deviceID, CETKURL(rightsID), false))
                                            using (var strm = tikReq.GetResponseStream())
                                                using (var rd = new BinaryReader(strm))
                                                {
                                                    File.WriteAllBytes($"{tidTargets[1]}/{rightsID}.tik", rd.ReadBytes(0x2C0));
                                                    File.WriteAllBytes($"{tidTargets[1]}/{rightsID}.cert", rd.ReadBytes(0x700));
                                                }
                                    }
                                }
                            }
                        }
            }
        }
Exemplo n.º 13
0
        static void Main(string[] args)
        {
            var path = args.Length >= 1
                ? args[0]
                : Environment.CurrentDirectory;

            var fs = new FileSystem(path);

            if (!File.Exists("keys.txt"))
            {
                Console.WriteLine("Cannot verify NSPs without keys.txt");
                Console.WriteLine();
                Console.WriteLine("Press any key to continue");
                Console.ReadKey();
                return;
            }

            var keyset        = ExternalKeys.ReadKeyFile("keys.txt");
            var badlist       = new List <string>();
            var exceptionlist = new List <string>();



            foreach (var file in fs.GetFileSystemEntries("", "*.nsp", SearchOption.AllDirectories))
            {
                var filename = Path.GetFileName(file);
                var progress = $"Checking {filename}: ";
                Console.Write(progress);
                try
                {
                    bool ok = true;
                    using (var nspfile = fs.OpenFile(file, FileMode.Open, FileAccess.Read))
                    {
                        var nspdata  = new Pfs(nspfile);
                        var cnmtfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(".cnmt.nca"));
                        if (cnmtfile == null)
                        {
                            Console.WriteLine($"\rChecking {filename}: No cnmt.nca file present");
                            badlist.Add(filename);
                            continue;
                        }

                        var  cnmtdata = nspdata.OpenFile(cnmtfile);
                        Cnmt cnmt;
                        using (var sr = new BinaryReader(cnmtdata))
                        {
                            var cnmthash = SHA256.Create().ComputeHash(sr.ReadBytes((int)cnmtdata.Length));
                            if (!cnmtfile.Name.ToLowerInvariant().Contains(cnmthash.Take(16).ToArray().ToHexString()))
                            {
                                //Put failure here
                                Console.WriteLine($"\rChecking {filename}: cnmt.nca file is corrupted");
                                badlist.Add(filename);
                                cnmtdata.Dispose();
                                continue;
                            }

                            cnmtdata.Position = 0;
                            var cnmtnca    = new Nca(keyset, cnmtdata, false);
                            var section    = cnmtnca.OpenSection(0, false);
                            var sectionpfs = new Pfs(section);
                            cnmt = new Cnmt(sectionpfs.OpenFile(sectionpfs.Files[0]));
                        }

                        foreach (var entry in cnmt.ContentEntries)
                        {
                            var entryfile = nspdata.Files.FirstOrDefault(x => x.Name.ToLowerInvariant().EndsWith(entry.NcaId.ToHexString() + ".nca"));
                            if (entryfile == null)
                            {
                                if (entry.Type != CnmtContentType.UpdatePatch)
                                {
                                    //Put failure here
                                    Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is missing.");
                                    badlist.Add(filename);
                                    break;
                                }

                                continue;
                            }

                            using (var entrynca = nspdata.OpenFile(entryfile))
                            {
                                var hash = SHA256.Create();

                                using (var sr = new BinaryReader(entrynca))
                                {
                                    while (entrynca.Length != entrynca.Position)
                                    {
                                        var entryncadata = sr.ReadBytes(0x100000);
                                        hash.TransformBlock(entryncadata, 0, entryncadata.Length, entryncadata, 0);
                                        Console.Write($"\rChecking {filename}: {((entrynca.Position * 100.0) / entrynca.Length):0.0}%");
                                    }

                                    hash.TransformFinalBlock(new byte[0], 0, 0);
                                }

                                if (hash.Hash.ToHexString().Equals(entry.Hash.ToHexString()))
                                {
                                    Console.Write($"\rChecking {filename}: {100:0.0}%");
                                    continue;
                                }

                                //Put failure here
                                Console.WriteLine($"\rChecking {filename}: one of the entries required by the cnmt.nca is corrupted");
                                badlist.Add(filename);
                                ok = false;
                                break;
                            }
                        }

                        if (ok)
                        {
                            Console.WriteLine($"\rChecking {filename}: OK        ");
                        }
                        //Put Success here
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                    exceptionlist.Add($"{filename}{Environment.NewLine}Exception: {ex.Message}{Environment.NewLine}Stack Trace: {ex.StackTrace}{Environment.NewLine}");
                }
            }

            File.WriteAllText("Corrupted NSPs.txt", string.Join(Environment.NewLine, badlist));
            File.WriteAllText("Exception Log.txt", string.Join(Environment.NewLine, exceptionlist));

            Console.WriteLine();
            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
        }
Exemplo n.º 14
0
        private void BuildChildItems(SectionItem parentItem)
        {
            try
            {
                const string?ROOT_PATH = "/";

                var fileSystem = parentItem.FileSystem;
                if (fileSystem == null)
                {
                    return;
                }

                var directoryEntries = SafeGetDirectoryEntries(fileSystem, ROOT_PATH, parentItem);

                foreach (var directoryEntry in directoryEntries)
                {
                    var entryName = directoryEntry.Name;
                    var entryPath = directoryEntry.FullPath;

                    // NACP File
                    if (parentItem.ParentItem.ContentType == NcaContentType.Control && string.Equals(entryName, NacpItem.NacpFileName, StringComparison.OrdinalIgnoreCase) && directoryEntry.Type == DirectoryEntryType.File)
                    {
                        IFile nacpFile;
                        try
                        {
                            using var uniqueRefFile = new UniqueRef <IFile>();
                            fileSystem.OpenFile(ref uniqueRefFile.Ref(), entryPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            nacpFile = uniqueRefFile.Release();
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToOpenNacpFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        ApplicationControlProperty nacp;
                        try
                        {
                            var blitStruct = new BlitStruct <ApplicationControlProperty>(1);
                            nacpFile.Read(out _, 0, blitStruct.ByteSpan).ThrowIfFailure();

                            nacp = blitStruct.Value;
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadNacpFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        parentItem.ChildItems.Add(new NacpItem(nacp, parentItem, directoryEntry));
                    }
                    // CNMT File
                    else if (parentItem.ParentItem.ContentType == NcaContentType.Meta && entryName.EndsWith(".cnmt", StringComparison.OrdinalIgnoreCase) && directoryEntry.Type == DirectoryEntryType.File)
                    {
                        IFile cnmtFile;
                        try
                        {
                            using var uniqueRefFile = new UniqueRef <IFile>();
                            fileSystem.OpenFile(ref uniqueRefFile.Ref(), entryPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            cnmtFile = uniqueRefFile.Release();
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToOpenCnmtFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        Cnmt cnmt;
                        try
                        {
                            cnmt = new Cnmt(cnmtFile.AsStream());
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadCnmtFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }
                        parentItem.ChildItems.Add(new CnmtItem(cnmt, parentItem, directoryEntry));
                    }
                    // MAIN file
                    else if (parentItem.ParentItem.ContentType == NcaContentType.Program && string.Equals(entryName, "main", StringComparison.OrdinalIgnoreCase) && directoryEntry.Type == DirectoryEntryType.File)
                    {
                        IFile nsoFile;
                        try
                        {
                            using var uniqueRefFile = new UniqueRef <IFile>();
                            fileSystem.OpenFile(ref uniqueRefFile.Ref(), entryPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            nsoFile = uniqueRefFile.Release();
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToOpenMainFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        NsoHeader?nsoHeader;
                        try
                        {
                            var nsoReader = new NsoReader();
                            nsoReader.Initialize(nsoFile).ThrowIfFailure();
                            nsoHeader = nsoReader.Header;
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadMainFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        parentItem.ChildItems.Add(new MainItem(nsoHeader.Value, parentItem, directoryEntry));
                    }
                    else
                    {
                        var directoryEntryItem = new DirectoryEntryItem(parentItem, directoryEntry);
                        BuildChildItems(directoryEntryItem);
                        parentItem.ChildItems.Add(directoryEntryItem);
                    }
                }
            }
            catch (Exception ex)
            {
                OnLoadingException(ex, parentItem);

                var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadSectionContent.SafeFormat(ex.Message);
                parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                _logger.LogError(ex, message);
            }
        }