private async Task AddDlc(string path)
        {
            if (!File.Exists(path) || Dlcs.FirstOrDefault(x => x.ContainerPath == path) != null)
            {
                return;
            }

            using (FileStream containerFile = File.OpenRead(path))
            {
                PartitionFileSystem pfs = new PartitionFileSystem(containerFile.AsStorage());
                bool containsDlc        = false;

                VirtualFileSystem.ImportTickets(pfs);

                foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
                {
                    using var ncaFile = new UniqueRef <IFile>();

                    pfs.OpenFile(ref ncaFile.Ref(), fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                    Nca nca = TryCreateNca(ncaFile.Get.AsStorage(), path);

                    if (nca == null)
                    {
                        continue;
                    }

                    if (nca.Header.ContentType == NcaContentType.PublicData)
                    {
                        if ((nca.Header.TitleId & 0xFFFFFFFFFFFFE000) != TitleId)
                        {
                            break;
                        }

                        Dlcs.Add(new DlcModel(nca.Header.TitleId.ToString("X16"), path, fileEntry.FullPath, true));

                        containsDlc = true;
                    }
                }

                if (!containsDlc)
                {
                    await ContentDialogHelper.CreateErrorDialog(this, LocaleManager.Instance["DialogDlcNoDlcErrorMessage"]);
                }
            }
        }
示例#2
0
        public void AddAocItem(ulong titleId, string containerPath, string ncaPath, bool enabled)
        {
            if (!_aocData.TryAdd(titleId, new AocItem(containerPath, ncaPath, enabled)))
            {
                Logger.Warning?.Print(LogClass.Application, $"Duplicate AddOnContent detected. TitleId {titleId:X16}");
            }
            else
            {
                Logger.Info?.Print(LogClass.Application, $"Found AddOnContent with TitleId {titleId:X16}");

                using (FileStream fileStream = File.OpenRead(containerPath))
                    using (PartitionFileSystem pfs = new PartitionFileSystem(fileStream.AsStorage()))
                    {
                        _virtualFileSystem.ImportTickets(pfs);
                    }
            }
        }
示例#3
0
        public static void ProcessPk11(Context ctx)
        {
            using (var file = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read))
            {
                var    package1 = new Package1(ctx.Keyset, file.AsStorage());
                string outDir   = ctx.Options.OutDir;

                if (outDir != null)
                {
                    Directory.CreateDirectory(outDir);

                    package1.Pk11.OpenWarmboot().WriteAllBytes(Path.Combine(outDir, "Warmboot.bin"), ctx.Logger);
                    package1.Pk11.OpenNxBootloader().WriteAllBytes(Path.Combine(outDir, "NX_Bootloader.bin"), ctx.Logger);
                    package1.Pk11.OpenSecureMonitor().WriteAllBytes(Path.Combine(outDir, "Secure_Monitor.bin"), ctx.Logger);
                    package1.OpenDecryptedPackage().WriteAllBytes(Path.Combine(outDir, "Decrypted.bin"), ctx.Logger);
                }
            }
        }
        public static ResultCode OpenFileSystemFromInternalFile(ServiceCtx context, string fullPath, out IFileSystem openedFileSystem)
        {
            openedFileSystem = null;

            DirectoryInfo archivePath = new DirectoryInfo(fullPath).Parent;

            while (string.IsNullOrWhiteSpace(archivePath.Extension))
            {
                archivePath = archivePath.Parent;
            }

            if (archivePath.Extension == ".nsp" && File.Exists(archivePath.FullName))
            {
                FileStream pfsFile = new FileStream(
                    archivePath.FullName.TrimEnd(Path.DirectorySeparatorChar),
                    FileMode.Open,
                    FileAccess.Read);

                try
                {
                    PartitionFileSystem nsp = new PartitionFileSystem(pfsFile.AsStorage());

                    ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);

                    string filename = fullPath.Replace(archivePath.FullName, string.Empty).TrimStart('\\');

                    using var ncaFile = new UniqueRef <LibHac.Fs.Fsa.IFile>();

                    Result result = nsp.OpenFile(ref ncaFile.Ref(), filename.ToU8Span(), OpenMode.Read);
                    if (result.IsFailure())
                    {
                        return((ResultCode)result.Value);
                    }

                    return(OpenNcaFs(context, fullPath, ncaFile.Release().AsStorage(), out openedFileSystem));
                }
                catch (HorizonResultException ex)
                {
                    return((ResultCode)ex.ResultValue.Value);
                }
            }

            return(ResultCode.PathDoesNotExist);
        }
示例#5
0
        public void LoadXci(string xciFile)
        {
            FileStream file = new FileStream(xciFile, FileMode.Open, FileAccess.Read);

            Xci xci = new Xci(_fileSystem.KeySet, file.AsStorage());

            if (!xci.HasPartition(XciPartitionType.Secure))
            {
                Logger.PrintError(LogClass.Loader, "Unable to load XCI: Could not find XCI secure partition");

                return;
            }

            PartitionFileSystem securePartition = xci.OpenPartition(XciPartitionType.Secure);

            Nca mainNca    = null;
            Nca patchNca   = null;
            Nca controlNca = null;

            try
            {
                (mainNca, patchNca, controlNca) = GetGameData(securePartition);
            }
            catch (Exception e)
            {
                Logger.PrintError(LogClass.Loader, $"Unable to load XCI: {e.Message}");

                return;
            }

            if (mainNca == null)
            {
                Logger.PrintError(LogClass.Loader, "Unable to load XCI: Could not find Main NCA");

                return;
            }

            _contentManager.LoadEntries(_device);

            _contentManager.ClearAocData();
            _contentManager.AddAocData(securePartition, xciFile, mainNca.Header.TitleId);

            LoadNca(mainNca, patchNca, controlNca);
        }
示例#6
0
        public static void ProcessIni1(Context ctx)
        {
            using (var file = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read))
            {
                var ini1 = new Ini1(file.AsStorage());

                string outDir = ctx.Options.OutDir;

                if (outDir != null)
                {
                    Directory.CreateDirectory(outDir);

                    foreach (Kip kip in ini1.Kips)
                    {
                        kip.OpenRawFile().WriteAllBytes(Path.Combine(outDir, $"{kip.Header.Name}.kip1"));
                    }
                }
            }
        }
示例#7
0
        public void LoadXci(string xciFile)
        {
            FileStream file = new FileStream(xciFile, FileMode.Open, FileAccess.Read);

            Xci xci = new Xci(KeySet, file.AsStorage());

            (Nca mainNca, Nca patchNca, Nca controlNca) = GetXciGameData(xci);

            if (mainNca == null)
            {
                Logger.PrintError(LogClass.Loader, "Unable to load XCI");

                return;
            }

            ContentManager.LoadEntries(Device);

            LoadNca(mainNca, patchNca, controlNca);
        }
示例#8
0
        private void AddUpdate(string path, bool showErrorDialog = true)
        {
            if (File.Exists(path))
            {
                using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());

                    _virtualFileSystem.ImportTickets(nsp);

                    foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
                    {
                        nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                        try
                        {
                            Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());

                            if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" == _titleId)
示例#9
0
        public void LoadNca(Nca mainNca, Nca patchNca, Nca controlNca)
        {
            if (mainNca.Header.ContentType != NcaContentType.Program)
            {
                Logger.PrintError(LogClass.Loader, "Selected NCA is not a \"Program\" NCA");

                return;
            }

            IStorage    dataStorage = null;
            IFileSystem codeFs      = null;

            if (File.Exists(Path.Combine(Device.FileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "updates.json")))
            {
                using (Stream stream = File.OpenRead(Path.Combine(Device.FileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "updates.json")))
                {
                    IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase);
                    string updatePath = JsonSerializer.Deserialize <TitleUpdateMetadata>(stream, resolver).Selected;

                    if (File.Exists(updatePath))
                    {
                        FileStream          file = new FileStream(updatePath, FileMode.Open, FileAccess.Read);
                        PartitionFileSystem nsp  = new PartitionFileSystem(file.AsStorage());

                        foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik"))
                        {
                            Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);

                            if (result.IsSuccess())
                            {
                                Ticket ticket = new Ticket(ticketFile.AsStream());

                                KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(KeySet)));
                            }
                        }

                        foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
                        {
                            nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                            Nca nca = new Nca(KeySet, ncaFile.AsStorage());

                            if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != mainNca.Header.TitleId.ToString("x16"))
示例#10
0
        private void AddUpdate(string path)
        {
            if (File.Exists(path))
            {
                using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());

                    try
                    {
                        (Nca patchNca, Nca controlNca) = ApplicationLoader.GetGameUpdateDataFromPartition(_virtualFileSystem, nsp, _titleId, 0);

                        if (controlNca != null && patchNca != null)
                        {
                            ApplicationControlProperty controlData = new ApplicationControlProperty();

                            using var nacpFile = new UniqueRef <IFile>();

                            controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref(), "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();

                            RadioButton radioButton = new RadioButton($"Version {controlData.DisplayVersion.ToString()} - {path}");
                            radioButton.JoinGroup(_noUpdateRadioButton);

                            _availableUpdatesBox.Add(radioButton);
                            _radioButtonToPathDictionary.Add(radioButton, path);

                            radioButton.Show();
                            radioButton.Active = true;
                        }
                        else
                        {
                            GtkDialog.CreateErrorDialog("The specified file does not contain an update for the selected title!");
                        }
                    }
                    catch (Exception exception)
                    {
                        GtkDialog.CreateErrorDialog($"{exception.Message}. Errored File: {path}");
                    }
                }
            }
        }
示例#11
0
文件: Horizon.cs 项目: lrp360/Ryujinx
        public void LoadNsp(string nspFile)
        {
            FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read);

            Pfs nsp = new Pfs(file.AsStorage(false));

            foreach (PfsFileEntry ticketEntry in nsp.Files.Where(x => x.Name.EndsWith(".tik")))
            {
                Ticket ticket = new Ticket(nsp.OpenFile(ticketEntry).AsStream());

                if (!KeySet.TitleKeys.ContainsKey(ticket.RightsId))
                {
                    KeySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(KeySet));
                }
            }

            Nca mainNca    = null;
            Nca controlNca = null;

            foreach (PfsFileEntry ncaFile in nsp.Files.Where(x => x.Name.EndsWith(".nca")))
            {
                Nca nca = new Nca(KeySet, nsp.OpenFile(ncaFile), true);

                if (nca.Header.ContentType == ContentType.Program)
                {
                    mainNca = nca;
                }
                else if (nca.Header.ContentType == ContentType.Control)
                {
                    controlNca = nca;
                }
            }

            if (mainNca != null)
            {
                LoadNca(mainNca, controlNca);

                return;
            }

            Logger.PrintError(LogClass.Loader, "Could not find an Application NCA in the provided NSP file");
        }
示例#12
0
        private static bool IsUpdateApplied(string titleId, out string version)
        {
            string jsonPath = Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "updates.json");

            if (File.Exists(jsonPath))
            {
                using (Stream stream = File.OpenRead(jsonPath))
                {
                    IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase);
                    string updatePath = JsonSerializer.Deserialize <TitleUpdateMetadata>(stream, resolver).Selected;

                    if (!File.Exists(updatePath))
                    {
                        version = "";

                        return(false);
                    }

                    using (FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read))
                    {
                        PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());

                        foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik"))
                        {
                            Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);

                            if (result.IsSuccess())
                            {
                                Ticket ticket = new Ticket(ticketFile.AsStream());

                                _virtualFileSystem.KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(_virtualFileSystem.KeySet)));
                            }
                        }

                        foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
                        {
                            nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                            Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());

                            if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != titleId)
示例#13
0
        public void LoadNsp(string nspFile)
        {
            FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read);

            PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());

            Nca mainNca    = null;
            Nca patchNca   = null;
            Nca controlNca = null;

            try
            {
                (mainNca, patchNca, controlNca) = GetGameData(nsp);
            }
            catch (Exception e)
            {
                Logger.PrintError(LogClass.Loader, $"Unable to load NSP: {e.Message}");

                return;
            }

            if (mainNca == null)
            {
                Logger.PrintError(LogClass.Loader, "Unable to load NSP: Could not find Main NCA");

                return;
            }

            if (mainNca != null)
            {
                _contentManager.ClearAocData();
                _contentManager.AddAocData(nsp, nspFile, mainNca.Header.TitleId);

                LoadNca(mainNca, patchNca, controlNca);

                return;
            }

            // This is not a normal NSP, it's actually a ExeFS as a NSP
            LoadExeFs(nsp);
        }
示例#14
0
        private long OpenFileSystemFromInternalFile(ServiceCtx context, string fullPath)
        {
            DirectoryInfo archivePath = new DirectoryInfo(fullPath).Parent;

            while (string.IsNullOrWhiteSpace(archivePath.Extension))
            {
                archivePath = archivePath.Parent;
            }

            if (archivePath.Extension == ".nsp" && File.Exists(archivePath.FullName))
            {
                FileStream pfsFile = new FileStream(
                    archivePath.FullName.TrimEnd(Path.DirectorySeparatorChar),
                    FileMode.Open,
                    FileAccess.Read);

                try
                {
                    PartitionFileSystem nsp = new PartitionFileSystem(pfsFile.AsStorage());

                    ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);

                    string filename = fullPath.Replace(archivePath.FullName, string.Empty).TrimStart('\\');

                    if (nsp.FileExists(filename))
                    {
                        return(OpenNcaFs(context, fullPath, nsp.OpenFile(filename, OpenMode.Read).AsStorage()));
                    }
                }
                catch (HorizonResultException ex)
                {
                    return(ex.ResultValue.Value);
                }
            }

            return(MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist));
        }
示例#15
0
        // OpenFileSystemWithId(nn::fssrv::sf::FileSystemType filesystem_type, nn::ApplicationId tid, buffer<bytes<0x301>, 0x19, 0x301> path)
        // -> object<nn::fssrv::sf::IFileSystem> contentFs
        public ResultCode OpenFileSystemWithId(ServiceCtx context)
        {
            FileSystemType fileSystemType = (FileSystemType)context.RequestData.ReadInt32();
            long           titleId        = context.RequestData.ReadInt64();
            string         switchPath     = ReadUtf8String(context);
            string         fullPath       = context.Device.FileSystem.SwitchPathToSystemPath(switchPath);

            if (!File.Exists(fullPath))
            {
                if (fullPath.Contains("."))
                {
                    ResultCode result = FileSystemProxyHelper.OpenFileSystemFromInternalFile(context, fullPath, out FileSystemProxy.IFileSystem fileSystem);

                    if (result == ResultCode.Success)
                    {
                        MakeObject(context, fileSystem);
                    }

                    return(result);
                }

                return(ResultCode.PathDoesNotExist);
            }

            FileStream fileStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read);
            string     extension  = Path.GetExtension(fullPath);

            if (extension == ".nca")
            {
                ResultCode result = FileSystemProxyHelper.OpenNcaFs(context, fullPath, fileStream.AsStorage(), out FileSystemProxy.IFileSystem fileSystem);

                if (result == ResultCode.Success)
                {
                    MakeObject(context, fileSystem);
                }

                return(result);
            }
            else if (extension == ".nsp")
            {
                ResultCode result = FileSystemProxyHelper.OpenNsp(context, fullPath, out FileSystemProxy.IFileSystem fileSystem);

                if (result == ResultCode.Success)
                {
                    MakeObject(context, fileSystem);
                }

                return(result);
            }

            return(ResultCode.InvalidInput);
        }
示例#16
0
        public static Title processXci(string filename)
        {
            Title title = new Title();

            using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                Xci    xci;
                string biggestNca = null, controlNca = null;

                try
                {
                    xci = new Xci(keyset, filestream.AsStorage());

                    title.distribution = Title.Distribution.Cartridge;
                }
                catch (InvalidDataException)
                {
                    return(null);
                }

                log?.WriteLine("Processing XCI {0}", filename);

                if (xci.RootPartition?.Files.Length > 0)
                {
                    title.structure.Add(Title.Structure.RootPartition);
                }

                if (xci.UpdatePartition?.Files.Length > 0)
                {
                    title.structure.Add(Title.Structure.UpdatePartition);
                }

                if (xci.NormalPartition?.Files.Length > 0)
                {
                    title.structure.Add(Title.Structure.NormalPartition);
                }

                if (xci.SecurePartition?.Files.Length > 0)
                {
                    PfsFileEntry[] fileEntries = xci.SecurePartition.Files;
                    foreach (PfsFileEntry entry in fileEntries)
                    {
                        if (entry.Name.EndsWith(".cnmt.nca"))
                        {
                            using (var cnmtNca = xci.SecurePartition.OpenFile(entry))
                            {
                                var nca = processCnmtNca(cnmtNca, ref title);
                                if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent))
                                {
                                    (biggestNca, controlNca) = nca;
                                }
                            }

                            title.structure.Add(Title.Structure.CnmtNca);
                        }
                    }

                    if (!String.IsNullOrEmpty(biggestNca))
                    {
                        using (var biggest = xci.SecurePartition.OpenFile(biggestNca))
                        {
                            processBiggestNca(biggest, ref title);
                        }
                    }

                    if (!String.IsNullOrEmpty(controlNca))
                    {
                        using (var control = xci.SecurePartition.OpenFile(controlNca))
                        {
                            processControlNca(control, ref title);
                        }
                    }

                    title.structure.Add(Title.Structure.SecurePartition);
                }

                if (xci.LogoPartition?.Files.Length > 0)
                {
                    title.structure.Add(Title.Structure.LogoPartition);
                }
            }

            if (title.type == TitleType.Application || title.type == TitleType.Patch)
            {
                if (versionList.TryGetValue(title.titleIDApplication, out uint version))
                {
                    title.latestVersion = version;
                }
            }

            log?.WriteLine("XCI information for {0}: [{1}] {2}", filename, title.titleID, title.titleName);

            return(title);
        }
示例#17
0
        public static Title processNsp(string filename)
        {
            Title title = new Title();

            using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                Pfs    pfs;
                string biggestNca = null, controlNca = null;

                try
                {
                    pfs = new Pfs(filestream.AsStorage());

                    title.distribution = Title.Distribution.Digital;
                }
                catch (InvalidDataException)
                {
                    return(null);
                }

                log?.WriteLine("Processing NSP {0}", filename);

                PfsFileEntry[] fileEntries = pfs.Files;
                foreach (PfsFileEntry entry in fileEntries)
                {
                    if (entry.Name.EndsWith(".cnmt.xml"))
                    {
                        using (var cnmtXml = pfs.OpenFile(entry))
                        {
                            (biggestNca, controlNca) = processCnmtXml(cnmtXml, ref title);
                        }

                        title.structure.Add(Title.Structure.CnmtXml);
                    }
                    else if (entry.Name.EndsWith(".cnmt.nca"))
                    {
                        using (var cnmtNca = pfs.OpenFile(entry))
                        {
                            var nca = processCnmtNca(cnmtNca, ref title);
                            if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent))
                            {
                                (biggestNca, controlNca) = nca;
                            }
                        }

                        title.structure.Add(Title.Structure.CnmtNca);
                    }
                    else if (entry.Name.EndsWith(".cert"))
                    {
                        title.structure.Add(Title.Structure.Cert);
                    }
                    else if (entry.Name.EndsWith(".tik"))
                    {
                        title.structure.Add(Title.Structure.Tik);
                    }
                    else if (entry.Name.EndsWith(".legalinfo.xml"))
                    {
                        title.structure.Add(Title.Structure.LegalinfoXml);
                    }
                    else if (entry.Name.EndsWith(".nacp.xml"))
                    {
                        using (var nacpXml = pfs.OpenFile(entry))
                        {
                            processNacpXml(nacpXml, ref title);
                        }

                        title.structure.Add(Title.Structure.NacpXml);
                    }
                    else if (entry.Name.EndsWith(".programinfo.xml"))
                    {
                        title.structure.Add(Title.Structure.PrograminfoXml);
                    }
                    else if (entry.Name.Equals("cardspec.xml"))
                    {
                        title.structure.Add(Title.Structure.CardspecXml);
                    }
                    else if (entry.Name.Equals("authoringtoolinfo.xml"))
                    {
                        title.structure.Add(Title.Structure.AuthoringtoolinfoXml);
                    }
                }

                if (!String.IsNullOrEmpty(biggestNca))
                {
                    using (var biggest = pfs.OpenFile(biggestNca))
                    {
                        processBiggestNca(biggest, ref title);
                    }
                }

                if (!String.IsNullOrEmpty(controlNca))
                {
                    using (var control = pfs.OpenFile(controlNca))
                    {
                        processControlNca(control, ref title);
                    }
                }
            }

            if (title.type == TitleType.Application || title.type == TitleType.Patch)
            {
                if (versionList.TryGetValue(title.titleIDApplication, out uint version))
                {
                    title.latestVersion = version;
                }
            }

            log?.WriteLine("NSP information for {0}: [{1}] {2}", filename, title.titleID, title.titleName);

            return(title);
        }
示例#18
0
文件: Horizon.cs 项目: solulu/Ryujinx
        public void LoadNsp(string nspFile)
        {
            FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read);

            Pfs nsp = new Pfs(file.AsStorage(false));

            foreach (PfsFileEntry ticketEntry in nsp.Files.Where(x => x.Name.EndsWith(".tik")))
            {
                Ticket ticket = new Ticket(nsp.OpenFile(ticketEntry).AsStream());

                if (!KeySet.TitleKeys.ContainsKey(ticket.RightsId))
                {
                    KeySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(KeySet));
                }
            }

            Nca mainNca    = null;
            Nca controlNca = null;

            foreach (PfsFileEntry ncaFile in nsp.Files.Where(x => x.Name.EndsWith(".nca")))
            {
                Nca nca = new Nca(KeySet, nsp.OpenFile(ncaFile), true);

                if (nca.Header.ContentType == ContentType.Program)
                {
                    mainNca = nca;
                }
                else if (nca.Header.ContentType == ContentType.Control)
                {
                    controlNca = nca;
                }
            }

            if (mainNca != null)
            {
                LoadNca(mainNca, controlNca);

                return;
            }

            // This is not a normal NSP, it's actually a ExeFS as a NSP
            Npdm metaData = null;

            PfsFileEntry npdmFile = nsp.Files.FirstOrDefault(x => x.Name.Equals("main.npdm"));

            if (npdmFile != null)
            {
                Logger.PrintInfo(LogClass.Loader, $"Loading main.npdm...");

                metaData = new Npdm(nsp.OpenFile(npdmFile).AsStream());
            }
            else
            {
                Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!");

                metaData = GetDefaultNpdm();
            }

            List <IExecutable> staticObjects = new List <IExecutable>();

            void LoadNso(string searchPattern)
            {
                PfsFileEntry entry = nsp.Files.FirstOrDefault(x => x.Name.Equals(searchPattern));

                if (entry != null)
                {
                    Logger.PrintInfo(LogClass.Loader, $"Loading {entry.Name}...");

                    NxStaticObject staticObject = new NxStaticObject(nsp.OpenFile(entry).AsStream());

                    staticObjects.Add(staticObject);
                }
            }

            CurrentTitle = metaData.Aci0.TitleId.ToString("x16");

            LoadNso("rtld");
            LoadNso("main");
            LoadNso("subsdk*");
            LoadNso("sdk");

            ContentManager.LoadEntries();

            if (staticObjects.Count == 0)
            {
                Logger.PrintError(LogClass.Loader, "Could not find an Application NCA in the provided NSP file");
            }
            else
            {
                ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray());
            }
        }
示例#19
0
        public static void LoadApplications(List <string> appDirs, Keyset keySet, TitleLanguage desiredTitleLanguage, FileSystemClient fsClient = null, VirtualFileSystem vfs = null)
        {
            int numApplicationsFound  = 0;
            int numApplicationsLoaded = 0;

            _keySet = keySet;
            _desiredTitleLanguage = desiredTitleLanguage;

            // Builds the applications list with paths to found applications
            List <string> applications = new List <string>();

            foreach (string appDir in appDirs)
            {
                if (Directory.Exists(appDir) == false)
                {
                    Logger.PrintWarning(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\"");

                    continue;
                }

                foreach (string app in Directory.GetFiles(appDir, "*.*", SearchOption.AllDirectories))
                {
                    if ((Path.GetExtension(app) == ".xci") ||
                        (Path.GetExtension(app) == ".nro") ||
                        (Path.GetExtension(app) == ".nso") ||
                        (Path.GetFileName(app) == "hbl.nsp"))
                    {
                        applications.Add(app);
                        numApplicationsFound++;
                    }
                    else if ((Path.GetExtension(app) == ".nsp") || (Path.GetExtension(app) == ".pfs0"))
                    {
                        try
                        {
                            bool hasMainNca = false;

                            PartitionFileSystem nsp = new PartitionFileSystem(new FileStream(app, FileMode.Open, FileAccess.Read).AsStorage());
                            foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
                            {
                                nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure();

                                Nca nca       = new Nca(_keySet, ncaFile.AsStorage());
                                int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);

                                if (nca.Header.ContentType == NcaContentType.Program && !nca.Header.GetFsHeader(dataIndex).IsPatchSection())
                                {
                                    hasMainNca = true;
                                }
                            }

                            if (!hasMainNca)
                            {
                                continue;
                            }
                        }
                        catch (InvalidDataException)
                        {
                            Logger.PrintWarning(LogClass.Application, $"{app}: The header key is incorrect or missing and therefore the NCA header content type check has failed.");
                        }

                        applications.Add(app);
                        numApplicationsFound++;
                    }
                    else if (Path.GetExtension(app) == ".nca")
                    {
                        try
                        {
                            Nca nca       = new Nca(_keySet, new FileStream(app, FileMode.Open, FileAccess.Read).AsStorage());
                            int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);

                            if (nca.Header.ContentType != NcaContentType.Program || nca.Header.GetFsHeader(dataIndex).IsPatchSection())
                            {
                                continue;
                            }
                        }
                        catch (InvalidDataException)
                        {
                            Logger.PrintWarning(LogClass.Application, $"{app}: The header key is incorrect or missing and therefore the NCA header content type check has failed.");
                        }

                        applications.Add(app);
                        numApplicationsFound++;
                    }
                }
            }

            // Loops through applications list, creating a struct and then firing an event containing the struct for each application
            foreach (string applicationPath in applications)
            {
                double fileSize        = new FileInfo(applicationPath).Length * 0.000000000931;
                string titleName       = "Unknown";
                string titleId         = "0000000000000000";
                string developer       = "Unknown";
                string version         = "0";
                string saveDataPath    = null;
                byte[] applicationIcon = null;

                using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read))
                {
                    if ((Path.GetExtension(applicationPath) == ".nsp") ||
                        (Path.GetExtension(applicationPath) == ".pfs0") ||
                        (Path.GetExtension(applicationPath) == ".xci"))
                    {
                        try
                        {
                            PartitionFileSystem pfs;

                            if (Path.GetExtension(applicationPath) == ".xci")
                            {
                                Xci xci = new Xci(_keySet, file.AsStorage());

                                pfs = xci.OpenPartition(XciPartitionType.Secure);
                            }
                            else
                            {
                                pfs = new PartitionFileSystem(file.AsStorage());
                            }

                            // Store the ControlFS in variable called controlFs
                            IFileSystem controlFs = GetControlFs(pfs);

                            // If this is null then this is probably not a normal NSP, it's probably an ExeFS as an NSP
                            if (controlFs == null)
                            {
                                applicationIcon = _nspIcon;

                                Result result = pfs.OpenFile(out IFile npdmFile, "/main.npdm", OpenMode.Read);

                                if (result != ResultFs.PathNotFound)
                                {
                                    Npdm npdm = new Npdm(npdmFile.AsStream());

                                    titleName = npdm.TitleName;
                                    titleId   = npdm.Aci0.TitleId.ToString("x16");
                                }
                            }
                            else
                            {
                                // Creates NACP class from the NACP file
                                controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp", OpenMode.Read).ThrowIfFailure();

                                Nacp controlData = new Nacp(controlNacpFile.AsStream());

                                // Get the title name, title ID, developer name and version number from the NACP
                                version = controlData.DisplayVersion;

                                titleName = controlData.Descriptions[(int)_desiredTitleLanguage].Title;

                                if (string.IsNullOrWhiteSpace(titleName))
                                {
                                    titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title;
                                }

                                titleId = controlData.PresenceGroupId.ToString("x16");

                                if (string.IsNullOrWhiteSpace(titleId))
                                {
                                    titleId = controlData.SaveDataOwnerId.ToString("x16");
                                }

                                if (string.IsNullOrWhiteSpace(titleId))
                                {
                                    titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
                                }

                                developer = controlData.Descriptions[(int)_desiredTitleLanguage].Developer;

                                if (string.IsNullOrWhiteSpace(developer))
                                {
                                    developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer;
                                }

                                // Read the icon from the ControlFS and store it as a byte array
                                try
                                {
                                    controlFs.OpenFile(out IFile icon, $"/icon_{_desiredTitleLanguage}.dat", OpenMode.Read).ThrowIfFailure();

                                    using (MemoryStream stream = new MemoryStream())
                                    {
                                        icon.AsStream().CopyTo(stream);
                                        applicationIcon = stream.ToArray();
                                    }
                                }
                                catch (HorizonResultException)
                                {
                                    foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
                                    {
                                        if (entry.Name == "control.nacp")
                                        {
                                            continue;
                                        }

                                        controlFs.OpenFile(out IFile icon, entry.FullPath, OpenMode.Read).ThrowIfFailure();

                                        using (MemoryStream stream = new MemoryStream())
                                        {
                                            icon.AsStream().CopyTo(stream);
                                            applicationIcon = stream.ToArray();
                                        }

                                        if (applicationIcon != null)
                                        {
                                            break;
                                        }
                                    }

                                    if (applicationIcon == null)
                                    {
                                        applicationIcon = Path.GetExtension(applicationPath) == ".xci" ? _xciIcon : _nspIcon;
                                    }
                                }
                            }
                        }
                        catch (MissingKeyException exception)
                        {
                            applicationIcon = Path.GetExtension(applicationPath) == ".xci" ? _xciIcon : _nspIcon;

                            Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
                        }
                        catch (InvalidDataException)
                        {
                            applicationIcon = Path.GetExtension(applicationPath) == ".xci" ? _xciIcon : _nspIcon;

                            Logger.PrintWarning(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}");
                        }
                    }
                    else if (Path.GetExtension(applicationPath) == ".nro")
                    {
                        BinaryReader reader = new BinaryReader(file);

                        byte[] Read(long position, int size)
                        {
                            file.Seek(position, SeekOrigin.Begin);

                            return(reader.ReadBytes(size));
                        }

                        file.Seek(24, SeekOrigin.Begin);
                        int assetOffset = reader.ReadInt32();

                        if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
                        {
                            byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);

                            long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
                            long iconSize   = BitConverter.ToInt64(iconSectionInfo, 8);

                            ulong nacpOffset = reader.ReadUInt64();
                            ulong nacpSize   = reader.ReadUInt64();

                            // Reads and stores game icon as byte array
                            applicationIcon = Read(assetOffset + iconOffset, (int)iconSize);

                            // Creates memory stream out of byte array which is the NACP
                            using (MemoryStream stream = new MemoryStream(Read(assetOffset + (int)nacpOffset, (int)nacpSize)))
                            {
                                // Creates NACP class from the memory stream
                                Nacp controlData = new Nacp(stream);

                                // Get the title name, title ID, developer name and version number from the NACP
                                version = controlData.DisplayVersion;

                                titleName = controlData.Descriptions[(int)_desiredTitleLanguage].Title;

                                if (string.IsNullOrWhiteSpace(titleName))
                                {
                                    titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title;
                                }

                                titleId = controlData.PresenceGroupId.ToString("x16");

                                if (string.IsNullOrWhiteSpace(titleId))
                                {
                                    titleId = controlData.SaveDataOwnerId.ToString("x16");
                                }

                                if (string.IsNullOrWhiteSpace(titleId))
                                {
                                    titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
                                }

                                developer = controlData.Descriptions[(int)_desiredTitleLanguage].Developer;

                                if (string.IsNullOrWhiteSpace(developer))
                                {
                                    developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer;
                                }
                            }
                        }
                        else
                        {
                            applicationIcon = _nroIcon;
                        }
                    }
                    // If its an NCA or NSO we just set defaults
                    else if ((Path.GetExtension(applicationPath) == ".nca") || (Path.GetExtension(applicationPath) == ".nso"))
                    {
                        applicationIcon = Path.GetExtension(applicationPath) == ".nca" ? _ncaIcon : _nsoIcon;
                        titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                    }
                }

                ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId);

                if (ulong.TryParse(titleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNum))
                {
                    SaveDataFilter filter = new SaveDataFilter();
                    filter.SetUserId(new UserId(1, 0));
                    filter.SetTitleId(new TitleId(titleIdNum));

                    Result result = fsClient.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter);

                    if (result.IsSuccess())
                    {
                        saveDataPath = Path.Combine(vfs.GetNandPath(), $"user/save/{saveDataInfo.SaveDataId:x16}");
                    }
                }

                ApplicationData data = new ApplicationData()
                {
                    Favorite      = appMetadata.Favorite,
                    Icon          = applicationIcon,
                    TitleName     = titleName,
                    TitleId       = titleId,
                    Developer     = developer,
                    Version       = version,
                    TimePlayed    = ConvertSecondsToReadableString(appMetadata.TimePlayed),
                    LastPlayed    = appMetadata.LastPlayed,
                    FileExtension = Path.GetExtension(applicationPath).ToUpper().Remove(0, 1),
                    FileSize      = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + "MB" : fileSize.ToString("0.##") + "GB",
                    Path          = applicationPath,
                    SaveDataPath  = saveDataPath
                };

                numApplicationsLoaded++;

                OnApplicationAdded(new ApplicationAddedEventArgs()
                {
                    AppData       = data,
                    NumAppsFound  = numApplicationsFound,
                    NumAppsLoaded = numApplicationsLoaded
                });
            }
        }
示例#20
0
        private void AddButton_Clicked(object sender, EventArgs args)
        {
            FileChooserNative fileChooser = new FileChooserNative("Select DLC files", this, FileChooserAction.Open, "Add", "Cancel")
            {
                SelectMultiple = true
            };

            FileFilter filter = new FileFilter()
            {
                Name = "Switch Game DLCs"
            };

            filter.AddPattern("*.nsp");

            fileChooser.AddFilter(filter);

            if (fileChooser.Run() == (int)ResponseType.Accept)
            {
                foreach (string containerPath in fileChooser.Filenames)
                {
                    if (!File.Exists(containerPath))
                    {
                        return;
                    }

                    using (FileStream containerFile = File.OpenRead(containerPath))
                    {
                        PartitionFileSystem pfs = new PartitionFileSystem(containerFile.AsStorage());
                        bool containsDlc        = false;

                        _virtualFileSystem.ImportTickets(pfs);

                        TreeIter?parentIter = null;

                        foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
                        {
                            pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                            Nca nca = TryCreateNca(ncaFile.AsStorage(), containerPath);

                            if (nca == null)
                            {
                                continue;
                            }

                            if (nca.Header.ContentType == NcaContentType.PublicData)
                            {
                                if ((nca.Header.TitleId & 0xFFFFFFFFFFFFE000).ToString("x16") != _titleId)
                                {
                                    break;
                                }

                                parentIter ??= ((TreeStore)_dlcTreeView.Model).AppendValues(true, "", containerPath);

                                ((TreeStore)_dlcTreeView.Model).AppendValues(parentIter.Value, true, nca.Header.TitleId.ToString("X16"), fileEntry.FullPath);
                                containsDlc = true;
                            }
                        }

                        if (!containsDlc)
                        {
                            GtkDialog.CreateErrorDialog("The specified file does not contain DLC for the selected title!");
                        }
                    }
                }
            }

            fileChooser.Dispose();
        }
示例#21
0
        public static void LoadApplications(List <string> appDirs, VirtualFileSystem virtualFileSystem, Language desiredTitleLanguage)
        {
            int numApplicationsFound  = 0;
            int numApplicationsLoaded = 0;

            _loadingError         = false;
            _virtualFileSystem    = virtualFileSystem;
            _desiredTitleLanguage = desiredTitleLanguage;

            // Builds the applications list with paths to found applications
            List <string> applications = new List <string>();

            foreach (string appDir in appDirs)
            {
                if (!Directory.Exists(appDir))
                {
                    Logger.PrintWarning(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\"");

                    continue;
                }

                foreach (string app in GetFilesInDirectory(appDir))
                {
                    if ((Path.GetExtension(app).ToLower() == ".nsp") ||
                        (Path.GetExtension(app).ToLower() == ".pfs0") ||
                        (Path.GetExtension(app).ToLower() == ".xci") ||
                        (Path.GetExtension(app).ToLower() == ".nca") ||
                        (Path.GetExtension(app).ToLower() == ".nro") ||
                        (Path.GetExtension(app).ToLower() == ".nso"))
                    {
                        applications.Add(app);
                        numApplicationsFound++;
                    }
                }
            }

            // Loops through applications list, creating a struct and then firing an event containing the struct for each application
            foreach (string applicationPath in applications)
            {
                double fileSize        = new FileInfo(applicationPath).Length * 0.000000000931;
                string titleName       = "Unknown";
                string titleId         = "0000000000000000";
                string developer       = "Unknown";
                string version         = "0";
                string saveDataPath    = null;
                byte[] applicationIcon = null;
                BlitStruct <ApplicationControlProperty> controlHolder = new BlitStruct <ApplicationControlProperty>(1);

                try
                {
                    using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read))
                    {
                        if ((Path.GetExtension(applicationPath).ToLower() == ".nsp") ||
                            (Path.GetExtension(applicationPath).ToLower() == ".pfs0") ||
                            (Path.GetExtension(applicationPath).ToLower() == ".xci"))
                        {
                            try
                            {
                                PartitionFileSystem pfs;

                                bool isExeFs = false;

                                if (Path.GetExtension(applicationPath).ToLower() == ".xci")
                                {
                                    Xci xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage());

                                    pfs = xci.OpenPartition(XciPartitionType.Secure);
                                }
                                else
                                {
                                    pfs = new PartitionFileSystem(file.AsStorage());

                                    // If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application.
                                    bool hasMainNca = false;

                                    foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
                                    {
                                        if (Path.GetExtension(fileEntry.FullPath).ToLower() == ".nca")
                                        {
                                            pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                            Nca nca       = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
                                            int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);

                                            if (nca.Header.ContentType == NcaContentType.Program && !nca.Header.GetFsHeader(dataIndex).IsPatchSection())
                                            {
                                                hasMainNca = true;

                                                break;
                                            }
                                        }
                                        else if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
                                        {
                                            isExeFs = true;
                                        }
                                    }

                                    if (!hasMainNca && !isExeFs)
                                    {
                                        numApplicationsFound--;

                                        continue;
                                    }
                                }

                                if (isExeFs)
                                {
                                    applicationIcon = _nspIcon;

                                    Result result = pfs.OpenFile(out IFile npdmFile, "/main.npdm".ToU8Span(), OpenMode.Read);

                                    if (ResultFs.PathNotFound.Includes(result))
                                    {
                                        Npdm npdm = new Npdm(npdmFile.AsStream());

                                        titleName = npdm.TitleName;
                                        titleId   = npdm.Aci0.TitleId.ToString("x16");
                                    }
                                }
                                else
                                {
                                    // Store the ControlFS in variable called controlFs
                                    GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId);

                                    ReadControlData(controlFs, controlHolder.ByteSpan);

                                    // Creates NACP class from the NACP file
                                    controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                    // Get the title name, title ID, developer name and version number from the NACP
                                    version = IsUpdateApplied(titleId, out string updateVersion) ? updateVersion : controlHolder.Value.DisplayVersion.ToString();

                                    GetNameIdDeveloper(ref controlHolder.Value, out titleName, out _, out developer);

                                    // Read the icon from the ControlFS and store it as a byte array
                                    try
                                    {
                                        controlFs.OpenFile(out IFile icon, $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                        using (MemoryStream stream = new MemoryStream())
                                        {
                                            icon.AsStream().CopyTo(stream);
                                            applicationIcon = stream.ToArray();
                                        }
                                    }
                                    catch (HorizonResultException)
                                    {
                                        foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
                                        {
                                            if (entry.Name == "control.nacp")
                                            {
                                                continue;
                                            }

                                            controlFs.OpenFile(out IFile icon, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                            using (MemoryStream stream = new MemoryStream())
                                            {
                                                icon.AsStream().CopyTo(stream);
                                                applicationIcon = stream.ToArray();
                                            }

                                            if (applicationIcon != null)
                                            {
                                                break;
                                            }
                                        }

                                        if (applicationIcon == null)
                                        {
                                            applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon;
                                        }
                                    }
                                }
                            }
                            catch (MissingKeyException exception)
                            {
                                applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon;

                                Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
                            }
                            catch (InvalidDataException)
                            {
                                applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon;

                                Logger.PrintWarning(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}");
                            }
                            catch (Exception exception)
                            {
                                Logger.PrintWarning(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
                                Logger.PrintDebug(LogClass.Application, exception.ToString());

                                numApplicationsFound--;
                                _loadingError = true;

                                continue;
                            }
                        }
                        else if (Path.GetExtension(applicationPath).ToLower() == ".nro")
                        {
                            BinaryReader reader = new BinaryReader(file);

                            byte[] Read(long position, int size)
                            {
                                file.Seek(position, SeekOrigin.Begin);

                                return(reader.ReadBytes(size));
                            }

                            try
                            {
                                file.Seek(24, SeekOrigin.Begin);

                                int assetOffset = reader.ReadInt32();

                                if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
                                {
                                    byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);

                                    long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
                                    long iconSize   = BitConverter.ToInt64(iconSectionInfo, 8);

                                    ulong nacpOffset = reader.ReadUInt64();
                                    ulong nacpSize   = reader.ReadUInt64();

                                    // Reads and stores game icon as byte array
                                    applicationIcon = Read(assetOffset + iconOffset, (int)iconSize);

                                    // Read the NACP data
                                    Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan);

                                    // Get the title name, title ID, developer name and version number from the NACP
                                    version = controlHolder.Value.DisplayVersion.ToString();

                                    GetNameIdDeveloper(ref controlHolder.Value, out titleName, out titleId, out developer);
                                }
                                else
                                {
                                    applicationIcon = _nroIcon;
                                    titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                                }
                            }
                            catch
                            {
                                Logger.PrintWarning(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");

                                numApplicationsFound--;

                                continue;
                            }
                        }
                        else if (Path.GetExtension(applicationPath).ToLower() == ".nca")
                        {
                            try
                            {
                                Nca nca       = new Nca(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage());
                                int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);

                                if (nca.Header.ContentType != NcaContentType.Program || nca.Header.GetFsHeader(dataIndex).IsPatchSection())
                                {
                                    numApplicationsFound--;

                                    continue;
                                }
                            }
                            catch (InvalidDataException)
                            {
                                Logger.PrintWarning(LogClass.Application, $"The NCA header content type check has failed. This is usually because the header key is incorrect or missing. Errored File: {applicationPath}");
                            }
                            catch
                            {
                                Logger.PrintWarning(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");

                                numApplicationsFound--;
                                _loadingError = true;

                                continue;
                            }

                            applicationIcon = _ncaIcon;
                            titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                        }
                        // If its an NSO we just set defaults
                        else if (Path.GetExtension(applicationPath).ToLower() == ".nso")
                        {
                            applicationIcon = _nsoIcon;
                            titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                        }
                    }
                }
                catch (IOException exception)
                {
                    Logger.PrintWarning(LogClass.Application, exception.Message);

                    numApplicationsFound--;
                    _loadingError = true;

                    continue;
                }

                ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId);

                if (ulong.TryParse(titleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNum))
                {
                    SaveDataFilter filter = new SaveDataFilter();
                    filter.SetUserId(new UserId(1, 0));
                    filter.SetProgramId(new TitleId(titleIdNum));

                    Result result = virtualFileSystem.FsClient.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter);

                    if (result.IsSuccess())
                    {
                        saveDataPath = Path.Combine(virtualFileSystem.GetNandPath(), "user", "save", saveDataInfo.SaveDataId.ToString("x16"));
                    }
                }

                ApplicationData data = new ApplicationData
                {
                    Favorite      = appMetadata.Favorite,
                    Icon          = applicationIcon,
                    TitleName     = titleName,
                    TitleId       = titleId,
                    Developer     = developer,
                    Version       = version,
                    TimePlayed    = ConvertSecondsToReadableString(appMetadata.TimePlayed),
                    LastPlayed    = appMetadata.LastPlayed,
                    FileExtension = Path.GetExtension(applicationPath).ToUpper().Remove(0, 1),
                    FileSize      = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + "MB" : fileSize.ToString("0.##") + "GB",
                    Path          = applicationPath,
                    SaveDataPath  = saveDataPath,
                    ControlHolder = controlHolder
                };

                numApplicationsLoaded++;

                OnApplicationAdded(new ApplicationAddedEventArgs()
                {
                    AppData = data
                });

                OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
                {
                    NumAppsFound  = numApplicationsFound,
                    NumAppsLoaded = numApplicationsLoaded
                });
            }

            OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
            {
                NumAppsFound  = numApplicationsFound,
                NumAppsLoaded = numApplicationsLoaded
            });

            if (_loadingError)
            {
                Gtk.Application.Invoke(delegate
                {
                    GtkDialog.CreateErrorDialog("One or more files encountered could not be loaded, check logs for more info.");
                });
            }
        }
示例#22
0
        public void LoadApplications(List <string> appDirs, Language desiredTitleLanguage)
        {
            int numApplicationsFound  = 0;
            int numApplicationsLoaded = 0;

            _desiredTitleLanguage = desiredTitleLanguage;

            _cancellationToken = new CancellationTokenSource();

            // Builds the applications list with paths to found applications
            List <string> applications = new List <string>();

            try
            {
                foreach (string appDir in appDirs)
                {
                    if (_cancellationToken.Token.IsCancellationRequested)
                    {
                        return;
                    }

                    if (!Directory.Exists(appDir))
                    {
                        Logger.Warning?.Print(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\"");

                        continue;
                    }

                    foreach (string app in GetFilesInDirectory(appDir))
                    {
                        if (_cancellationToken.Token.IsCancellationRequested)
                        {
                            return;
                        }

                        string extension = Path.GetExtension(app).ToLower();

                        if ((extension == ".nsp") ||
                            (extension == ".pfs0") ||
                            (extension == ".xci") ||
                            (extension == ".nca") ||
                            (extension == ".nro") ||
                            (extension == ".nso"))
                        {
                            applications.Add(app);
                            numApplicationsFound++;
                        }
                    }
                }

                // Loops through applications list, creating a struct and then firing an event containing the struct for each application
                foreach (string applicationPath in applications)
                {
                    if (_cancellationToken.Token.IsCancellationRequested)
                    {
                        return;
                    }

                    double fileSize        = new FileInfo(applicationPath).Length * 0.000000000931;
                    string titleName       = "Unknown";
                    string titleId         = "0000000000000000";
                    string developer       = "Unknown";
                    string version         = "0";
                    byte[] applicationIcon = null;

                    BlitStruct <ApplicationControlProperty> controlHolder = new BlitStruct <ApplicationControlProperty>(1);

                    try
                    {
                        string extension = Path.GetExtension(applicationPath).ToLower();

                        using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read))
                        {
                            if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
                            {
                                try
                                {
                                    PartitionFileSystem pfs;

                                    bool isExeFs = false;

                                    if (extension == ".xci")
                                    {
                                        Xci xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage());

                                        pfs = xci.OpenPartition(XciPartitionType.Secure);
                                    }
                                    else
                                    {
                                        pfs = new PartitionFileSystem(file.AsStorage());

                                        // If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application.
                                        bool hasMainNca = false;

                                        foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
                                        {
                                            if (Path.GetExtension(fileEntry.FullPath).ToLower() == ".nca")
                                            {
                                                using var ncaFile = new UniqueRef <IFile>();

                                                pfs.OpenFile(ref ncaFile.Ref(), fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                                Nca nca       = new Nca(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
                                                int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);

                                                // Some main NCAs don't have a data partition, so check if the partition exists before opening it
                                                if (nca.Header.ContentType == NcaContentType.Program && !(nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()))
                                                {
                                                    hasMainNca = true;

                                                    break;
                                                }
                                            }
                                            else if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
                                            {
                                                isExeFs = true;
                                            }
                                        }

                                        if (!hasMainNca && !isExeFs)
                                        {
                                            numApplicationsFound--;

                                            continue;
                                        }
                                    }

                                    if (isExeFs)
                                    {
                                        applicationIcon = _nspIcon;

                                        using var npdmFile = new UniqueRef <IFile>();

                                        Result result = pfs.OpenFile(ref npdmFile.Ref(), "/main.npdm".ToU8Span(), OpenMode.Read);

                                        if (ResultFs.PathNotFound.Includes(result))
                                        {
                                            Npdm npdm = new Npdm(npdmFile.Get.AsStream());

                                            titleName = npdm.TitleName;
                                            titleId   = npdm.Aci0.TitleId.ToString("x16");
                                        }
                                    }
                                    else
                                    {
                                        GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId);

                                        // Check if there is an update available.
                                        if (IsUpdateApplied(titleId, out IFileSystem updatedControlFs))
                                        {
                                            // Replace the original ControlFs by the updated one.
                                            controlFs = updatedControlFs;
                                        }

                                        ReadControlData(controlFs, controlHolder.ByteSpan);

                                        GetGameInformation(ref controlHolder.Value, out titleName, out _, out developer, out version);

                                        // Read the icon from the ControlFS and store it as a byte array
                                        try
                                        {
                                            using var icon = new UniqueRef <IFile>();

                                            controlFs.OpenFile(ref icon.Ref(), $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                            using (MemoryStream stream = new MemoryStream())
                                            {
                                                icon.Get.AsStream().CopyTo(stream);
                                                applicationIcon = stream.ToArray();
                                            }
                                        }
                                        catch (HorizonResultException)
                                        {
                                            foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
                                            {
                                                if (entry.Name == "control.nacp")
                                                {
                                                    continue;
                                                }

                                                using var icon = new UniqueRef <IFile>();

                                                controlFs.OpenFile(ref icon.Ref(), entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                                using (MemoryStream stream = new MemoryStream())
                                                {
                                                    icon.Get.AsStream().CopyTo(stream);
                                                    applicationIcon = stream.ToArray();
                                                }

                                                if (applicationIcon != null)
                                                {
                                                    break;
                                                }
                                            }

                                            if (applicationIcon == null)
                                            {
                                                applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
                                            }
                                        }
                                    }
                                }
                                catch (MissingKeyException exception)
                                {
                                    applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;

                                    Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
                                }
                                catch (InvalidDataException)
                                {
                                    applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;

                                    Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}");
                                }
                                catch (Exception exception)
                                {
                                    Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}");

                                    numApplicationsFound--;

                                    continue;
                                }
                            }
                            else if (extension == ".nro")
                            {
                                BinaryReader reader = new BinaryReader(file);

                                byte[] Read(long position, int size)
                                {
                                    file.Seek(position, SeekOrigin.Begin);

                                    return(reader.ReadBytes(size));
                                }

                                try
                                {
                                    file.Seek(24, SeekOrigin.Begin);

                                    int assetOffset = reader.ReadInt32();

                                    if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
                                    {
                                        byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);

                                        long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
                                        long iconSize   = BitConverter.ToInt64(iconSectionInfo, 8);

                                        ulong nacpOffset = reader.ReadUInt64();
                                        ulong nacpSize   = reader.ReadUInt64();

                                        // Reads and stores game icon as byte array
                                        applicationIcon = Read(assetOffset + iconOffset, (int)iconSize);

                                        // Read the NACP data
                                        Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan);

                                        GetGameInformation(ref controlHolder.Value, out titleName, out titleId, out developer, out version);
                                    }
                                    else
                                    {
                                        applicationIcon = _nroIcon;
                                        titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                                    }
                                }
                                catch
                                {
                                    Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");

                                    numApplicationsFound--;

                                    continue;
                                }
                            }
                            else if (extension == ".nca")
                            {
                                try
                                {
                                    Nca nca       = new Nca(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage());
                                    int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);

                                    if (nca.Header.ContentType != NcaContentType.Program || (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()))
                                    {
                                        numApplicationsFound--;

                                        continue;
                                    }
                                }
                                catch (InvalidDataException)
                                {
                                    Logger.Warning?.Print(LogClass.Application, $"The NCA header content type check has failed. This is usually because the header key is incorrect or missing. Errored File: {applicationPath}");
                                }
                                catch
                                {
                                    Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");

                                    numApplicationsFound--;

                                    continue;
                                }

                                applicationIcon = _ncaIcon;
                                titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                            }
                            // If its an NSO we just set defaults
                            else if (extension == ".nso")
                            {
                                applicationIcon = _nsoIcon;
                                titleName       = Path.GetFileNameWithoutExtension(applicationPath);
                            }
                        }
                    }
                    catch (IOException exception)
                    {
                        Logger.Warning?.Print(LogClass.Application, exception.Message);

                        numApplicationsFound--;

                        continue;
                    }

                    ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId);

                    if (appMetadata.LastPlayed != "Never" && !DateTime.TryParse(appMetadata.LastPlayed, out _))
                    {
                        Logger.Warning?.Print(LogClass.Application, $"Last played datetime \"{appMetadata.LastPlayed}\" is invalid for current system culture, skipping (did current culture change?)");

                        appMetadata.LastPlayed = "Never";
                    }

                    ApplicationData data = new ApplicationData
                    {
                        Favorite      = appMetadata.Favorite,
                        Icon          = applicationIcon,
                        TitleName     = titleName,
                        TitleId       = titleId,
                        Developer     = developer,
                        Version       = version,
                        TimePlayed    = ConvertSecondsToReadableString(appMetadata.TimePlayed),
                        LastPlayed    = appMetadata.LastPlayed,
                        FileExtension = Path.GetExtension(applicationPath).ToUpper().Remove(0, 1),
                        FileSize      = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + "MB" : fileSize.ToString("0.##") + "GB",
                        Path          = applicationPath,
                        ControlHolder = controlHolder
                    };

                    numApplicationsLoaded++;

                    OnApplicationAdded(new ApplicationAddedEventArgs()
                    {
                        AppData = data
                    });

                    OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
                    {
                        NumAppsFound  = numApplicationsFound,
                        NumAppsLoaded = numApplicationsLoaded
                    });
                }

                OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs()
                {
                    NumAppsFound  = numApplicationsFound,
                    NumAppsLoaded = numApplicationsLoaded
                });
            }
            finally
            {
                _cancellationToken.Dispose();
                _cancellationToken = null;
            }
        }
示例#23
0
        public void LoadEntries()
        {
            _contentDictionary = new SortedDictionary <(ulong, NcaContentType), string>();

            foreach (StorageId storageId in Enum.GetValues(typeof(StorageId)))
            {
                string contentDirectory    = null;
                string contentPathString   = null;
                string registeredDirectory = null;

                try
                {
                    contentPathString   = LocationHelper.GetContentRoot(storageId);
                    contentDirectory    = LocationHelper.GetRealPath(_device.FileSystem, contentPathString);
                    registeredDirectory = Path.Combine(contentDirectory, "registered");
                }
                catch (NotSupportedException)
                {
                    continue;
                }

                Directory.CreateDirectory(registeredDirectory);

                LinkedList <LocationEntry> locationList = new LinkedList <LocationEntry>();

                void AddEntry(LocationEntry entry)
                {
                    locationList.AddLast(entry);
                }

                foreach (string directoryPath in Directory.EnumerateDirectories(registeredDirectory))
                {
                    if (Directory.GetFiles(directoryPath).Length > 0)
                    {
                        string ncaName = new DirectoryInfo(directoryPath).Name.Replace(".nca", string.Empty);

                        using (FileStream ncaFile = new FileStream(Directory.GetFiles(directoryPath)[0], FileMode.Open, FileAccess.Read))
                        {
                            Nca nca = new Nca(_device.System.KeySet, ncaFile.AsStorage());

                            string switchPath = contentPathString + ":/" + ncaFile.Name.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar);

                            // Change path format to switch's
                            switchPath = switchPath.Replace('\\', '/');

                            LocationEntry entry = new LocationEntry(switchPath,
                                                                    0,
                                                                    (long)nca.Header.TitleId,
                                                                    nca.Header.ContentType);

                            AddEntry(entry);

                            _contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName);
                        }
                    }
                }

                foreach (string filePath in Directory.EnumerateFiles(contentDirectory))
                {
                    if (Path.GetExtension(filePath) == ".nca")
                    {
                        string ncaName = Path.GetFileNameWithoutExtension(filePath);

                        using (FileStream ncaFile = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                        {
                            Nca nca = new Nca(_device.System.KeySet, ncaFile.AsStorage());

                            string switchPath = contentPathString + ":/" + filePath.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar);

                            // Change path format to switch's
                            switchPath = switchPath.Replace('\\', '/');

                            LocationEntry entry = new LocationEntry(switchPath,
                                                                    0,
                                                                    (long)nca.Header.TitleId,
                                                                    nca.Header.ContentType);

                            AddEntry(entry);

                            _contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName);
                        }
                    }
                }

                if (_locationEntries.ContainsKey(storageId) && _locationEntries[storageId]?.Count == 0)
                {
                    _locationEntries.Remove(storageId);
                }

                if (!_locationEntries.ContainsKey(storageId))
                {
                    _locationEntries.Add(storageId, locationList);
                }
            }

            TimeManager.Instance.InitializeTimeZone(_device);
        }
示例#24
0
        public static void Process(Context ctx)
        {
            using (var file = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read))
            {
                var xci = new Xci(ctx.Keyset, file.AsStorage());

                ctx.Logger.LogMessage(xci.Print());

                if (ctx.Options.RootDir != null)
                {
                    xci.RootPartition?.Extract(ctx.Options.RootDir, ctx.Logger);
                }

                if (ctx.Options.UpdateDir != null)
                {
                    xci.UpdatePartition?.Extract(ctx.Options.UpdateDir, ctx.Logger);
                }

                if (ctx.Options.NormalDir != null)
                {
                    xci.NormalPartition?.Extract(ctx.Options.NormalDir, ctx.Logger);
                }

                if (ctx.Options.SecureDir != null)
                {
                    xci.SecurePartition?.Extract(ctx.Options.SecureDir, ctx.Logger);
                }

                if (ctx.Options.LogoDir != null)
                {
                    xci.LogoPartition?.Extract(ctx.Options.LogoDir, ctx.Logger);
                }

                if (ctx.Options.OutDir != null && xci.RootPartition != null)
                {
                    XciPartition root = xci.RootPartition;
                    if (root == null)
                    {
                        ctx.Logger.LogMessage("Could not find root partition");
                        return;
                    }

                    foreach (PfsFileEntry sub in root.Files)
                    {
                        var    subPfs = new Pfs(root.OpenFile(sub));
                        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 Romfs(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);
                    }
                }
            }
        }
示例#25
0
        private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetObject("_dlcWindow").Handle)
        {
            builder.Autoconnect(this);

            _titleId                 = titleId;
            _virtualFileSystem       = virtualFileSystem;
            _dlcJsonPath             = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "dlc.json");
            _baseTitleInfoLabel.Text = $"DLC Available for {titleName} [{titleId.ToUpper()}]";

            try
            {
                _dlcContainerList = JsonHelper.DeserializeFromFile <List <DlcContainer> >(_dlcJsonPath);
            }
            catch
            {
                _dlcContainerList = new List <DlcContainer>();
            }

            _dlcTreeView.Model = new TreeStore(typeof(bool), typeof(string), typeof(string));

            CellRendererToggle enableToggle = new CellRendererToggle();

            enableToggle.Toggled += (sender, args) =>
            {
                _dlcTreeView.Model.GetIter(out TreeIter treeIter, new TreePath(args.Path));
                bool newValue = !(bool)_dlcTreeView.Model.GetValue(treeIter, 0);
                _dlcTreeView.Model.SetValue(treeIter, 0, newValue);

                if (_dlcTreeView.Model.IterChildren(out TreeIter childIter, treeIter))
                {
                    do
                    {
                        _dlcTreeView.Model.SetValue(childIter, 0, newValue);
                    }while (_dlcTreeView.Model.IterNext(ref childIter));
                }
            };

            _dlcTreeView.AppendColumn("Enabled", enableToggle, "active", 0);
            _dlcTreeView.AppendColumn("TitleId", new CellRendererText(), "text", 1);
            _dlcTreeView.AppendColumn("Path", new CellRendererText(), "text", 2);

            foreach (DlcContainer dlcContainer in _dlcContainerList)
            {
                if (File.Exists(dlcContainer.Path))
                {
                    // The parent tree item has its own "enabled" check box, but it's the actual
                    // nca entries that store the enabled / disabled state. A bit of a UI inconsistency.
                    // Maybe a tri-state check box would be better, but for now we check the parent
                    // "enabled" box if all child NCAs are enabled. Usually fine since each nsp has only one nca.
                    bool     areAllContentPacksEnabled = dlcContainer.DlcNcaList.TrueForAll((nca) => nca.Enabled);
                    TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(areAllContentPacksEnabled, "", dlcContainer.Path);
                    using FileStream containerFile = File.OpenRead(dlcContainer.Path);
                    PartitionFileSystem pfs = new PartitionFileSystem(containerFile.AsStorage());
                    _virtualFileSystem.ImportTickets(pfs);

                    foreach (DlcNca dlcNca in dlcContainer.DlcNcaList)
                    {
                        using var ncaFile = new UniqueRef <IFile>();

                        pfs.OpenFile(ref ncaFile.Ref(), dlcNca.Path.ToU8Span(), OpenMode.Read).ThrowIfFailure();
                        Nca nca = TryCreateNca(ncaFile.Get.AsStorage(), dlcContainer.Path);

                        if (nca != null)
                        {
                            ((TreeStore)_dlcTreeView.Model).AppendValues(parentIter, dlcNca.Enabled, nca.Header.TitleId.ToString("X16"), dlcNca.Path);
                        }
                    }
                }
                else
                {
                    // DLC file moved or renamed. Allow the user to remove it without crashing the whole dialog.
                    TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(false, "", $"(MISSING) {dlcContainer.Path}");
                }
            }
        }
示例#26
0
        public static Title processXci(string filename)
        {
            Title title = new Title();

            using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                Xci    xci;
                string biggestNca = null, controlNca = null;

                try
                {
                    xci = new Xci(keyset, filestream.AsStorage());

                    title.distribution = Title.Distribution.Cartridge;

                    log?.WriteLine("Processing XCI {0}", filename);

                    if (xci.RootPartition?.Files.Length > 0)
                    {
                        title.structure.Add(Title.Structure.RootPartition);
                    }

                    if (xci.UpdatePartition?.Files.Length > 0)
                    {
                        PfsFileEntry[] fileEntries = xci.UpdatePartition.Files;

                        List <string> cnmtNca = fileEntries.Select(x => x.Name).Where(x => x.EndsWith(".cnmt.nca")).Intersect(Title.SystemUpdate.Keys).ToList();
                        if (cnmtNca.Any())
                        {
                            uint systemUpdate = unchecked ((uint)-1);
                            Title.SystemUpdate.TryGetValue(cnmtNca.First(), out systemUpdate);
                            title.systemUpdate = systemUpdate;
                        }

                        title.structure.Add(Title.Structure.UpdatePartition);
                    }

                    if (xci.NormalPartition?.Files.Length > 0)
                    {
                        title.structure.Add(Title.Structure.NormalPartition);
                    }

                    if (xci.SecurePartition?.Files.Length > 0)
                    {
                        PfsFileEntry[] fileEntries = xci.SecurePartition.Files;
                        foreach (PfsFileEntry entry in fileEntries)
                        {
                            if (entry.Name.EndsWith(".cnmt.nca"))
                            {
                                try
                                {
                                    using (var cnmtNca = xci.SecurePartition.OpenFile(entry))
                                    {
                                        var nca = processCnmtNca(cnmtNca, ref title);
                                        if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent))
                                        {
                                            (biggestNca, controlNca) = nca;
                                        }
                                    }
                                }
                                catch (FileNotFoundException)
                                {
                                    if (xci.SecurePartition.FileExists(entry.Name.Replace(".nca", ".ncz")))
                                    {
                                        title.error = "Unsupported Format: Compressed NCA";
                                    }
                                }

                                title.structure.Add(Title.Structure.CnmtNca);
                            }
                            else if (entry.Name.EndsWith(".cert"))
                            {
                                title.structure.Add(Title.Structure.Cert);
                            }
                            else if (entry.Name.EndsWith(".tik"))
                            {
                                try
                                {
                                    using (var tik = xci.SecurePartition.OpenFile(entry))
                                    {
                                        if (entry.Name.Split('.')[0].TryToBytes(out byte[] rightsId))
                                        {
                                            processTik(tik, rightsId, ref keyset, out byte[] titleKey);

                                            title.titleKey = BitConverter.ToString(titleKey).Replace("-", "").ToUpper();
                                        }
                                    }
                                }
                                catch (FileNotFoundException)
                                {
                                    if (xci.SecurePartition.FileExists(entry.Name.Replace(".nca", ".ncz")))
                                    {
                                        title.error = "Unsupported Format: Compressed NCA";
                                    }
                                }

                                title.structure.Add(Title.Structure.Tik);
                            }
                        }

                        if (!String.IsNullOrEmpty(biggestNca))
                        {
                            try
                            {
                                using (var biggest = xci.SecurePartition.OpenFile(biggestNca))
                                {
                                    processBiggestNca(biggest, ref title);
                                }
                            }
                            catch (FileNotFoundException)
                            {
                                if (xci.SecurePartition.FileExists(biggestNca.Replace(".nca", ".ncz")))
                                {
                                    title.error = "Unsupported Format: Compressed NCA";
                                }
                            }
                        }

                        if (!String.IsNullOrEmpty(controlNca))
                        {
                            try
                            {
                                using (var control = xci.SecurePartition.OpenFile(controlNca))
                                {
                                    processControlNca(control, ref title);
                                }
                            }
                            catch (FileNotFoundException)
                            {
                                if (xci.SecurePartition.FileExists(controlNca.Replace(".nca", ".ncz")))
                                {
                                    title.error = "Unsupported Format: Compressed NCA";
                                }
                            }
                        }

                        title.structure.Add(Title.Structure.SecurePartition);
                    }

                    if (xci.LogoPartition?.Files.Length > 0)
                    {
                        title.structure.Add(Title.Structure.LogoPartition);
                    }
                }
                catch (InvalidDataException)
                {
                    return(null);
                }
            }

            if (title.type == TitleType.Application || title.type == TitleType.Patch)
            {
                if (versionList.TryGetValue(title.baseTitleID, out uint version))
                {
                    title.latestVersion = version;
                }
            }

            log?.WriteLine("XCI information for {0}: [{1}] {2}", filename, title.titleID, title.titleName);

            return(title);
        }
示例#27
0
        private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetObject("_dlcWindow").Handle)
        {
            builder.Autoconnect(this);

            _titleId                 = titleId;
            _virtualFileSystem       = virtualFileSystem;
            _dlcJsonPath             = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "dlc.json");
            _baseTitleInfoLabel.Text = $"DLC Available for {titleName} [{titleId.ToUpper()}]";

            try
            {
                _dlcContainerList = JsonHelper.DeserializeFromFile <List <DlcContainer> >(_dlcJsonPath);
            }
            catch
            {
                _dlcContainerList = new List <DlcContainer>();
            }

            _dlcTreeView.Model = new TreeStore(typeof(bool), typeof(string), typeof(string));

            CellRendererToggle enableToggle = new CellRendererToggle();

            enableToggle.Toggled += (sender, args) =>
            {
                _dlcTreeView.Model.GetIter(out TreeIter treeIter, new TreePath(args.Path));
                bool newValue = !(bool)_dlcTreeView.Model.GetValue(treeIter, 0);
                _dlcTreeView.Model.SetValue(treeIter, 0, newValue);

                if (_dlcTreeView.Model.IterChildren(out TreeIter childIter, treeIter))
                {
                    do
                    {
                        _dlcTreeView.Model.SetValue(childIter, 0, newValue);
                    }while (_dlcTreeView.Model.IterNext(ref childIter));
                }
            };

            _dlcTreeView.AppendColumn("Enabled", enableToggle, "active", 0);
            _dlcTreeView.AppendColumn("TitleId", new CellRendererText(), "text", 1);
            _dlcTreeView.AppendColumn("Path", new CellRendererText(), "text", 2);

            foreach (DlcContainer dlcContainer in _dlcContainerList)
            {
                TreeIter parentIter = ((TreeStore)_dlcTreeView.Model).AppendValues(false, "", dlcContainer.Path);

                using FileStream containerFile = File.OpenRead(dlcContainer.Path);
                PartitionFileSystem pfs = new PartitionFileSystem(containerFile.AsStorage());
                _virtualFileSystem.ImportTickets(pfs);

                foreach (DlcNca dlcNca in dlcContainer.DlcNcaList)
                {
                    pfs.OpenFile(out IFile ncaFile, dlcNca.Path.ToU8Span(), OpenMode.Read).ThrowIfFailure();
                    Nca nca = TryCreateNca(ncaFile.AsStorage(), dlcContainer.Path);

                    if (nca != null)
                    {
                        ((TreeStore)_dlcTreeView.Model).AppendValues(parentIter, dlcNca.Enabled, nca.Header.TitleId.ToString("X16"), dlcNca.Path);
                    }
                }
            }
        }
示例#28
0
        public static Title processNsp(string filename)
        {
            Title title = new Title();

            using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                Pfs    pfs;
                string biggestNca = null, controlNca = null;

                try
                {
                    pfs = new Pfs(filestream.AsStorage());

                    title.distribution = Title.Distribution.Digital;

                    log?.WriteLine("Processing NSP {0}", filename);

                    PfsFileEntry[] fileEntries = pfs.Files;
                    foreach (PfsFileEntry entry in fileEntries)
                    {
                        if (entry.Name.EndsWith(".cnmt.xml"))
                        {
                            try
                            {
                                using (var cnmtXml = pfs.OpenFile(entry))
                                {
                                    (biggestNca, controlNca) = processCnmtXml(cnmtXml, ref title);
                                }
                            }
                            catch (FileNotFoundException) { }

                            title.structure.Add(Title.Structure.CnmtXml);
                        }
                        else if (entry.Name.EndsWith(".cnmt.nca"))
                        {
                            try
                            {
                                using (var cnmtNca = pfs.OpenFile(entry))
                                {
                                    var nca = processCnmtNca(cnmtNca, ref title);
                                    if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent))
                                    {
                                        (biggestNca, controlNca) = nca;
                                    }
                                }
                            }
                            catch (FileNotFoundException)
                            {
                                if (pfs.FileExists(entry.Name.Replace(".nca", ".ncz")))
                                {
                                    title.error = "Unsupported Format: Compressed NCA";
                                }
                            }

                            title.structure.Add(Title.Structure.CnmtNca);
                        }
                        else if (entry.Name.EndsWith(".cert"))
                        {
                            title.structure.Add(Title.Structure.Cert);
                        }
                        else if (entry.Name.EndsWith(".tik"))
                        {
                            try
                            {
                                using (var tik = pfs.OpenFile(entry))
                                {
                                    if (entry.Name.Split('.')[0].TryToBytes(out byte[] rightsId))
                                    {
                                        processTik(tik, rightsId, ref keyset, out byte[] titleKey);

                                        title.titleKey = BitConverter.ToString(titleKey).Replace("-", "").ToUpper();
                                    }
                                }
                            }
                            catch (FileNotFoundException)
                            {
                                if (pfs.FileExists(entry.Name.Replace(".nca", ".ncz")))
                                {
                                    title.error = "Unsupported Format: Compressed NCA";
                                }
                            }

                            title.structure.Add(Title.Structure.Tik);
                        }
                        else if (entry.Name.EndsWith(".legalinfo.xml"))
                        {
                            title.structure.Add(Title.Structure.LegalinfoXml);
                        }
                        else if (entry.Name.EndsWith(".nacp.xml"))
                        {
                            try
                            {
                                using (var nacpXml = pfs.OpenFile(entry))
                                {
                                    processNacpXml(nacpXml, ref title);
                                }
                            }
                            catch (FileNotFoundException) { }

                            title.structure.Add(Title.Structure.NacpXml);
                        }
                        else if (entry.Name.EndsWith(".programinfo.xml"))
                        {
                            title.structure.Add(Title.Structure.PrograminfoXml);
                        }
                        else if (entry.Name.Equals("cardspec.xml"))
                        {
                            title.structure.Add(Title.Structure.CardspecXml);
                        }
                        else if (entry.Name.Equals("authoringtoolinfo.xml"))
                        {
                            title.structure.Add(Title.Structure.AuthoringtoolinfoXml);
                        }
                    }

                    if (!String.IsNullOrEmpty(biggestNca))
                    {
                        try
                        {
                            using (var biggest = pfs.OpenFile(biggestNca))
                            {
                                processBiggestNca(biggest, ref title);
                            }
                        }
                        catch (FileNotFoundException)
                        {
                            if (pfs.FileExists(biggestNca.Replace(".nca", ".ncz")))
                            {
                                title.error = "Unsupported Format: Compressed NCA";
                            }
                        }
                    }

                    if (!String.IsNullOrEmpty(controlNca))
                    {
                        try
                        {
                            using (var control = pfs.OpenFile(controlNca))
                            {
                                processControlNca(control, ref title);
                            }
                        }
                        catch (FileNotFoundException)
                        {
                            if (pfs.FileExists(controlNca.Replace(".nca", ".ncz")))
                            {
                                title.error = "Unsupported Format: Compressed NCA";
                            }
                        }
                    }
                }
                catch (InvalidDataException)
                {
                    return(null);
                }
            }

            if (title.type == TitleType.Application || title.type == TitleType.Patch)
            {
                if (versionList.TryGetValue(title.baseTitleID, out uint version))
                {
                    title.latestVersion = version;
                }
            }

            log?.WriteLine("NSP information for {0}: [{1}] {2}", filename, title.titleID, title.titleName);

            return(title);
        }
示例#29
0
        private void ExtractSection(NcaSectionType ncaSectionType)
        {
            FileChooserDialog fileChooser = new FileChooserDialog("Choose the folder to extract into", null, FileChooserAction.SelectFolder, "Cancel", ResponseType.Cancel, "Extract", ResponseType.Accept);

            fileChooser.SetPosition(WindowPosition.Center);

            int    response    = fileChooser.Run();
            string destination = fileChooser.Filename;

            fileChooser.Dispose();

            if (response == (int)ResponseType.Accept)
            {
                Thread extractorThread = new Thread(() =>
                {
                    string sourceFile = _gameTableStore.GetValue(_rowIter, 9).ToString();

                    Gtk.Application.Invoke(delegate
                    {
                        _dialog = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Cancel, null)
                        {
                            Title          = "Ryujinx - NCA Section Extractor",
                            Icon           = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"),
                            SecondaryText  = $"Extracting {ncaSectionType} section from {System.IO.Path.GetFileName(sourceFile)}...",
                            WindowPosition = WindowPosition.Center
                        };

                        int dialogResponse = _dialog.Run();
                        if (dialogResponse == (int)ResponseType.Cancel || dialogResponse == (int)ResponseType.DeleteEvent)
                        {
                            _cancel = true;
                            _dialog.Dispose();
                        }
                    });

                    using (FileStream file = new FileStream(sourceFile, FileMode.Open, FileAccess.Read))
                    {
                        Nca mainNca  = null;
                        Nca patchNca = null;

                        if ((System.IO.Path.GetExtension(sourceFile).ToLower() == ".nsp") ||
                            (System.IO.Path.GetExtension(sourceFile).ToLower() == ".pfs0") ||
                            (System.IO.Path.GetExtension(sourceFile).ToLower() == ".xci"))
                        {
                            PartitionFileSystem pfs;

                            if (System.IO.Path.GetExtension(sourceFile) == ".xci")
                            {
                                Xci xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage());

                                pfs = xci.OpenPartition(XciPartitionType.Secure);
                            }
                            else
                            {
                                pfs = new PartitionFileSystem(file.AsStorage());
                            }

                            foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
                            {
                                pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());

                                if (nca.Header.ContentType == NcaContentType.Program)
                                {
                                    int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);

                                    if (nca.Header.GetFsHeader(dataIndex).IsPatchSection())
                                    {
                                        patchNca = nca;
                                    }
                                    else
                                    {
                                        mainNca = nca;
                                    }
                                }
                            }
                        }
                        else if (System.IO.Path.GetExtension(sourceFile).ToLower() == ".nca")
                        {
                            mainNca = new Nca(_virtualFileSystem.KeySet, file.AsStorage());
                        }

                        if (mainNca == null)
                        {
                            Logger.PrintError(LogClass.Application, "Extraction failed. The main NCA was not present in the selected file.");

                            Gtk.Application.Invoke(delegate
                            {
                                GtkDialog.CreateErrorDialog("Extraction failed. The main NCA was not present in the selected file.");
                            });

                            return;
                        }

                        int index = Nca.GetSectionIndexFromType(ncaSectionType, mainNca.Header.ContentType);

                        IFileSystem ncaFileSystem = patchNca != null ? mainNca.OpenFileSystemWithPatch(patchNca, index, IntegrityCheckLevel.ErrorOnInvalid)
                                                                     : mainNca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid);

                        FileSystemClient fsClient = _virtualFileSystem.FsClient;

                        string source = DateTime.Now.ToFileTime().ToString().Substring(10);
                        string output = DateTime.Now.ToFileTime().ToString().Substring(10);

                        fsClient.Register(source.ToU8Span(), ncaFileSystem);
                        fsClient.Register(output.ToU8Span(), new LocalFileSystem(destination));

                        (Result? resultCode, bool canceled) = CopyDirectory(fsClient, $"{source}:/", $"{output}:/");

                        if (!canceled)
                        {
                            if (resultCode.Value.IsFailure())
                            {
                                Logger.PrintError(LogClass.Application, $"LibHac returned error code: {resultCode.Value.ErrorCode}");

                                Gtk.Application.Invoke(delegate
                                {
                                    _dialog?.Dispose();

                                    GtkDialog.CreateErrorDialog("Extraction failed. Read the log file for further information.");
                                });
                            }
                            else if (resultCode.Value.IsSuccess())
                            {
                                Gtk.Application.Invoke(delegate
                                {
                                    _dialog?.Dispose();

                                    MessageDialog dialog = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, null)
                                    {
                                        Title          = "Ryujinx - NCA Section Extractor",
                                        Icon           = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"),
                                        SecondaryText  = "Extraction has completed successfully.",
                                        WindowPosition = WindowPosition.Center
                                    };

                                    dialog.Run();
                                    dialog.Dispose();
                                });
                            }
                        }

                        fsClient.Unmount(source.ToU8Span());
                        fsClient.Unmount(output.ToU8Span());
                    }
                });

                extractorThread.Name         = "GUI.NcaSectionExtractorThread";
                extractorThread.IsBackground = true;
                extractorThread.Start();
            }
        }
示例#30
0
        public byte[] GetApplicationIcon(string applicationPath)
        {
            byte[] applicationIcon = null;

            try
            {
                // Look for icon only if applicationPath is not a directory
                if (!Directory.Exists(applicationPath))
                {
                    string extension = Path.GetExtension(applicationPath).ToLower();

                    using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read))
                    {
                        if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
                        {
                            try
                            {
                                PartitionFileSystem pfs;

                                bool isExeFs = false;

                                if (extension == ".xci")
                                {
                                    Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage());

                                    pfs = xci.OpenPartition(XciPartitionType.Secure);
                                }
                                else
                                {
                                    pfs = new PartitionFileSystem(file.AsStorage());

                                    foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
                                    {
                                        if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
                                        {
                                            isExeFs = true;
                                        }
                                    }
                                }

                                if (isExeFs)
                                {
                                    applicationIcon = _nspIcon;
                                }
                                else
                                {
                                    // Store the ControlFS in variable called controlFs
                                    GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out _);

                                    // Read the icon from the ControlFS and store it as a byte array
                                    try
                                    {
                                        using var icon = new UniqueRef <IFile>();

                                        controlFs.OpenFile(ref icon.Ref(), $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                        using (MemoryStream stream = new MemoryStream())
                                        {
                                            icon.Get.AsStream().CopyTo(stream);
                                            applicationIcon = stream.ToArray();
                                        }
                                    }
                                    catch (HorizonResultException)
                                    {
                                        foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
                                        {
                                            if (entry.Name == "control.nacp")
                                            {
                                                continue;
                                            }

                                            using var icon = new UniqueRef <IFile>();

                                            controlFs.OpenFile(ref icon.Ref(), entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                                            using (MemoryStream stream = new MemoryStream())
                                            {
                                                icon.Get.AsStream().CopyTo(stream);
                                                applicationIcon = stream.ToArray();
                                            }

                                            if (applicationIcon != null)
                                            {
                                                break;
                                            }
                                        }

                                        if (applicationIcon == null)
                                        {
                                            applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon;
                                        }
                                    }
                                }
                            }
                            catch (MissingKeyException)
                            {
                                applicationIcon = extension == ".xci"
                                    ? _xciIcon
                                    : _nspIcon;
                            }
                            catch (InvalidDataException)
                            {
                                applicationIcon = extension == ".xci"
                                    ? _xciIcon
                                    : _nspIcon;
                            }
                            catch (Exception exception)
                            {
                                Logger.Warning?.Print(LogClass.Application,
                                                      $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}");
                            }
                        }
                        else if (extension == ".nro")
                        {
                            BinaryReader reader = new(file);

                            byte[] Read(long position, int size)
                            {
                                file.Seek(position, SeekOrigin.Begin);

                                return(reader.ReadBytes(size));
                            }

                            try
                            {
                                file.Seek(24, SeekOrigin.Begin);

                                int assetOffset = reader.ReadInt32();

                                if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
                                {
                                    byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);

                                    long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
                                    long iconSize   = BitConverter.ToInt64(iconSectionInfo, 8);

                                    // Reads and stores game icon as byte array
                                    applicationIcon = Read(assetOffset + iconOffset, (int)iconSize);
                                }
                                else
                                {
                                    applicationIcon = _nroIcon;
                                }
                            }
                            catch
                            {
                                Logger.Warning?.Print(LogClass.Application,
                                                      $"The file encountered was not of a valid type. Errored File: {applicationPath}");
                            }
                        }
                        else if (extension == ".nca")
                        {
                            applicationIcon = _ncaIcon;
                        }
                        // If its an NSO we just set defaults
                        else if (extension == ".nso")
                        {
                            applicationIcon = _nsoIcon;
                        }
                    }
                }
            }
            catch (Exception)
            {
                Logger.Warning?.Print(LogClass.Application,
                                      $"Could not retrieve a valid icon for the app. Default icon will be used. Errored File: {applicationPath}");
            }

            return(applicationIcon ?? _ncaIcon);
        }